Sistemi di file virtuali in Linux: a cosa servono e come funzionano? Parte 2

Ciao a tutti, condividiamo con voi la seconda parte della pubblicazione "Sistemi di file virtuali in Linux: perché sono necessari e come funzionano?" È possibile leggere la prima parte qui. Ricordiamo che questa serie di pubblicazioni è dedicata al lancio di un nuovo ciclo del corso «Amministratore Linux», che inizierà molto presto.

Come osservare VFS usando strumenti eBPF e bcc

Il modo più semplice per capire come il kernel gestisce i file sysfs è osservare tutto ciò nella pratica, e il modo più semplice per osservare ARM64 è utilizzare eBPF. eBPF (acronimo di Berkeley Packet Filter) consiste in una macchina virtuale che viene eseguita nel kernel, che gli utenti privilegiati possono richiedere (query) dalla riga di comando. Il codice sorgente del kernel informa il lettore su cosa può fare il kernel; eseguire strumenti eBPF in un sistema in funzione mostra cosa fa realmente il kernel.

Sistemi di file virtuali in Linux: a cosa servono e come funzionano? Parte 2

Fortunatamente, iniziare a usare eBPF è piuttosto semplice grazie agli strumenti bcc, che sono disponibili come pacchetti dalla distribuzione generale Linux e documentati in dettaglio da Bernard Gregg. Gli strumenti bcc sono script in Python con piccoli inserti di codice in C, il che significa che chiunque conosca entrambi i linguaggi può modificarli facilmente. In bcc/tools ci sono 80 script Python, il che significa che molto probabilmente sviluppatori o amministratori di sistema troveranno qualcosa di adatto per risolvere i loro compiti.
Per avere almeno un'idea superficiale di quale lavoro svolgano gli VFS in un sistema attivo, provate vfscount o vfsstat. Questo mostrerà, ad esempio, che decine di chiamate vfs_open() e dei suoi "amici" accadono letteralmente ogni secondo.

Sistemi di file virtuali in Linux: a cosa servono e come funzionano? Parte 2

vfsstat.py è uno script in Python, con inserimenti di codice C, che conta semplicemente le chiamate alle funzioni VFS.

Facciamo un esempio più banale e vediamo cosa succede quando inseriamo una chiavetta USB nel computer e il sistema la riconosce.

Sistemi di file virtuali in Linux: a cosa servono e come funzionano? Parte 2

Con eBPF possiamo osservare cosa accade in /sysquando viene inserita una chiavetta USB. Qui viene mostrato un esempio semplice e uno complesso.

Nell'esempio mostrato sopra, bcc strumento trace.py emette un messaggio quando viene eseguita la comando sysfs_create_files(). Vediamo che sysfs_create_files() è stato avviato da kworker in risposta all'inserimento della chiavetta, ma quale file è stato creato in questo caso? trace.py stampa il backtrace del kernel (opzione -K) e il nome del file che è stato creato sysfs_create_files(). L'inserimento tra virgolette singole è codice in C, contenente una stringa di formato facilmente riconoscibile, fornita da uno script Python che esegue LLVM compilatore just-in-time. Questa stringa viene compilata ed eseguita in una macchina virtuale all'interno del kernel. La firma completa della funzione sysfs_create_files () deve essere replicata nel secondo comando, affinché la stringa di formato possa fare riferimento a uno dei parametri. Errori in questo frammento di codice in C portano a errori riconoscibili del compilatore C. Ad esempio, se il parametro -l è mancante, vedrai "Failed to compile BPF text." Gli sviluppatori che hanno familiarità con C e Python troveranno gli strumenti bcc facili da estendere e modificare.

Quando la chiavetta USB è inserita, il backtrace del kernel mostrerà che il PID 7711 è un thread kworker, che ha creato il file "events" in sysfs. Di conseguenza, la chiamata a sysfs_remove_files() mostrerà che la rimozione della chiavetta ha portato alla cancellazione del file events, il che corrisponde al concetto generale di conteggio dei riferimenti. Inoltre, la visualizzazione sysfs_create_link () con eBPF durante l'inserimento della chiavetta USB mostrerà che sono state create almeno 48 link simbolici.

Qual è dunque il significato del file events? L'uso di cscope per cercare __device_add_disk(), mostra che essa chiama disk_add_events (), e o "media_change", oppure "eject_request" possono essere scritti nel file eventi. Qui, lo strato del blocco del kernel informa il userspace dell'inserimento e dell'estrazione del "disco". Nota quanto sia informativo questo metodo di indagine prendendo come esempio l'inserimento della chiavetta USB rispetto ai tentativi di scoprire come funziona tutto esclusivamente dai sorgenti.

I file system radice di sola lettura rendono possibili i dispositivi incorporati

Certo, nessuno spegne un server o il proprio computer staccando la spina dalla presa. Ma perché? È tutto dovuto al fatto che i file system montati su dispositivi fisici di memorizzazione possono avere scritture in sospeso, e le strutture dati che registrano il loro stato potrebbero non essere sincronizzate con le scritture nella memorizzazione. Quando ciò accade, ai proprietari del sistema tocca attendere il successivo avvio per eseguire l'utility fsck filesystem-recovery e, nel peggiore dei casi, perdere dati.

Tuttavia, tutti sappiamo che molti dispositivi IoT, così come router, termostati e automobili, ora funzionano sotto Linux. Molti di questi dispositivi hanno praticamente un'interfaccia utente inesistente e non c'è modo di spegnerli "pulitamente". Immaginate di avviare un'auto con la batteria scarica, quando l'alimentazione del dispositivo di controllo è Linux costantemente altalenante. Come fa dunque il sistema a caricarsi senza un lungo fsck, quando il motore alla fine inizia a funzionare? La risposta è semplice. I dispositivi embedded si basano su un file system radice solo in lettura (abbreviato ro-rootfs (read-only root filesystem)).

ro-rootfs offrono numerosi vantaggi, che sono meno ovvi rispetto all'immutabilità. Un vantaggio è che il malware non può scrivere in /usr o /lib, se nessun processo Linux può scriverci. Un altro è che un file system sostanzialmente immutabile è cruciale per il supporto sul campo dei dispositivi remoti, poiché il personale di supporto utilizza sistemi locali che sono nominalmente identici ai sistemi sul campo. Forse il vantaggio più importante (ma anche il più insidioso) è che ro-rootfs costringe gli sviluppatori a decidere quali oggetti di sistema saranno immutabili fin dall'inizio della progettazione del sistema. Lavorare con ro-rootfs può essere scomodo e doloroso, come spesso accade con le variabili const nei linguaggi di programmazione, ma i loro vantaggi compensano facilmente le spese aggiuntive.

Creazione rootfs La scrittura su un file system di sola lettura richiede alcuni sforzi aggiuntivi per gli sviluppatori di sistemi embedded, ed è qui che entra in gioco VFS. Linux richiede che i file in /var siano accessibili in scrittura, e inoltre, molte applicazioni popolari che eseguono sistemi embedded cercheranno di creare file di configurazione dot-files in $HOME. Una delle soluzioni per i file di configurazione nella home directory è generalmente la loro generazione predefinita e integrazione in rootfs. Per /var un approccio possibile è montarlo in una partizione separata accessibile in scrittura, mentre il / stesso viene montato solo in lettura. Un'altra alternativa popolare è l'uso di montaggi bind o overlay.

Mounts collegabili e sovrapposti, utilizzo come contenitori

Esecuzione del comando man mount – il modo migliore per conoscere i mount collegabili e sovrapposti, che consentono a sviluppatori e amministratori di sistema di creare un file system in un percorso e poi fornirlo a delle applicazioni in un altro. Per i sistemi embedded, questo significa la possibilità di memorizzare file in /var su un'unità flash in sola lettura, ma il montaggio sovrapposto o collegato di un percorso da tmpfs in /var al boot consentirà alle applicazioni di scriverci delle annotazioni. Al successivo avvio, le modifiche a /var andrebbero perse. Il montaggio sovrapposto crea una fusione tra tmpfs e il file system sottostante, permettendo di fare apparenti modifiche ai file esistenti in ro-tootf mentre il montaggio collegato può far vedere nuove cartelle vuote come accessibili per la scrittura in tmpfs percorsi. Mentre ro-rootfs overlayfs è il tipo corretto ( proper) di file system, il montaggio collegato è implementato nellospazio dei nomi VFS Basandosi sulla descrizione dei montaggi sovrapposti e collegati, nessuno si sorprende che.

i container Linux li utilizzino attivamente. Osserviamo cosa succede quando utilizziamo per avviare un container, usando lo strumento systemd-nspawn mountsnoop system-nspawn di bcc.

Chiamata avvia il container mentre viene eseguito mountsnoop.py durante il "boot" del container mostra che l'ambiente di esecuzione del container dipende fortemente dal montaggio collegato (Viene mostrato solo l'inizio di un lungo output)..

Vediamo cosa è stato ottenuto:

Avvio system-nspawn fornisce file selezionati in

Qui systemd-nspawn dell'host nel container come percorsi nel suo procfs e sysfs . Oltre al rootfsMS_BIND flag, che stabilisce il montaggio collegato, alcuni altri flag nel sistema di montaggio definiscono la relazione tra le modifiche nel namespace dell'host e del container. Ad esempio, il montaggio collegato può either saltare le modifiche in nel container, o nasconderle a seconda della chiamata. /proc e /sys Comprendere il funzionamento interno di Linux può sembrare un compito impossibile, poiché il kernel stesso contiene una gigantesca quantità di codice, lasciando da parte le applicazioni dello spazio utente Linux e le interfacce delle chiamate di sistema nelle librerie in linguaggio C, come

Conclusione

Comprendere il funzionamento interno di Linux può sembrare un compito arduo, poiché il kernel stesso contiene una quantità gigantesca di codice, escludendo le applicazioni dello spazio utente di Linux e le interfacce delle chiamate di sistema nelle librerie C, come glibc. Uno dei modi per progredire è leggere il codice sorgente di un sotto-sistema del kernel, con particolare attenzione alla comprensione delle chiamate di sistema e degli header indirizzati allo spazio utente, così come delle principali interfacce interne del kernel, ad esempio, la tabella operazioni_file. Le operazioni sui file seguono il principio "tutto è un file", quindi gestirle è particolarmente piacevole. I file sorgente del kernel in linguaggio C si trovano nella directory principale fs/ e rappresentano l'implementazione dei sistemi di file virtuali, che sono uno strato di interfaccia che fornisce una compatibilità ampia e relativamente semplice con i sistemi di file e i dispositivi di archiviazione più popolari. Il montaggio tramite binding e sovrapposizione attraverso i namespace di Linux è la magia del VFS, che rende possibile la creazione di container e sistemi di file di root in sola lettura. In combinazione con lo studio del codice sorgente, lo strumento kernel eBPF e la sua interfaccia bcc
rendono la ricerca nel kernel più semplice che mai.

Amici, fatemi sapere se questo articolo è stato utile per voi? Forse avete qualche commento o osservazione? E per chi è interessato al corso "Amministratore Linux", vi invitiamo al giornata di porte aperte, che si terrà il 18 aprile.

Prima parte.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster