Hallo allemaal, we delen met jullie het tweede deel van de publicatie "Virtuele bestandssystemen in Linux: waarom zijn ze nodig en hoe werken ze?" Je kunt het eerste deel lezen
Hoe VFS te monitoren met behulp van eBPF- en bcc-tools
De eenvoudigste manier om te begrijpen hoe de kernel op bestanden werkt sysfs
is om het in de praktijk te zien, en de gemakkelijkste manier om ARM64 te bekijken is door eBPF te gebruiken. eBPF (afkorting van Berkeley Packet Filter) bestaat uit een virtuele machine die wordt uitgevoerd query
) vanaf de opdrachtregel. De kernelbronnen vertellen de lezer wat de kernel kan doen; het uitvoeren van de eBPF-tools op een geladen systeem laat zien wat de kernel feitelijk doet.
Gelukkig is het vrij eenvoudig om met behulp van hulpmiddelen aan de slag te gaan met eBPF bcc
zijn Python-scripts met kleine toevoegingen van C-code, wat betekent dat iedereen die bekend is met beide talen deze gemakkelijk kan aanpassen. IN bcc/tools
Er zijn 80 Python-scripts, wat betekent dat een ontwikkelaar of systeembeheerder hoogstwaarschijnlijk iets kan kiezen dat geschikt is om het probleem op te lossen.
Probeer het eens om op zijn minst een oppervlakkig idee te krijgen van wat VFS'en doen op een draaiend systeem vfscount
of vfsstat
. Hieruit zullen, laten we zeggen, tientallen telefoontjes blijken vfs_open()
en “zijn vrienden” gebeuren letterlijk elke seconde.
vfsstat.py
is een Python-script met C-code-invoegingen dat eenvoudigweg VFS-functieaanroepen telt.
Laten we een trivialer voorbeeld geven en kijken wat er gebeurt als we een USB-flashstation in een computer steken en het systeem dit detecteert.
Met behulp van eBPF kunt u zien wat er gebeurt
/sys
wanneer er een USB-flashstation is geplaatst. Een eenvoudig en complex voorbeeld wordt hier getoond.
In het hierboven getoonde voorbeeld is bcc
инструмент sysfs_create_files()
. We zien dat sysfs_create_files()
werd gelanceerd met behulp van kworker
stream als reactie op het feit dat de flashdrive is geplaatst, maar welk bestand is gemaakt? Het tweede voorbeeld toont de kracht van eBPF. Hier trace.py
Drukt een kernel-backtrace af (optie -K) en de naam van het bestand dat is gemaakt sysfs_create_files()
. Het invoegen van een enkele instructie is C-code die een gemakkelijk herkenbare formatstring bevat die wordt geleverd door het Python-script dat LLVM uitvoert just-in-time-compiler. Het compileert deze regel en voert deze uit op een virtuele machine in de kernel. Volledig functionele handtekening sysfs_create_files ()
moet in het tweede commando worden gereproduceerd, zodat de formatstring naar een van de parameters kan verwijzen. Fouten in dit stukje C-code resulteren in herkenbare fouten van de C-compiler. Als de parameter -l bijvoorbeeld wordt weggelaten, ziet u 'Kan BPF-tekst niet compileren'. Ontwikkelaars die bekend zijn met C en Python zullen de tools vinden bcc
eenvoudig uit te breiden en te wijzigen.
Wanneer de USB-drive wordt geplaatst, zal de kernel-backtrace laten zien dat PID 7711 een thread is kworker
die het bestand heeft gemaakt «events»
в sysfs
. Dienovereenkomstig, de oproep van sysfs_remove_files()
zal laten zien dat het verwijderen van de schijf resulteerde in het verwijderen van het bestand events
, wat overeenkomt met het algemene concept van referentietelling. Tegelijkertijd kijken sysfs_create_link ()
met eBPF terwijl u de USB-stick plaatst, zal laten zien dat er minstens 48 symbolische links zijn gemaakt.
Dus wat is het nut van het evenementenbestand? Gebruik disk_add_events ()
, en ook "media_change"
Of "eject_request"
kan worden vastgelegd in een gebeurtenisbestand. Hier informeert de kernelbloklaag de gebruikersruimte dat er een "schijf" is verschenen en uitgeworpen. Merk op hoe informatief deze onderzoeksmethode is door het plaatsen van een USB-stick, vergeleken met proberen uit te zoeken hoe dingen puur vanaf de bron werken.
Alleen-lezen rootbestandssystemen maken ingebedde apparaten mogelijk
Natuurlijk zet niemand de server of zijn computer uit door de stekker uit het stopcontact te trekken. Maar waarom? Dit komt omdat aangekoppelde bestandssystemen op fysieke opslagapparaten mogelijk vertraagde schrijfbewerkingen hebben, en de datastructuren die hun status registreren mogelijk niet gesynchroniseerd zijn met schrijfbewerkingen naar de opslag. Wanneer dit gebeurt, moeten systeemeigenaren wachten tot de volgende keer opstarten voordat het hulpprogramma wordt gestart. fsck filesystem-recovery
en, in het ergste geval, gegevensverlies.
We weten echter allemaal dat veel IoT-apparaten, maar ook routers, thermostaten en auto's, nu op Linux draaien. Veel van deze apparaten hebben weinig tot geen gebruikersinterface en er is geen manier om ze 'schoon' uit te schakelen. Stel je voor dat je een auto start met een lege accu terwijl er stroom naar de besturingseenheid is fsck
wanneer begint de motor eindelijk te draaien? En het antwoord is simpel. Ingebouwde apparaten zijn afhankelijk van het rootbestandssysteem ro-rootfs
(alleen-lezen rootbestandssysteem)).
ro-rootfs
bieden veel voordelen die minder voor de hand liggend zijn dan authenticiteit. Een voordeel is dat malware er niet naar kan schrijven /usr
of /lib
, als geen enkel Linux-proces daar kan schrijven. Een andere is dat een grotendeels onveranderlijk bestandssysteem van cruciaal belang is voor veldondersteuning van externe apparaten, aangezien ondersteunend personeel afhankelijk is van lokale systemen die nominaal identiek zijn aan de veldsystemen. Misschien wel het belangrijkste (maar ook meest verraderlijke) voordeel is dat ro-rootfs ontwikkelaars dwingt om te beslissen welke systeemobjecten onveranderlijk zullen zijn in de ontwerpfase van het systeem. Werken met ro-rootfs kan lastig en pijnlijk zijn, omdat const-variabelen vaak in programmeertalen voorkomen, maar hun voordelen rechtvaardigen gemakkelijk de extra overhead.
schepping rootfs
Alleen-lezen vereist wat extra inspanning voor embedded-ontwikkelaars, en dit is waar VFS in beeld komt. Linux vereist dat er bestanden aanwezig zijn /var
waren beschrijfbaar, en bovendien zullen veel populaire applicaties die ingebedde systemen draaien proberen configuraties te creëren dot-files
в $HOME
. Eén oplossing voor configuratiebestanden in de homedirectory is meestal om ze vooraf te genereren en in te bouwen rootfs
. Voor /var
Een mogelijke aanpak is om het op een afzonderlijke beschrijfbare partitie te plaatsen /
alleen-lezen gemonteerd. Een ander populair alternatief is het gebruik van bind- of overlay-mounts.
Koppelbare en stapelbare steunen, hun gebruik door containers
Opdracht uitvoering man mount
is de beste manier om meer te leren over bindbare en overlaybare mounts, die ontwikkelaars en systeembeheerders de mogelijkheid geven om een bestandssysteem in het ene pad te creëren en dit vervolgens bloot te stellen aan toepassingen in een ander pad. Voor embedded systemen betekent dit de mogelijkheid om bestanden op te slaan /var
op een alleen-lezen flashdrive, maar een overlay of koppelbaar koppelpad van tmpfs
в /var
tijdens het laden kunnen toepassingen daar aantekeningen schrijven (scrawlen). De volgende keer dat u de wijzigingen inschakelt /var
zal verloren gaan. Een overlay-montage creëert een verbinding tussen tmpfs
en het onderliggende bestandssysteem en stelt u in staat ogenschijnlijke wijzigingen aan te brengen in bestaande bestanden in ro-tootf
terwijl een bindbare houder nieuwe leeg kan maken tmpfs
mappen zichtbaar als beschrijfbaar ro-rootfs
manieren. Terwijl overlayfs
dit is de juiste (proper
) bestandssysteemtype, bindbare mount is geïmplementeerd
Afgaande op de beschrijving van de overlay en koppelbare houder is daar niemand verbaasd over mountsnoop
van bcc
.
telefoontje system-nspawn
start de container terwijl deze draait mountsnoop.py
.
Laten we eens kijken wat er gebeurd is:
lancering mountsnoop
terwijl de container aan het "opstarten" is, blijkt dat de runtime van de container sterk afhankelijk is van de gekoppelde mount (alleen het begin van de lange uitvoer wordt getoond).
Hier systemd-nspawn
levert geselecteerde bestanden in procfs
и sysfs
host naar container als paden ernaartoe rootfs
... Trouwens MS_BIND
flag die de bindende mount instelt, definiëren enkele andere vlaggen op de mount de relatie tussen wijzigingen in de host- en containernaamruimten. Een gekoppelde koppeling kan bijvoorbeeld wijzigingen overslaan naar /proc
и /sys
in de container of verberg ze, afhankelijk van de oproep.
Conclusie
Het begrijpen van de innerlijke werking van Linux kan een onmogelijke taak lijken, omdat de kernel zelf een enorme hoeveelheid code bevat, afgezien van Linux-gebruikersruimtetoepassingen en systeemaanroepinterfaces in C-bibliotheken zoals glibc
. Eén manier om vooruitgang te boeken is door de broncode van één kernelsubsysteem te lezen, met de nadruk op het begrijpen van systeemaanroepen en headers van de gebruikersruimte, evenals de belangrijkste interne kernelinterfaces, zoals tabel file_operations
. Bestandsbewerkingen maken gebruik van het principe 'alles is een bestand', waardoor ze bijzonder prettig te beheren zijn. C-kernelbronbestanden in de map op het hoogste niveau fs/
presenteren een implementatie van virtuele bestandssystemen, die een wrapper-laag vormen die een brede en relatief eenvoudige compatibiliteit biedt tussen populaire bestandssystemen en opslagapparaten. Het koppelen en overlay-mounten via Linux-naamruimten is de magie van VFS die het creëren van alleen-lezen containers en rootbestandssystemen mogelijk maakt. Gecombineerd met een onderzoek van de broncode, de eBPF-kerntool en de interface ervan bcc
waardoor kernverkenning eenvoudiger dan ooit wordt.
Vrienden, schrijf, was dit artikel nuttig voor u? Heeft u wellicht op- of aanmerkingen? En degenen die geïnteresseerd zijn in de Linux Administrator-cursus zijn uitgenodigd
Bron: www.habr.com