X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileintro.tex;h=14e4f274eb7ef4ef6ce9fafb414f67f1900e97c3;hp=927dc4da827076a43c36d233593b5aa7e2d8d5cd;hb=81ff87c3e2a6ecd3e33867798cba0d27576f44d0;hpb=8e2e384f75e8ea30c3ea290d736af1077f20117b diff --git a/fileintro.tex b/fileintro.tex index 927dc4d..14e4f27 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -22,16 +22,17 @@ delle modalit -\section{L'architettura dell'accesso} +\section{L'architettura generale} \label{sec:file_access_arch} -Per poter accedere ai file il kernel deve mettere a disposizione dei programmi -le opportune interfacce che consentano di leggerne il contenuto; il sistema -cioè deve provvedere ad organizzare e rendere accessibile in maniera opportuna -l'informazione tenuta sullo spazio grezzo disponibile sui dischi. Questo viene -fatto strutturando l'informazione sul disco attraverso quello che si chiama un -\textit{filesystem}, essa poi viene resa disponibile ai processi attraverso -quello che viene chiamato il \textsl{montaggio} del filesystem. +Per poter accedere ai file, il kernel deve mettere a disposizione dei +programmi le opportune interfacce che consentano di leggerne il contenuto; il +sistema cioè deve provvedere ad organizzare e rendere accessibile in maniera +opportuna l'informazione tenuta sullo spazio grezzo disponibile sui dischi. +Questo viene fatto strutturando l'informazione sul disco attraverso quello che +si chiama un \textit{filesystem} (vedi \ref{sec:file_arch_func}), essa poi +viene resa disponibile ai processi attraverso quello che viene chiamato il +\textsl{montaggio} del \textit{filesystem}. % (approfondiremo tutto ciò in \secref{sec:file_arch_func}). In questa sezione faremo una panormamica generica su come il sistema presenta @@ -46,21 +47,24 @@ In Unix, a differenza di quanto avviene in altri sistemi operativi, tutti i file vengono tenuti all'interno di un unico albero la cui radice (quella che viene chiamata \textit{root directory}) viene montata all'avvio. Un file viene identificato dall'utente usando quello che viene chiamato -\textit{pathname}\footnote{anche se il manuale della \acr{glibc} depreca - questa nomenclatura, poiché genererebbe confusione, dato che con - \textit{path} si indica anche un insieme di directory su cui effettuare una - ricerca (come quello in cui si cercano i comandi) non seguiremo questa - scelta dato che l'uso della parola \textit{pathname} è ormai così comune che - mantenerne l'uso è senz'altro più chiaro dell'alternativa proposta.}, cioè -il percorso che si deve fare per accedere al file, che è composto da una serie +\textit{pathname}\footnote{il manuale della \acr{glibc} depreca questa + nomenclatura, che genererebbe confusione poiché \textit{path} indica anche + un insieme di directory su cui effettuare una ricerca (come quello in cui si + cercano i comandi). Al suo posto viene proposto l'uso di \textit{filename} e + di componente per il nome del file all'interno della directory. Non + seguiremo questa scelta dato che l'uso della parola \textit{pathname} è + ormai così comune che mantenerne l'uso è senz'altro più chiaro + dell'alternativa proposta.}, cioè il percorso che si deve fare per accedere +al file a partire dalla \textit{root directory}, che è composto da una serie di nomi separati da una \file{/}. -Dopo la fase di inizializzazione il kernel riceve dal boot loader -l'indicazione di quale dispositivo contiene il filesystem da usare come punto -di partenza e questo viene montato come radice dell'albero (cioè nella -directory \file{/}); tutti gli ulteriori filesystem che possono essere su -altri dispositivi devono poi essere inseriti nell'albero montandoli su -opportune directory del filesystem montato come radice. +All'avvio del sistema, completata la fase di inizializzazione, il kernel +riceve dal boot loader l'indicazione di quale dispositivo contiene il +filesystem da usare come punto di partenza e questo viene montato come radice +dell'albero (cioè nella directory \file{/}); tutti gli ulteriori filesystem +che possono essere su altri dispositivi dovranno poi essere inseriti +nell'albero montandoli su opportune directory del filesystem montato come +radice. Alcuni filesystem speciali (come \file{/proc} che contiene un'interfaccia ad alcune strutture interne del kernel) sono generati automaticamente dal kernel @@ -87,12 +91,13 @@ Il nome completo di un file viene chiamato \textit{pathname} ed il procedimento con cui si individua il file a cui esso fa riferimento è chiamato risoluzione del nome (\textit{file name resolution} o \textit{pathname resolution}). La risoluzione viene fatta esaminando il \textit{pathname} da -destra a sinistra e localizzando ogni nome nella directory indicata dal nome +sinistra a destra e localizzando ogni nome nella directory indicata dal nome precedente usando \file{/} come separatore\footnote{nel caso di nome vuoto, il - costrutto \file{//} viene considerato equivalente a \file{/}.}: ovviamente -perché il procedimento funzioni occorre che i nomi indicati come directory + costrutto \file{//} viene considerato equivalente a \file{/}.}: ovviamente, +perché il procedimento funzioni, occorre che i nomi indicati come directory esistano e siano effettivamente directory, inoltre i permessi (si veda -\secref{sec:file_access_control}) devono consentire l'accesso. +\secref{sec:file_access_control}) devono consentire l'accesso all'intero +\textit{pathname}. Se il \textit{pathname} comincia per \file{/} la ricerca parte dalla directory radice del processo; questa, a meno di un \func{chroot} (su cui torneremo in @@ -104,16 +109,16 @@ parte dalla directory corrente (su cui torneremo in relativo}\index{pathname relativo}. I nomi \file{.} e \file{..} hanno un significato speciale e vengono inseriti -in ogni directory, il primo fa riferimento alla directory corrente e il +in ogni directory: il primo fa riferimento alla directory corrente e il secondo alla directory \textsl{genitrice} (o \textit{parent directory}) cioè la directory che contiene il riferimento alla directory corrente; nel caso -questa sia la directory radice allora il riferimento è a se stessa. +questa sia la directory radice, allora il riferimento è a se stessa. \subsection{I tipi di file} \label{sec:file_file_types} -Come detto in precedenza in unix esistono vari tipi di file, in Linux questi +Come detto in precedenza, in Unix esistono vari tipi di file; in Linux questi sono implementati come oggetti del \textit{Virtual File System} (vedi \secref{sec:file_vfs_work}) e sono presenti in tutti i filesystem unix-like utilizzabili con Linux. L'elenco dei vari tipi di file definiti dal @@ -139,13 +144,13 @@ dati) in base al loro contenuto, o tipo di accesso. \textit{symbolic link} & \textsl{collegamento simbolico} & un file che contiene un riferimento ad un altro file/directory \\ \textit{char device} & \textsl{dispositivo a caratteri} & - un file che identifica una periferica ad accesso sequenziale \\ + un file che identifica una periferica ad accesso a caratteri \\ \textit{block device} & \textsl{dispositivo a blocchi} & - un file che identifica una periferica ad accesso diretto \\ - \textit{fifo} & \textsl{tubo} & + un file che identifica una periferica ad accesso a blocchi \\ + \textit{fifo} & \textsl{``coda''} & un file speciale che identifica una linea di comunicazione software (unidirezionale) \\ - \textit{socket} & \textsl{manicotto} & + \textit{socket} & \textsl{``presa''} & un file speciale che identifica una linea di comunicazione software (bidirezionale) \\ \hline @@ -159,68 +164,79 @@ VMS o Windows) un flusso continuo di byte. Non esiste cioè differenza per come vengono visti dal sistema file di diverso contenuto o formato (come nel caso di quella fra file di testo e binari che c'è in Windows) né c'è una strutturazione a record -per il cosiddetto ``accesso diretto'' come nel caso del VMS\footnote{con i - kernel della serie 2.4 è disponibile una forma di accesso diretto ai dischi - (il \textit{raw access}) attraverso dei device file appositi, che però non - ha nulla a che fare con questo}. - -Una seconda differenza è nel formato dei file ASCII; in Unix la fine riga è -codificata in maniera diversa da Windows o Mac, in particolare il fine -riga è il carattere \texttt{LF} (o \verb|\n|) al posto del \texttt{CR} -(\verb|\r|) del Mac e del \texttt{CR LF} di Windows. Questo può causare alcuni +per il cosiddetto ``accesso diretto'' come nel caso del VMS.\footnote{con i + kernel della serie 2.4 è disponibile, attraverso dei device file appositi, + una forma di accesso diretto ai dischi (il \textit{raw access}) che però non + ha nulla a che fare con questo, trattandosi solo di operazioni fatte senza + passare attraverso un filesystem.} + +Una seconda differenza è nel formato dei file ASCII: in Unix la fine riga è +codificata in maniera diversa da Windows o Mac, in particolare il fine riga è +il carattere \texttt{LF} (o \verb|\n|) al posto del \texttt{CR} (\verb|\r|) +del Mac e del \texttt{CR LF} di Windows.\footnote{per questo esistono in Linux + dei programmi come \cmd{unix2dos} e \cmd{dos2unix} che effettuano una + conversione fra questi due formati di testo.} Questo può causare alcuni problemi qualora nei programmi si facciano assunzioni sul terminatore della riga. +Si ricordi infine che in ambiente Unix non esistono tipizzazioni dei file di +dati e che non c'è nessun supporto del sistema per le estensioni come parte +del filesystem. Ciò nonostante molti programmi adottano delle convenzioni per +i nomi dei file, ad esempio il codice C normalmente si mette in file con +l'estensione \file{.c}, ma questa è, per quanto usata ed accettata in maniera +universale, solo una convenzione. + \subsection{Le due interfacce ai file} \label{sec:file_io_api} -In unix le modalità di accesso ai file e le relative interfacce di +In Linux le modalità di accesso ai file e le relative interfacce di programmazione sono due, basate su due diversi meccanismi con cui è possibile accedere al loro contenuto. -La prima è l'interfaccia standard di unix, quella che il manuale delle +La prima è l'interfaccia standard di Unix, quella che il manuale delle \acr{glibc} chiama interfaccia dei descrittori di file (o \textit{file - descriptor}). È un'interfaccia specifica di unix e provvede un accesso non -bufferizzato, la tratteremo in dettaglio in \capref{cha:file_unix_interface}. + descriptor}). È un'interfaccia specifica dei sistemi unix-like e fornisce +un accesso non bufferizzato; la tratteremo in dettaglio in +\capref{cha:file_unix_interface}. L'interfaccia è primitiva ed essenziale, l'accesso viene detto non bufferizzato in quanto la lettura e la scrittura vengono eseguite chiamando direttamente le system call del kernel (in realtà il kernel effettua al suo interno alcune bufferizzazioni per aumentare l'efficienza nell'accesso ai dispositivi); i \textit{file descriptor}\index{file descriptor} sono -rappresentati da numeri interi (cioè semplici variabili di tipo \type{int}). +rappresentati da numeri interi (cioè semplici variabili di tipo \ctyp{int}). L'interfaccia è definita nell'header \file{unistd.h}. La seconda interfaccia è quella che il manuale della \acr{glibc} chiama degli -\textit{stream}\index{stream}, essa provvede funzioni più evolute e un accesso -bufferizzato (controllato dalla implementazione fatta dalle librerie del C), -la tratteremo in dettaglio in \capref{cha:files_std_interface}. +\textit{stream}\index{stream}. Essa fornisce funzioni più evolute e un accesso +bufferizzato (controllato dalla implementazione fatta dalle \acr{glibc}), la +tratteremo in dettaglio nel \capref{cha:files_std_interface}. Questa è l'interfaccia standard specificata dall'ANSI C e perciò si trova anche su tutti i sistemi non Unix. Gli \textit{stream} sono oggetti complessi e sono rappresentati da puntatori ad un opportuna struttura definita dalle -librerie del C, si accede ad essi sempre in maniera indiretta utilizzando il -tipo \type{FILE *}. L'interfaccia è definita nell'header \type{stdio.h}. +librerie del C; si accede ad essi sempre in maniera indiretta utilizzando il +tipo \ctyp{FILE *}. L'interfaccia è definita nell'header \file{stdio.h}. Entrambe le interfacce possono essere usate per l'accesso ai file come agli -altri oggetti del VFS (pipe, socket, device, sui quali torneremo in dettaglio -a tempo opportuno), ma per poter accedere alle operazioni di controllo sul -particolare tipo di oggetto del VFS scelto occorre usare l'interfaccia -standard di Unix coi \textit{file descriptor}. Allo stesso modo devono essere -usati i \textit{file descriptor} se si vuole ricorrere a modalità speciali di -I/O come il polling o il non-bloccante (vedi \capref{cha:file_advanced}). +altri oggetti del VFS (fifo, socket, device, sui quali torneremo in dettaglio +a tempo opportuno), ma per poter accedere alle operazioni di controllo +(descritte in \ref{sec:file_fcntl} e \ref{sec:file_ioctl}) su un qualunque +tipo di oggetto del VFS occorre usare l'interfaccia standard di Unix con i +\textit{file descriptor}. Allo stesso modo devono essere usati i \textit{file + descriptor} se si vuole ricorrere a modalità speciali di I/O come il polling +o il non-bloccante (vedi \capref{cha:file_advanced}). Gli \textit{stream} forniscono un'interfaccia di alto livello costruita sopra -quella dei \textit{file descriptor}, che tratta tutti i file nello stesso -modo, con l'eccezione di poter scegliere tra diversi stili di bufferizzazione. -Il maggior vantaggio degli \textit{stream} è che l'interfaccia per le -operazioni di input/output è enormemente più ricca di quella dei \textit{file - descriptor}, che provvedono solo funzioni elementari per la -lettura/scrittura diretta di blocchi di byte. In particolare gli -\textit{stream} dispongono di tutte le funzioni di formattazione per l'input e -l'output adatte per manipolare anche i dati in forma di linee o singoli -caratteri. +quella dei \textit{file descriptor}, che permette di poter scegliere tra +diversi stili di bufferizzazione. Il maggior vantaggio degli \textit{stream} +è che l'interfaccia per le operazioni di input/output è enormemente più ricca +di quella dei \textit{file descriptor}, che forniscono solo funzioni +elementari per la lettura/scrittura diretta di blocchi di byte. In +particolare gli \textit{stream} dispongono di tutte le funzioni di +formattazione per l'input e l'output adatte per manipolare anche i dati in +forma di linee o singoli caratteri. In ogni caso, dato che gli stream sono implementati sopra l'interfaccia standard di Unix, è sempre possibile estrarre il \textit{file descriptor} da @@ -229,88 +245,82 @@ tempo uno \textit{stream} ad un \textit{file descriptor}. In generale, se non necessitano specificatamente le funzionalità di basso livello, è opportuno usare sempre gli \textit{stream} per la loro maggiore -portabilità essendo questi ultimi definiti nello standard ANSI C; -l'interfaccia con i \textit{file descriptor} invece segue solo lo standard -POSIX.1 dei sistemi unix ed è pertanto di portabilità più limitata. - - -\subsection{Caratteristiche specifiche dei file in Unix} -\label{sec:fileint_unix_spec} - -Essendo un sistema multitasking e multiutente esistono alcune caratteristiche -specifiche di un sistema unix-like che devono essere tenute in conto -nell'accesso ai file. È infatti normale che più processi o programmi possano -accedere contemporaneamente allo stesso file e devono poter eseguire le loro -operazioni indipendentemente da quello che fanno gli altri processi. - -Per questo motivo le strutture usate per all'accesso ai file sono relative al -processo che effettua l'accesso. All'apertura di ogni file infatti viene -creata all'interno del processo una apposita struttura in cui sono memorizzati -tutti gli attributi del medesimo, che viene utilizzata per tutte le -operazioni. Questa è una struttura che resta locale al processo stesso; in -questo modo processi diversi possono usare le proprie strutture locali per -accedere ai file (che può essere sempre lo stesso) in maniera assolutamente -indipendente. - -Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i -sistemi POSIX uno degli attributi di un file aperto è la posizione corrente nel -file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione -successiva. Essa è rappresentata da un numero intero che indica il numero di -byte dall'inizio del file, che viene (a meno che non si apra il file in -append) inizializzato a zero all'apertura del medesimo. - -Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui -ogni processo avrà la sua posizione corrente nel file, che non sarà -influenzata da quello che altri processi possono fare. Anzi, aprire un file -significa appunto creare ed inizializzare una tale struttura, per cui se si -apre due volte lo stesso file all'interno dello stesso processo, si otterranno -due file descriptor o due stream che avranno ancora una posizione corrente nel -file assolutamente indipendente. - -Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di -accesso è un riferimento all'inode del file, pertanto anche se il file viene -cancellato da un altro processo, sarà sempre possibile mantenere l'accesso ai -dati, e lo spazio su disco non verrà rilasciato fintanto che il file non sarà -chiuso e l'ultimo riferimento cancellato. È pertanto possibile (come vedremo -in dettaglio in \secref{sec:file_link}) aprire un file provvisorio per -cancellarlo immediatamente dopo; in questo modo all'uscita del programma il -file scomparirà definitivamente dal disco, ma il file ed il suo contenuto -saranno disponibili per tutto il tempo in cui il processo è attivo. - -Ritorneremo su questo più avanti in \secref{sec:file_fd}, quando tratteremo -l'input/output sui file, esaminando in dettaglio come tutto ciò viene -realizzato. - -Si ricordi infine che in ambiente unix non esistono i tipi di file e che non -c'è nessun supporto per le estensioni come parte del filesystem. Ciò non -ostante molti programmi adottano delle convenzioni per i nomi dei file, ad -esempio il codice C normalmente si mette in file con l'estensione .c, ma -questa è, appunto, solo una convenzione. - - -\section{L'architettura di funzionamento} +portabilità, essendo questi ultimi definiti nello standard ANSI C; +l'interfaccia con i \textit{file descriptor} infatti segue solo lo standard +POSIX.1 dei sistemi Unix, ed è pertanto di portabilità più limitata. + + +% \subsection{Caratteristiche specifiche dei file in Unix} +% \label{sec:fileint_unix_spec} + +% Essendo un sistema multitasking e multiutente esistono alcune caratteristiche +% specifiche di un sistema unix-like che devono essere tenute in conto +% nell'accesso ai file. È infatti normale che più processi o programmi possano +% accedere contemporaneamente allo stesso file e devono poter eseguire le loro +% operazioni indipendentemente da quello che fanno gli altri processi. + +% Per questo motivo le strutture usate per all'accesso ai file sono relative al +% processo che effettua l'accesso. All'apertura di ogni file infatti viene +% creata all'interno del processo una apposita struttura in cui sono memorizzati +% tutti gli attributi del medesimo, che viene utilizzata per tutte le +% operazioni. Questa è una struttura che resta locale al processo stesso; in +% questo modo processi diversi possono usare le proprie strutture locali per +% accedere ai file (che può essere sempre lo stesso) in maniera assolutamente +% indipendente. + +% Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i +% sistemi POSIX uno degli attributi di un file aperto è la posizione corrente nel +% file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione +% successiva. Essa è rappresentata da un numero intero che indica il numero di +% byte dall'inizio del file, che viene (a meno che non si apra il file in +% append) inizializzato a zero all'apertura del medesimo. + +% Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui +% ogni processo avrà la sua posizione corrente nel file, che non sarà +% influenzata da quello che altri processi possono fare. Anzi, aprire un file +% significa appunto creare ed inizializzare una tale struttura, per cui se si +% apre due volte lo stesso file all'interno dello stesso processo, si otterranno +% due file descriptor o due stream che avranno ancora una posizione corrente nel +% file assolutamente indipendente. + +% Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di +% accesso è un riferimento all'inode del file, pertanto anche se il file viene +% cancellato da un altro processo, sarà sempre possibile mantenere l'accesso ai +% dati, e lo spazio su disco non verrà rilasciato fintanto che il file non sarà +% chiuso e l'ultimo riferimento cancellato. È pertanto possibile (come vedremo +% in dettaglio in \secref{sec:file_link}) aprire un file provvisorio per +% cancellarlo immediatamente dopo; in questo modo all'uscita del programma il +% file scomparirà definitivamente dal disco, ma il file ed il suo contenuto +% saranno disponibili per tutto il tempo in cui il processo è attivo. + +% Ritorneremo su questo più avanti in \secref{sec:file_fd}, quando tratteremo +% l'input/output sui file, esaminando in dettaglio come tutto ciò viene +% realizzato. + + +\section{L'architettura della gestione dei file} \label{sec:file_arch_func} Per capire fino in fondo le proprietà di file e directory in un sistema unix-like ed il comportamento delle relative funzioni di manipolazione occorre una breve introduzione al funzionamento gestione dei file da parte del kernel -e sugli oggetti su cui è basato un filesystem di tipo unix. In particolare -occorre tenere presente dov'è che si situa la divisione fondamentale fra -kernel space e user space che tracciavamo al \capref{cha:intro_unix}. +e sugli oggetti su cui è basato un filesystem. In particolare occorre tenere +presente dov'è che si situa la divisione fondamentale fra kernel space e user +space che tracciavamo al \capref{cha:intro_unix}. In questa sezione esamineremo come viene implementato l'accesso ai file in Linux, come il kernel può gestire diversi tipi di filesystem, descrivendo -prima le caratteristiche generali di un filesystem Unix, per poi trattare in -maniera un po' più dettagliata il filesystem standard di Linux, l'\acr{ext2}. - +prima le caratteristiche generali di un filesystem di un sistema unix-like, +per poi trattare in maniera un po' più dettagliata il filesystem standard di +Linux, l'\acr{ext2}. -% in particolare si riprenderà, approfondendolo sul piano -% dell'uso nelle funzioni di libreria, il concetto di \textit{inode} di cui -% abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione -% nel kernel) in \secref{sec:file_vfs}. +% in particolare si riprenderà, approfondendolo sul piano dell'uso nelle +% funzioni di libreria, il concetto di \textit{inode} di cui abbiamo brevemente +% accennato le caratteristiche (dal lato dell'implementazione nel kernel) in +% \secref{sec:file_vfs}. -\subsection{Il \textit{virtual filesystem} di Linux} +\subsection{Il \textit{Virtual Filesystem} di Linux} \label{sec:file_vfs} % Questa sezione riporta informazioni sui dettagli di come il kernel gestisce i @@ -320,25 +330,27 @@ maniera un po' pi % \textit{inode}, \textit{dentry}, \textit{dcache}. In Linux il concetto di \textit{everything is a file} è stato implementato -attraverso il \textit{Virtual File System} (da qui in avanti VFS) che è -l'interfaccia che il kernel rende disponibile ai programmi in user space -attraverso la quale vengono manipolati i file; esso provvede un livello di -indirezione che permette di collegare le operazioni di manipolazione sui file -alle operazioni di I/O e gestisce l'organizzazione di questi ultimi nei vari -modi in cui diversi filesystem la effettuano, permettendo la coesistenza -di filesystem differenti all'interno dello stesso albero delle directory - -Quando un processo esegue una system call che opera su un file il kernel +attraverso il \textit{Virtual Filesystem} (da qui in avanti VFS) che è uno +strato intermedio che il kernel usa per accedere ai più svariati filesystem +mantenendo la stessa interfaccia per i programmi in user space. Esso fornisce +un livello di indirezione che permette di collegare le operazioni di +manipolazione sui file alle operazioni di I/O, e gestisce l'organizzazione di +queste ultime nei vari modi in cui i diversi filesystem le effettuano, +permettendo la coesistenza di filesystem differenti all'interno dello stesso +albero delle directory. + +Quando un processo esegue una system call che opera su un file, il kernel chiama sempre una funzione implementata nel VFS; la funzione eseguirà le -manipolazioni sulle strutture generiche e utilizzerà poi la chiamata alla +manipolazioni sulle strutture generiche e utilizzerà poi la chiamata alle opportune routine del filesystem specifico a cui si fa riferimento. Saranno queste a chiamare le funzioni di più basso livello che eseguono le operazioni -di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig. +di I/O sul dispositivo fisico, secondo lo schema riportato in +\figref{fig:file_VFS_scheme}. \begin{figure}[htb] \centering \includegraphics[width=7cm]{img/vfs} - \caption{Schema delle operazioni del VFS} + \caption{Schema delle operazioni del VFS.} \label{fig:file_VFS_scheme} \end{figure} @@ -359,17 +371,17 @@ In questo modo quando viene effettuata la richiesta di montare un nuovo disco (o qualunque altro \textit{block device} che può contenere un filesystem), il VFS può ricavare dalla citata tabella il puntatore alle funzioni da chiamare nelle operazioni di montaggio. Quest'ultima è responsabile di leggere da disco -il superblock (vedi \ref{sec:file_ext2}), inizializzare tutte le -variabili interne e restituire uno speciale descrittore dei filesystem montati -al VFS; attraverso quest'ultimo diventa possibile accedere alle routine -specifiche per l'uso di quel filesystem. +il superblock (vedi \secref{sec:file_ext2}), inizializzare tutte le variabili +interne e restituire uno speciale descrittore dei filesystem montati al VFS; +attraverso quest'ultimo diventa possibile accedere alle routine specifiche per +l'uso di quel filesystem. Il primo oggetto usato dal VFS è il descrittore di filesystem, un puntatore ad una apposita struttura che contiene vari dati come le informazioni comuni ad ogni filesystem, i dati privati relativi a quel filesystem specifico, e i puntatori alle funzioni del kernel relative al filesystem. Il VFS può così -usare le funzioni contenute nel filesystem descriptor per accedere alle routine -specifiche di quel filesystem. +usare le funzioni contenute nel \textit{filesystem descriptor} per accedere +alle routine specifiche di quel filesystem. Gli altri due descrittori usati dal VFS sono relativi agli altri due oggetti su cui è strutturata l'interfaccia. Ciascuno di essi contiene le informazioni @@ -384,28 +396,28 @@ file gi \subsection{Il funzionamento del VFS} \label{sec:file_vfs_work} -La funzione più fondamentale implementata dal VFS è la system call -\func{open} che permette di aprire un file. Dato un pathname viene eseguita -una ricerca dentro la \textit{directory entry cache} (in breve -\textit{dcache}), una tabella di hash che contiene tutte le \textit{directory - entry} (in breve \textit{dentry}) che permette di associare in maniera -rapida ed efficiente il pathname a una specifica dentry. +La funzione più importante implementata dal VFS è la system call \func{open} +che permette di aprire un file. Dato un pathname viene eseguita una ricerca +dentro la \textit{directory entry cache} (in breve \textit{dcache}), una +tabella che contiene tutte le \textit{directory entry} (in breve +\textit{dentry}) che permette di associare in maniera rapida ed efficiente il +pathname a una specifica \textit{dentry}. Una singola \textit{dentry} contiene in genere il puntatore ad un \textit{inode}; quest'ultimo è la struttura base che sta sul disco e che identifica un singolo oggetto del VFS sia esso un file ordinario, una directory, un link simbolico, una FIFO, un file di dispositivo, o una -qualsiasi altra cosa che possa essere rappresentata dal VFS (sui tipi di -``file'' possibili torneremo in seguito). A ciascuno di essi è associata pure -una struttura che sta in memoria, e che oltre alle informazioni sullo -specifico file contiene pure il riferimento alle funzioni (i \textsl{metodi}) -da usare per poterlo manipolare. +qualsiasi altra cosa che possa essere rappresentata dal VFS (i tipi di +``file'' riportati in \tabref{tab:file_file_types}). A ciascuno di essi è +associata pure una struttura che sta in memoria, e che, oltre alle +informazioni sullo specifico file, contiene anche il riferimento alle funzioni +(i \textsl{metodi} del VFS) da usare per poterlo manipolare. Le \textit{dentry} ``vivono'' in memoria e non vengono mai salvate su disco, -vengono usate per motivi di velocità, gli inode invece stanno su disco e -vengono copiati in memoria quando serve, ed ogni cambiamento viene copiato -all'indietro sul disco, gli inode che stanno in memoria sono inode del VFS ed -è ad essi che puntano le singole \textit{dentry}. +vengono usate per motivi di velocità, gli \textit{inode} invece stanno su +disco e vengono copiati in memoria quando serve, ed ogni cambiamento viene +copiato all'indietro sul disco, gli inode che stanno in memoria sono inode del +VFS ed è ad essi che puntano le singole \textit{dentry}. La \textit{dcache} costituisce perciò una sorta di vista completa di tutto l'albero dei file, ovviamente per non riempire tutta la memoria questa vista è @@ -419,9 +431,9 @@ della directory che contiene il file; questo viene installato nelle relative strutture in memoria quando si effettua il montaggio lo specifico filesystem su cui l'inode va a vivere. -Una volta che il VFS ha a disposizione la dentry (ed il relativo inode) -diventa possibile accedere alle varie operazioni sul file come la -\func{open} per aprire il file o la \func{stat} per leggere i dati +Una volta che il VFS ha a disposizione la \textit{dentry} (ed il relativo +\textit{inode}) diventa possibile accedere alle varie operazioni sul file come +la \func{open} per aprire il file o la \func{stat} per leggere i dati dell'inode e passarli in user space. L'apertura di un file richiede comunque un'altra operazione, l'allocazione di @@ -462,45 +474,47 @@ operazioni previste dal kernel \label{tab:file_file_operations} \end{table} -In questo modo per ciascun file diventano utilizzabili una serie di operazioni -(non è dette che tutte siano disponibili), che costituiscono l'interfaccia -astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad -utilizzare la opportuna routine dichiarata in \var{f\_ops} appropriata al tipo -di file in questione. +In questo modo per ciascun file diventano possibili una serie di operazioni +(non è detto che tutte siano disponibili), che costituiscono l'interfaccia +astratta del VFS. Qualora se ne voglia eseguire una, il kernel andrà ad +utilizzare l'opportuna routine dichiarata in \var{f\_ops} appropriata al tipo +di file in questione. -Così sarà possibile scrivere sulla porta seriale come su un file di dati -normale; ovviamente certe operazioni (nel caso della seriale ad esempio la -\code{seek}) non saranno disponibili, però con questo sistema l'utilizzo di -diversi filesystem (come quelli usati da Windows o MacOs) è immediato e -(relativamente) trasparente per l'utente ed il programmatore. +In questo modo è possibile scrivere allo stesso modo sulla porta seriale come +su normale un file di dati; ovviamente certe operazioni (nel caso della +seriale ad esempio la \code{seek}) non saranno disponibili, però con questo +sistema l'utilizzo di diversi filesystem (come quelli usati da Windows o +MacOs) è immediato e (relativamente) trasparente per l'utente ed il +programmatore. -\subsection{Il funzionamento di un filesystem unix} +\subsection{Il funzionamento di un filesystem Unix} \label{sec:file_filesystem} -Come già accennato in \secref{sec:file_organization} Linux (ed ogni unix -in generale) organizza i dati che tiene su disco attraverso l'uso di un +Come già accennato in \secref{sec:file_organization} Linux (ed ogni sistema +unix-like) organizza i dati che tiene su disco attraverso l'uso di un filesystem. Una delle caratteristiche di Linux rispetto agli altri Unix è -quella di poter supportare grazie al VFS una enorme quantità di filesystem +quella di poter supportare, grazie al VFS, una enorme quantità di filesystem diversi, ognuno dei quali ha una sua particolare struttura e funzionalità -proprie; per questo non entreremo nei dettagli di un filesystem specifico, ma -daremo una descrizione a grandi linee che si adatta alle caratteristiche -comuni di un qualunque filesystem standard unix. +proprie. Per questo, per il momento non entreremo nei dettagli di un +filesystem specifico, ma daremo una descrizione a grandi linee che si adatta +alle caratteristiche comuni di qualunque filesystem di sistema unix-like. -Dato un disco lo spazio fisico viene usualmente diviso in partizioni; ogni -partizione può contenere un filesystem; la strutturazione tipica +Lo spazio fisico di un disco viene usualmente diviso in partizioni; ogni +partizione può contenere un filesystem. La strutturazione tipica dell'informazione su un disco è riportata in \nfig; in essa si fa riferimento alla struttura del filesystem \acr{ext2}, che prevede una separazione dei dati in \textit{blocks group} che replicano il superblock (ma sulle caratteristiche di \acr{ext2} torneremo in \secref{sec:file_ext2}). È comunque caratteristica -comune di tutti i filesystem unix, indipendentemente da come poi viene +comune di tutti i filesystem per Unix, indipendentemente da come poi viene strutturata nei dettagli questa informazione, prevedere una divisione fra la lista degli inodes e lo spazio a disposizione per i dati e le directory. \begin{figure}[htb] \centering - \includegraphics[width=9cm]{img/disk_struct} - \caption{Organizzazione dello spazio su un disco in partizioni e filesystem} + \includegraphics[width=12cm]{img/disk_struct} + \caption{Organizzazione dello spazio su un disco in partizioni e + filesystem.} \label{fig:file_disk_filesys} \end{figure} @@ -512,15 +526,16 @@ esemplificare la situazione con uno schema come quello esposto in \nfig. \begin{figure}[htb] \centering - \includegraphics[width=11cm]{img/filesys_struct} - \caption{Strutturazione dei dati all'interno di un filesystem} + \includegraphics[width=12cm]{img/filesys_struct} + \caption{Strutturazione dei dati all'interno di un filesystem.} \label{fig:file_filesys_detail} \end{figure} -Da \curfig\ si evidenziano alcune caratteristiche base di ogni filesystem su -cui è bene porre attenzione in quanto sono fondamentali per capire il -funzionamento delle funzioni che manipolano i file e le directory su cui -torneremo in seguito; in particolare è opportuno ricordare sempre che: +Da \curfig\ si evidenziano alcune delle caratteristiche di base di un +filesystem, sulle quali è bene porre attenzione visto che sono fondamentali +per capire il funzionamento delle funzioni che manipolano i file e le +directory che tratteremo nel prossimo capitolo; in particolare è opportuno +ricordare sempre che: \begin{enumerate} @@ -533,40 +548,40 @@ torneremo in seguito; in particolare (traduzione approssimata dell'inglese \textit{directory entry}, che non useremo anche per evitare confusione con le \textit{dentry} del kernel di cui si parlava in \secref{sec:file_vfs}). - -\item Come mostrato in \curfig si possono avere più voci che puntano allo + +\item Come mostrato in \curfig\ si possono avere più voci che puntano allo stesso \textit{inode}. Ogni \textit{inode} ha un contatore che contiene il numero di riferimenti (\textit{link count}) che sono stati fatti ad esso; solo quando questo contatore si annulla i dati del file vengono effettivamente rimossi dal disco. Per questo la funzione per cancellare un file si chiama \func{unlink}, ed in realtà non cancella affatto i dati del - file, ma si limita a eliminare la relativa voce da una directory e + file, ma si limita ad eliminare la relativa voce da una directory e decrementare il numero di riferimenti nell'\textit{inode}. - + \item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode} nello stesso filesystem e non ci può essere una directory che contiene riferimenti ad \textit{inodes} relativi ad altri filesystem. Questo limita l'uso del comando \cmd{ln} (che crea una nuova voce per un file esistente, con la funzione \func{link}) al filesystem corrente. -\item Quando si cambia nome ad un file senza cambiare filesystem il contenuto - del file non deve essere spostato, viene semplicemente creata una nuova voce - per l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità - in cui opera normalmente il comando \cmd{mv} attraverso la funzione - \func{rename}). +\item Quando si cambia nome ad un file senza cambiare filesystem, il contenuto + del file non viene spostato fisicamente, viene semplicemente creata una + nuova voce per l'\textit{inode} in questione e rimossa la vecchia (questa è + la modalità in cui opera normalmente il comando \cmd{mv} attraverso la + funzione \func{rename}). \end{enumerate} -Infine è bene avere presente che essendo file pure loro, esiste un numero di -riferimenti anche per le directory; per cui se ad esempio a partire dalla -situazione mostrata in \curfig\ creiamo una nuova directory \file{img} nella -directory \file{gapil}: avremo una situazione come quella in \nfig, dove per -chiarezza abbiamo aggiunto dei numeri di inode. +Infine è bene avere presente che, essendo file pure loro, esiste un numero di +riferimenti anche per le directory; per cui, se a partire dalla situazione +mostrata in \curfig\ creiamo una nuova directory \file{img} nella directory +\file{gapil}, avremo una situazione come quella in \nfig, dove per chiarezza +abbiamo aggiunto dei numeri di inode. \begin{figure}[htb] \centering - \includegraphics[width=11cm]{img/dir_links} - \caption{Organizzazione dei link per le directory} + \includegraphics[width=12cm]{img/dir_links} + \caption{Organizzazione dei link per le directory.} \label{fig:file_dirs_link} \end{figure} @@ -574,8 +589,8 @@ La nuova directory avr è referenziata dalla directory da cui si era partiti (in cui è inserita la nuova voce che fa riferimento a \file{img}) e dalla voce \file{.} che è sempre inserita in ogni directory; questo vale sempre per ogni directory -che non contenga a sua volta altre directory. Al contempo la directory da -cui si era partiti avrà un numero di riferiementi di almeno tre, in quanto +che non contenga a sua volta altre directory. Al contempo, la directory da +cui si era partiti avrà un numero di riferimenti di almeno tre, in quanto adesso sarà referenziata anche dalla voce \file{..} di \file{img}. @@ -584,13 +599,12 @@ adesso sar Il filesystem standard usato da Linux è il cosiddetto \textit{second extended filesystem}, identificato dalla sigla \acr{ext2}. Esso supporta tutte le -caratteristiche di un filesystem standard unix, è in grado di gestire -filename lunghi (256 caratteri, estendibili a 1012), una dimensione fino a -4~Tb. +caratteristiche di un filesystem standard Unix, è in grado di gestire nomi di +file lunghi (256 caratteri, estendibili a 1012) con una dimensione massima di +4~Tb. -Oltre alle caratteristiche standard \acr{ext2} fornisce alcune estensioni -che non sono presenti sugli altri filesystem unix, le cui principali sono le -seguenti: +Oltre alle caratteristiche standard, \acr{ext2} fornisce alcune estensioni che +non sono presenti sugli altri filesystem Unix. Le principali sono le seguenti: \begin{itemize} \item i \textit{file attributes} consentono di modificare il comportamento del kernel quando agisce su gruppi di file. Possono essere settati su file e @@ -618,7 +632,7 @@ seguenti: log). \end{itemize} -La struttura di \acr{ext2} è stata ispirata a quella del filesystem di BSD, +La struttura di \acr{ext2} è stata ispirata a quella del filesystem di BSD: un filesystem è composto da un insieme di blocchi, la struttura generale è quella riportata in \figref{fig:file_filesys_detail}, in cui la partizione è divisa in gruppi di blocchi.