+
+\subsection{Il \textit{Virtual File System} di Linux}
+\label{sec:file_vfs}
+
+\itindbeg{Virtual~File~System}
+In Linux il concetto di \textit{everything is a file} è stato implementato
+attraverso il \textit{Virtual File System} (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 alle
+opportune funzioni 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
+fig.~\ref{fig:file_VFS_scheme}.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=7cm]{img/vfs}
+ \caption{Schema delle operazioni del VFS.}
+ \label{fig:file_VFS_scheme}
+\end{figure}
+
+Il VFS definisce un insieme di funzioni che tutti i filesystem devono
+implementare. L'interfaccia comprende tutte le funzioni che riguardano i file;
+le operazioni sono suddivise su tre tipi di oggetti: \textit{filesystem},
+\textit{inode}\index{inode} e \textit{file}, corrispondenti a tre apposite
+strutture definite nel kernel.
+
+Il VFS usa una tabella mantenuta dal kernel che contiene il nome di ciascun
+filesystem supportato: quando si vuole inserire il supporto di un nuovo
+filesystem tutto quello che occorre è chiamare la funzione
+\code{register\_filesystem} passandole un'apposita struttura
+\code{file\_system\_type} che contiene i dettagli per il riferimento
+all'implementazione del medesimo, che sarà aggiunta alla citata tabella.
+
+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 sez.~\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 funzioni 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 \textit{filesystem descriptor} per accedere
+alle funzioni 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
+relative al file in uso, insieme ai puntatori alle funzioni dello specifico
+filesystem usate per l'accesso dal VFS; in particolare il descrittore
+dell'inode\index{inode} contiene i puntatori alle funzioni che possono essere
+usate su qualunque file (come \func{link}, \func{stat} e \func{open}), mentre
+il descrittore di file contiene i puntatori alle funzioni che vengono usate
+sui file già aperti.
+
+
+\subsection{Il funzionamento del \textit{Virtual File System}}
+\label{sec:file_vfs_work}
+
+La funzione più importante implementata dal VFS è la system call \func{open}
+che permette di aprire un file. Dato un \itindex{pathname}\textit{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 \textit{pathname} a una specifica \textit{dentry}.
+
+Una singola \textit{dentry} contiene in genere il puntatore ad un
+\textit{inode}\index{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\index{file!di~dispositivo}, o una qualsiasi altra cosa che possa
+essere rappresentata dal VFS (i tipi di file riportati in
+tab.~\ref{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 \textit{inode}\index{inode} invece
+stanno su disco e vengono copiati in memoria quando serve, ed ogni cambiamento
+viene copiato all'indietro sul disco, gli inode\index{inode} che stanno in
+memoria sono inode\index{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 è
+parziale (la \textit{dcache} cioè contiene solo le \textit{dentry} per i file
+per i quali è stato richiesto l'accesso), quando si vuole risolvere un nuovo
+\itindex{pathname}\textit{pathname} il VFS deve creare una nuova
+\textit{dentry} e caricare l'inode\index{inode} corrispondente in memoria.
+
+Questo procedimento viene eseguito dal metodo \code{lookup()}
+dell'inode\index{inode} 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 \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\index{inode} e passarli in user space.
+
+L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
+una struttura di tipo \struct{file} in cui viene inserito un puntatore alla
+\textit{dentry} e una struttura \struct{f\_ops} che contiene i puntatori ai
+metodi che implementano le operazioni disponibili sul file. In questo modo i
+processi in user space possono accedere alle operazioni attraverso detti
+metodi, che saranno diversi a seconda del tipo di file (o dispositivo) aperto
+(su questo torneremo in dettaglio in sez.~\ref{sec:file_fd}). Un elenco delle
+operazioni previste dal kernel è riportato in
+tab.~\ref{tab:file_file_operations}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Funzione} & \textbf{Operazione} \\
+ \hline
+ \hline
+ \textsl{\code{open}} & apre il file (vedi sez.~\ref{sec:file_open}). \\
+ \textsl{\code{read}} & legge dal file (vedi sez.~\ref{sec:file_read}).\\
+ \textsl{\code{write}} & scrive sul file (vedi
+ sez.~\ref{sec:file_write}).\\
+ \textsl{\code{llseek}} & sposta la posizione corrente sul file (vedi
+ sez.~\ref{sec:file_lseek}). \\
+ \textsl{\code{ioctl}} & accede alle operazioni di controllo
+ (vedi sez.~\ref{sec:file_ioctl}).\\
+ \textsl{\code{readdir}}& legge il contenuto di una directory \\
+ \textsl{\code{poll}} & usata nell'I/O multiplexing (vedi
+ sez.~\ref{sec:file_multiplexing}). \\
+ \textsl{\code{mmap}} & mappa il file in memoria (vedi
+ sez.~\ref{sec:file_memory_map}). \\
+ \textsl{\code{release}}& chiamata quando l'ultimo riferimento a un file
+ aperto è chiuso. \\
+ \textsl{\code{fsync}} & sincronizza il contenuto del file (vedi
+ sez.~\ref{sec:file_sync}). \\
+ \textsl{\code{fasync}} & abilita l'I/O asincrono (vedi
+ sez.~\ref{sec:file_asyncronous_io}) sul file. \\
+ \hline
+ \end{tabular}
+ \caption{Operazioni sui file definite nel VFS.}
+ \label{tab:file_file_operations}
+\end{table}
+
+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 funzione dichiarata in \struct{f\_ops} appropriata al
+tipo di file in questione.
+
+Pertanto è possibile scrivere allo stesso modo sulla porta seriale come su un
+normale 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.
+\itindend{Virtual~File~System}
+
+
+\subsection{Il funzionamento di un filesystem Unix}
+\label{sec:file_filesystem}
+
+Come già accennato in sez.~\ref{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
+diversi, ognuno dei quali ha una sua particolare struttura e funzionalità
+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.
+
+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 fig.~\ref{fig:file_disk_filesys};
+in essa si fa riferimento alla struttura del filesystem \acr{ext2}, che
+prevede una separazione dei dati in \textit{block group} che replicano il
+superblock (ma sulle caratteristiche di \acr{ext2} torneremo in
+sez.~\ref{sec:file_ext2}). È comunque caratteristica comune di tutti i
+filesystem per Unix, indipendentemente da come poi viene strutturata nei
+dettagli questa informazione, prevedere una divisione fra la lista degli
+inode\index{inode} e lo spazio a disposizione per i dati e le directory.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=14cm]{img/disk_struct}
+ \caption{Organizzazione dello spazio su un disco in partizioni e
+ filesystem.}
+ \label{fig:file_disk_filesys}
+\end{figure}
+
+Se si va ad esaminare con maggiore dettaglio la strutturazione
+dell'informazione all'interno del singolo filesystem (tralasciando i dettagli
+relativi al funzionamento del filesystem stesso come la strutturazione in
+gruppi dei blocchi, il superblock e tutti i dati di gestione) possiamo
+esemplificare la situazione con uno schema come quello esposto in
+fig.~\ref{fig:file_filesys_detail}.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=14cm]{img/filesys_struct}
+ \caption{Strutturazione dei dati all'interno di un filesystem.}
+ \label{fig:file_filesys_detail}
+\end{figure}
+
+Da fig.~\ref{fig:file_filesys_detail} 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}
+
+\item L'\textit{inode}\index{inode} contiene tutte le informazioni riguardanti
+ il file: il tipo di file, i permessi di accesso, le dimensioni, i puntatori
+ ai blocchi fisici che contengono i dati e così via; le informazioni che la
+ funzione \func{stat} fornisce provengono dall'\textit{inode}; dentro una
+ directory si troverà solo il nome del file e il numero
+ dell'\textit{inode}\index{inode} ad esso associato, cioè quella che da qui
+ in poi chiameremo una \textsl{voce} (come traduzione dell'inglese
+ \textit{directory entry}, che non useremo anche per evitare confusione con
+ le \textit{dentry} del kernel di cui si parlava in sez.~\ref{sec:file_vfs}).
+
+\item Come mostrato in fig.~\ref{fig:file_filesys_detail} 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 ad eliminare la relativa voce da una
+ directory e decrementare il numero di riferimenti
+ nell'\textit{inode}\index{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{inode}\index{inode} 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 viene spostato fisicamente, viene semplicemente creata una
+ nuova voce per l'\textit{inode}\index{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 a partire dalla situazione
+mostrata in fig.~\ref{fig:file_filesys_detail} creiamo una nuova directory
+\file{img} nella directory \file{gapil}, avremo una situazione come quella in
+fig.~\ref{fig:file_dirs_link}, dove per chiarezza abbiamo aggiunto dei numeri
+di inode\index{inode}.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=14cm]{img/dir_links}
+ \caption{Organizzazione dei link per le directory.}
+ \label{fig:file_dirs_link}
+\end{figure}
+
+La nuova directory avrà allora un numero di riferimenti pari a due, in quanto
+è 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 riferimenti di almeno tre, in quanto
+adesso sarà referenziata anche dalla voce \file{..} di \file{img}.
+
+
+\subsection{Il filesystem \textsl{ext2}}
+\label{sec:file_ext2}
+
+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 nomi di
+file lunghi (256 caratteri, estensibili 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 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 impostati su file e
+ directory e in quest'ultimo caso i nuovi file creati nella directory
+ ereditano i suoi attributi.
+\item sono supportate entrambe le semantiche di BSD e SVr4 come opzioni di
+ montaggio. La semantica BSD comporta che i file in una directory sono creati
+ con lo stesso identificatore di gruppo della directory che li contiene. La
+ semantica SVr4 comporta che i file vengono creati con l'identificatore del
+ gruppo primario del processo, eccetto il caso in cui la directory ha il bit
+ di \acr{sgid} impostato (per una descrizione dettagliata del significato di
+ questi termini si veda sez.~\ref{sec:file_access_control}), nel qual caso
+ file e subdirectory ereditano sia il \acr{gid} che lo \acr{sgid}.
+\item l'amministratore può scegliere la dimensione dei blocchi del filesystem
+ in fase di creazione, a seconda delle sue esigenze (blocchi più grandi
+ permettono un accesso più veloce, ma sprecano più spazio disco).
+\item il filesystem implementa link simbolici veloci, in cui il nome del file
+ non è salvato su un blocco, ma tenuto all'interno dell'inode\index{inode}
+ (evitando letture multiple e spreco di spazio), non tutti i nomi però
+ possono essere gestiti così per limiti di spazio (il limite è 60 caratteri).
+\item vengono supportati i file immutabili (che possono solo essere letti) per
+ la protezione di file di configurazione sensibili, o file
+ \textit{append-only} che possono essere aperti in scrittura solo per
+ aggiungere dati (caratteristica utilizzabile per la protezione dei file di
+ log).
+\end{itemize}
+
+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 fig.~\ref{fig:file_filesys_detail}, in cui la partizione è divisa
+in gruppi di blocchi.\footnote{non si confonda questa definizione con
+ quella riportata in fig.~\ref{fig:file_dirent_struct}; in quel caso si fa
+ riferimento alla struttura usata in user space per riportare i dati
+ contenuti in una directory generica, questa fa riferimento alla struttura
+ usata dal kernel per un filesystem \acr{ext2}, definita nel file
+ \texttt{ext2\_fs.h} nella directory \texttt{include/linux} dei sorgenti del
+ kernel.}
+
+Ciascun gruppo di blocchi contiene una copia delle informazioni essenziali del
+filesystem (superblock e descrittore del filesystem sono quindi ridondati) per
+una maggiore affidabilità e possibilità di recupero in caso di corruzione del
+superblock principale.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=9cm]{img/dir_struct}
+ \caption{Struttura delle directory nel \textit{second extented filesystem}.}
+ \label{fig:file_ext2_dirs}
+\end{figure}
+
+L'utilizzo di raggruppamenti di blocchi ha inoltre degli effetti positivi nelle
+prestazioni dato che viene ridotta la distanza fra i dati e la tabella degli
+inode\index{inode}.
+
+Le directory sono implementate come una \itindex{linked~list}\textit{linked
+ list} con voci di dimensione variabile. Ciascuna voce della lista contiene
+il numero di inode\index{inode}, la sua lunghezza, il nome del file e la sua
+lunghezza, secondo lo schema in fig.~\ref{fig:file_ext2_dirs}; in questo modo
+è possibile implementare nomi per i file anche molto lunghi (fino a 1024
+caratteri) senza sprecare spazio disco.
+
+
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End:
+
+% LocalWords: everything is device kernel filesystem sez pathname root glibc
+% LocalWords: path filename bootloader proc name components fifo socket dev LF
+% LocalWords: resolution chroot parent Virtual System like tab cap l'I regular
+% LocalWords: inode symbolic char block VFS VMS Windows dell'I raw access Mac
+% LocalWords: CR dos HFS l'XFS SGI magic number descriptor system call int ext
+% LocalWords: nell'header unistd stream dall'ANSI stdio locking POSIX fig type
+% LocalWords: register superblock dell'inode stat entry cache dcache dentry ln
+% LocalWords: l'inode lookup ops read write llseek ioctl readdir poll nell'I
+% LocalWords: multiplexing mmap fsync fasync seek MacOs group dall' dell' img
+% LocalWords: count unlink nell' rename gapil second Tb attributes BSD SVr gid
+% LocalWords: sgid append only log fs linux extented linked list