X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileintro.tex;h=cf0e674aeb98c510953620739e44bb40cc428250;hp=479ff86bf653717444cc04653c5819336984ff5e;hb=f43b330570ece41d80aaca3c775eb4b7835aab28;hpb=4ad4523de32d786ae4c24ef157bd4b8fe4aac534 diff --git a/fileintro.tex b/fileintro.tex index 479ff86..cf0e674 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -1,4 +1,4 @@ -\chapter{I file: l'architettura} +\chapter{L'architettura dei file} \label{cha:file_intro} Uno dei concetti fondamentali della architettura di unix è il cosiddetto @@ -19,6 +19,8 @@ nelle particolarit contempo tratteremo l'organizzazione dei file in un sistema unix-like, e le varie caratteristiche distintive. + + \section{L'organizzazione di file e directory} \label{sec:file_organization} @@ -64,7 +66,7 @@ alcune strutture interne del kernel) sono generati automaticamente dal kernel stesso, ma anche essi devono essere montati all'interno dell'albero. All'interno dello stesso albero si potranno poi inserire anche gli altri -oggetti visti attraverso l'interfaccia che manipola i file come le FIFO, i +oggetti visti attraverso l'interfaccia che manipola i file come le fifo, i link, i socket e gli stessi i file di dispositivo (questi ultimi, per convenzione, sono inseriti nella directory \file{/dev}). @@ -87,7 +89,7 @@ directory; l'albero viene appunto creato inserendo directory in altre directory. Il nome completo di file generico è composto da una serie di nomi separati da -una \texttt{/} (in Linux più \texttt{/} consecutive sono considerate +una \file{/} (in Linux più \file{/} consecutive sono considerate equivalenti ad una sola). Il nome completo di un file viene usualmente chiamato \textit{pathname}, e anche se il manuale della glibc depreca questo nome (poiché genererebbe confusione, dato che con \textit{path} si indica @@ -104,7 +106,7 @@ precedente: ovviamente perch indicati come directory esistano e siano effettivamente directory, inoltre i permessi devono consentire l'accesso. -Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice +Se il pathname comincia per \file{/} la ricerca parte dalla directory radice del processo; questa, a meno di un \textit{chroot} (su cui torneremo in seguito, vedi \secref{sec:xxx_chroot}) è la stessa per tutti i processi ed equivale alla directory radice dell'albero (come descritto in @@ -197,7 +199,7 @@ L'interfaccia 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 file descriptors sono rappresentati da numeri interi (cioè +dispositivi); i file descriptor sono rappresentati da numeri interi (cioè semplici variabili di tipo \type{int}). L'interfaccia è definita nell'header \file{unistd.h}. @@ -213,12 +215,12 @@ del C, si accede ad essi sempre in maniera indiretta utilizzando il tipo \type{FILE *}. L'interfaccia è definita nell'header \type{stdio.h}. Entrambe le interfacce possono essere usate per l'accesso ai file come agli -altri oggetti del VFS (pipe, socket, device), ma per poter accedere alle -operazioni di controllo sul particolare tipo di oggetto del VFS scelto occorre -usare l'interfaccia standard di unix coi file descriptors. Allo stesso modo -devono essere usati i file descriptor se si vuole ricorrere a modalità -speciali di I/O come il polling o il non-bloccante (vedi -\secref{sec:file_xxx}). +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 file descriptor. Allo stesso modo devono essere usati i +file descriptor se si vuole ricorrere a modalità speciali di I/O come il +polling o il non-bloccante (vedi \secref{sec:file_noblocking}). Gli stream forniscono un'interfaccia di alto livello costruita sopra quella dei file descriptor, che tratta tutti i file nello stesso modo, con @@ -316,6 +318,7 @@ l'\acr{ext2}, come esempio di un filesystem unix-like. % abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione % nel kernel) in \secref{sec:file_vfs}. + \subsection{Il \textit{virtual filesystem} di Linux} \label{sec:file_vfs} @@ -343,7 +346,7 @@ di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig. \begin{figure}[htb] \centering - \includegraphics[width=7cm]{img/vfs.eps} + \includegraphics[width=7cm]{img/vfs} \caption{Schema delle operazioni del VFS} \label{fig:file_VFS_scheme} \end{figure} @@ -356,7 +359,7 @@ e 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 -\func{register\_filesystem} passandole un'apposita struttura +\code{register\_filesystem} passandole un'apposita struttura (\var{file\_system\_type}) che contiene i dettagli per il riferimento all'implementazione del medesimo, che sarà aggiunta alla citata tabella. @@ -374,7 +377,7 @@ Il primo oggetto usato dal VFS 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 decriptor per accedere alle routine +usare le funzioni contenute nel filesystem descriptor per accedere alle routine specifiche di quel filesystem. Gli altri due descrittori usati dal VFS sono relativi agli altri due oggetti @@ -391,34 +394,36 @@ file gi \label{sec:file_vfs_work} La funzione più fondamentale implementata dal VFS è la system call -\texttt{open} che permette di aprire un file. Dato un pathname viene eseguita +\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. -Una singola 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, 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. - -Le 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 dentry. - -La 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 dcache cioè contiene solo le dentry per i file per i quali è stato -richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve -creare una nuova dentry e caricare l'inode corrispondente in memoria. - -Questo procedimento viene eseguito dal metodo \func{lookup()} dell'inode +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. + +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}. + +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 +pathname il VFS deve creare una nuova \textit{dentry} e caricare l'inode +corrispondente in memoria. + +Questo procedimento viene eseguito dal metodo \code{lookup()} dell'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. @@ -430,12 +435,12 @@ dell'inode e passarli in user space. L'apertura di un file richiede comunque un'altra operazione, l'allocazione di una struttura di tipo \var{file} in cui viene inserito un puntatore alla -dentry e una struttura \verb|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 \secref{sec:file_fd}). Un elenco delle operazioni -previste dal kernel è riportato in \ntab. +\textit{dentry} e una struttura \var{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 \secref{sec:file_fd}). Un elenco delle +operazioni previste dal kernel è riportato in \ntab. \begin{table}[htb] \centering @@ -445,20 +450,20 @@ previste dal kernel \textbf{Funzione} & \textbf{Operazione} \\ \hline \hline - \textsl{\func{open}} & apre il file \\ - \textsl{\func{read}} & legge dal file \\ - \textsl{\func{write}} & scrive sul file \\ - \textsl{\func{llseek}} & sposta la posizione corrente sul file \\ - \textsl{\func{ioctl}} & accede alle operazioni di controllo + \textsl{\code{open}} & apre il file \\ + \textsl{\code{read}} & legge dal file \\ + \textsl{\code{write}} & scrive sul file \\ + \textsl{\code{llseek}} & sposta la posizione corrente sul file \\ + \textsl{\code{ioctl}} & accede alle operazioni di controllo (tramite la \func{ioctl})\\ - \textsl{\func{readdir}}& per leggere il contenuto di una directory \\ - \textsl{\func{poll}} & \\ - \textsl{\func{mmap}} & chiamata dalla system call \func{mmap}. + \textsl{\code{readdir}}& per leggere il contenuto di una directory \\ + \textsl{\code{poll}} & \\ + \textsl{\code{mmap}} & chiamata dalla system call \func{mmap}. mappa il file in memoria\\ - \textsl{\func{release}}& chiamata quando l'ultima referenza a un file + \textsl{\code{release}}& chiamata quando l'ultima referenza a un file aperto è chiusa\\ - \textsl{\func{fsync}} & chiamata dalla system call \func{fsync} \\ - \textsl{\func{fasync}} & chiamate da \func{fcntl} quando è abilitato + \textsl{\code{fsync}} & chiamata dalla system call \func{fsync} \\ + \textsl{\code{fasync}} & chiamate da \func{fcntl} quando è abilitato il modo asincrono per l'I/O su file. \\ \hline \end{tabular} @@ -469,12 +474,12 @@ previste dal kernel 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 \verb|f_ops| appropriata al tipo +utilizzare la 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 -\textit{seek}) non saranno disponibili, però con questo sistema l'utilizzo di +\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. @@ -494,16 +499,16 @@ comuni di un qualunque filesystem standard unix. Dato un disco lo spazio fisico 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 ext2, che prevede una separazione dei dati in -\textit{blocks group} che replicano il superblock (ma sulle caratteristiche di -ext2 torneremo in \secref{sec:file_ext2}). È comunque caratteristica +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 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.eps} + \includegraphics[width=9cm]{img/disk_struct} \caption{Organizzazione dello spazio su un disco in partizioni e filesystem} \label{fig:file_disk_filesys} \end{figure} @@ -516,7 +521,7 @@ esemplificare la situazione con uno schema come quello esposto in \nfig. \begin{figure}[htb] \centering - \includegraphics[width=11cm]{img/filesys_struct.eps} + \includegraphics[width=11cm]{img/filesys_struct} \caption{Strutturazione dei dati all'interno di un filesystem} \label{fig:file_filesys_detail} \end{figure} @@ -569,7 +574,7 @@ chiarezza abbiamo aggiunto dei numeri di inode. \begin{figure}[htb] \centering - \includegraphics[width=11cm]{img/dir_links.eps} + \includegraphics[width=11cm]{img/dir_links} \caption{Organizzazione dei link per le directory} \label{fig:file_dirs_link} \end{figure} @@ -582,11 +587,12 @@ 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 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 \textsl{ext2}. Esso supporta tutte le + 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. @@ -599,14 +605,14 @@ seguenti: kernel quando agisce su gruppi di file. Possono essere settati 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 SYSV come opzioni di +\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 SYSV comporta che i file vengono creati con l'identificatore del + 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 sgid settato (per una descrizione dettagliata del significato di questi - termini si veda \secref{sec:file_access_control}), nel qual caso file e - sotto-directory ereditano sia il \acr{gid} che lo \acr{sgid}. + di \acr{sgid} settato (per una descrizione dettagliata del significato di + questi termini si veda \secref{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). @@ -631,17 +637,16 @@ 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.eps} + \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 raggrupamenti di blocchi ha inoltre degli effetti positivi nelle +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 -inodes. +inode. Le directory sono implementate come una linked list con voci di dimensione variabile. Ciascuna voce della lista contiene il numero di inode, la sua @@ -651,5 +656,3 @@ in questo modo - -