permettono di fare riferimento allo stesso file chiamandolo con nomi diversi
o accedendovi da directory diverse.
-Questo è possibile anche in ambiente unix, dove tali collegamenti sono
+Questo è possibile anche in ambiente Unix, dove tali collegamenti sono
usualmente chiamati \textit{link}; ma data la struttura del sistema di
gestione dei file (ed in particolare quanto trattato in
-\secref{sec:file_architecture}) ci sono due metodi sostanzialmente diversi per
+\secref{sec:file_arch_func}) ci sono due metodi sostanzialmente diversi per
fare questa operazione.
-Come spiegato in \secref{sec:file_filesystem} l'accesso al contenuto di
-un file su disco avviene attraverso il suo inode, e il nome che si trova in
-una directory è solo una etichetta associata ad un puntatore a che fa
+Come spiegato in \secref{sec:file_filesystem} l'accesso al contenuto di un
+file su disco avviene attraverso il suo inode\index{inode}, e il nome che si
+trova in una directory è solo una etichetta associata ad un puntatore a che fa
riferimento al suddetto inode.
Questo significa che la realizzazione di un link è immediata in quanto uno
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso la variabile \var{errno} restituisce i valori:
\begin{errlist}
- \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta i
- link simbolici.
+ \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta
+ i link simbolici.
\item[\macro{ENOENT}] una componente di \param{newpath} non esiste o
\param{oldpath} è una stringa vuota.
\item[\macro{EEXIST}] esiste già un file \param{newpath}.
specificati dalle variabili \var{owner} e \var{group}.
\bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per
- un errore, in caso di errore \texttt{errno} viene settato ai valori:
+ un errore, in caso di errore \var{errno} viene settato ai valori:
\begin{errlist}
\item[\macro{EPERM}] L'\textit{effective user id} non corrisponde a quello
del proprietario del file o non è zero, o utente e gruppo non sono validi
di lavoro corrente, ha anche una directory radice, che è la directory che per
il processo costituisce la radice dell'albero dei file e rispetto alla quale
vengono risolti i pathname assoluti (si ricordi quanto detto in
-\secref{sec:file_file_struct})
-
+\secref{sec:file_organization}).
La radice viene eredidata dal padre per ogni processo figlio; come si può
vedere da \figref{fig:proc_task_struct} è tenuta nella struttura
\type{fs\_struct} insieme alla directory di lavoro corrente e alla
\var{umask}, e quindi di norma coincide con la \file{/} del sistema.
-
-
In certe situazioni però per motivi di sicurezza non si vuole che un processo
possa accedere a tutto il filesystem; per questo si può cambiare la directory
radice con la funzione \func{chroot}, il cui prototipo è:
\begin{prototype}{unistd.h}{int chroot(const char *path)}
Cambia la directory radice del processo a quella specificata da
- \param{path}..
+ \param{path}.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per
- un errore, in caso di errore \texttt{errno} viene settato ai valori:
+ un errore, in caso di errore \var{errno} viene settato ai valori:
\begin{errlist}
\item[\macro{EPERM}] L'\textit{effective user id} non è zero.
\end{errlist}
\macro{ENOMEM}, \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP};
\macro{EROFS} e \macro{EIO}.}
\end{prototype}
-
-
-
-
-
-un caso tipico è quello di un server
-ftp che dovrebbe limitarsi
-
-
-Il sistema però consente di cambiare questa directory con la funzione
-\func{chroot}
+\noindent in questo modo la directory radice del processo diventerà
+\param{path} (che ovviamente deve esistere) ed ogni pathname assoluto sarà
+risolto a partire da essa, rendendo impossibile accedere alla parte di albero
+sovrastante; si ha cioè quella che viene chiamata una \textit{chroot jail}.
+
+Solo l'amministratore può usare questa funzione, e la nuova radice, per quanto
+detto in \secref{sec:proc_fork}, sarà ereditata da tutti i processi figli. Si
+tenga presente che la funzione non cambia la directory di lavoro corrente, che
+potrebbe restare fuori dalla \textit{chroot jail}.
+
+Un caso tipico di uso di \func{chroot} è quello di un server ftp, in questo
+caso infatti si vuole che il server veda solo i file che deve trasferire, per
+cui in genere si una \textit{chroot jail} alla directory che contiene i file.
+Si tenga presente però che in questo caso occorrerà replicare all'interno
+della \textit{chroot jail} tutti i file (in genere programmi e librerie) di
+cui il server potrebbe avere bisogno.
%%% Local Variables:
operazioni direttamente sulle periferiche, usando le stesse funzioni che si
usano per i normali file di dati.
-In questo capitolo forniremo una panoramica dell'architettura dei file, sia
-nelle sue caratteristiche generali, comuni a tutti gli Unix, che nelle
-particolarità che ha la specifica implementazione usata da Linux.
+In questo capitolo forniremo una descrizione dell'architettura dei file in
+Linux, iniziando da una panoramica sulle caratteristiche principali delle
+interfacce con cui i processi accedono ai file (che tratteremo in dettaglio
+nei capitoli seguenti), per poi passare ad una descrizione più dettagliata
+delle modalità con cui detto accesso viene realizzato dal sistema.
-\section{L'architettura dell'accesso ai file}
+\section{L'architettura dell'accesso}
\label{sec:file_access_arch}
Per poter accedere ai file il kernel deve mettere a disposizione dei programmi
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 attraverso quello che
-viene chiamato il \textsl{montaggio} del filesystem.
+\textit{filesystem}, essa poi viene resa disponibile ai processi attraverso
+quello che viene chiamato il \textsl{montaggio} del filesystem.
% (approfondiremo tutto ciò in \secref{sec:file_arch_func}).
In questa sezione faremo una panormamica generica su come il sistema presenta
i file ai processi, trattando l'organizzazione di file e directory, i tipi di
-file ed introducendo le interfacce disponibili, che saranno approfondite nei
-capitoli seguenti.
+file ed introducendo le interfacce disponibili e le loro caratteristiche.
\subsection{L'organizzazione di file e directory}
-\label{sec:file_file_struct}
+\label{sec:file_organization}
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. Pertanto
-un file viene identificato dall'utente usando quello che viene chiamato
-\textit{pathname}, cioè il percorso che si deve fare per accedere al file.
+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
+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 utilizzando opportune
-subdirectory.
+altri dispositivi devono 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
-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
-link, i socket e gli stessi i file di dispositivo (questi ultimi, per
-convenzione, sono inseriti nella directory \file{/dev}).
-
-L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
-medesimi nell'albero descritto in precedenza; una directory comunque, come
-vedremo in \secref{sec:file_vfs_work}, è solo un particolare tipo di file che
-contiene le informazioni che associano un nome al contenuto.
-
-% Per questo, anche se è usuale parlare di ``file in una directory'' in realtà
-% una directory contiene solo delle etichette per fare riferimento ai file
-% stessi.
-
-I manuale delle \acr{glibc} chiama i nomi contenuti nelle directory
-\textsl{componenti} (in inglese \textit{file name components}), noi li
-chiameremo più semplicemente \textit{nomi}. Un file può essere indicato
-rispetto alla directory corrente semplicemente specificando il nome da essa
-contenuto. Una directory contiene semplicemente un elenco di questi nomi, che
-possono corrispondere a un qualunque oggetto del filesystem, compresa un'altra
-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 \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 \acr{glibc} depreca questa
-nomenclatura\footnote{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 è
-senz'altro più chiaro dell'alternativa proposta.
-
-Il procedimento con cui si associa ad un pathname uno specifico file è
-chiamato risoluzione del nome (\textit{file name resolution} o
-\textit{pathname resolution}). La risoluzione viene fatta esaminando il
-pathname da destra a sinistra e localizzando ogni nome nella directory
-indicata dal nome precedente: ovviamente perché il procedimento funzioni
-occorre che i nomi indicati come directory esistano e siano effettivamente
-directory, inoltre i permessi devono consentire l'accesso.
-
-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:file_chroot}) è la stessa per tutti i processi ed
-equivale alla directory radice dell'albero (come descritto in
-\secref{sec:file_organization}): in questo caso si parla di un pathname
-\textsl{assoluto}. Altrimenti la ricerca parte dalla directory corrente (su
-cui torneremo più avanti in \secref{sec:file_work_dir}) ed il pathname è
-detto \textsl{relativo}.
+stesso, ma anche essi devono essere montati all'interno dell'albero dei file.
+
+Una directory, come vedremo in maggior dettaglio in
+\secref{sec:file_vfs_work}, è anch'essa un file, solo che è un file
+particolare che il kernel riconosce come tale. Il suo scopo è quello di
+contenere una lista di nomi di file e le informazioni che associano ciascun
+nome al contenuto. Dato che questi nomi possono corrispondere ad un qualunque
+oggetto del filesystem, compresa un'altra directory, si ottiene naturalmente
+un'organizzazione ad albero inserendo directory in altre directory.
+
+Un file può essere indicato rispetto alla directory corrente semplicemente
+specificandone il nome\footnote{Il manuale delle \acr{glibc} chiama i nomi
+ contenuti nelle directory \textsl{componenti} (in inglese \textit{file name
+ components}), noi li chiameremo più semplicemente \textit{nomi}.} da essa
+contenuto. All'interno dello stesso albero si potranno poi inserire anche
+tutti gli altri 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}).
+
+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
+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
+esistano e siano effettivamente directory, inoltre i permessi (si veda
+\secref{sec:file_access_control}) devono consentire l'accesso.
+
+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
+\secref{sec:file_chroot}) è la stessa per tutti i processi ed equivale alla
+directory radice dell'albero dei file: in questo caso si parla di un
+\textsl{pathname assoluto}\index{pathname assoluto}. Altrimenti la ricerca
+parte dalla directory corrente (su cui torneremo in
+\secref{sec:file_work_dir}) ed il pathname è detto \textsl{pathname
+ 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
-secondo alla directory \textsl{genitrice} (\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.
+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.
\subsection{I tipi di file}
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 Virtual
-File System è riportato in \ntab.
+utilizzabili con Linux. L'elenco dei vari tipi di file definiti dal
+\textit{Virtual File System}\index{Virtual File System} è riportato in \ntab.
Si tenga ben presente che questa classificazione non ha nulla a che fare con
la classificazione sui tipi di file (che in questo caso sono sempre file 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 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}.
+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}.
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 file descriptor sono rappresentati da numeri interi (cioè
-semplici variabili di tipo \type{int}). L'interfaccia è definita
-nell'header \file{unistd.h}.
+dispositivi); i \textit{file descriptor}\index{file descriptor} sono
+rappresentati da numeri interi (cioè semplici variabili di tipo \type{int}).
+L'interfaccia è definita nell'header \file{unistd.h}.
-La seconda interfaccia è quella che il manuale della glibc chiama degli
-\textit{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}.
+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}.
Questa è l'interfaccia standard specificata dall'ANSI C e perciò si trova
-anche su tutti i sistemi non unix. Gli 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}.
+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}.
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 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
-l'eccezione di poter scegliere tra diversi stili di bufferizzazione. Il
-maggior vantaggio degli stream è che l'interfaccia per le operazioni di
-input/output è enormemente più ricca di quella dei file descriptor, che
-provvedono solo funzioni elementari per la lettura/scrittura diretta di
-blocchi di byte. In particolare gli 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.
+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}).
+
+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.
In ogni caso, dato che gli stream sono implementati sopra l'interfaccia
-standard di unix, è sempre possibile estrarre il file descriptor da uno stream
-ed eseguirvi operazioni di basso livello, o associare in un secondo tempo uno
-stream ad un file descriptor.
+standard di Unix, è sempre possibile estrarre il \textit{file descriptor} da
+uno stream ed eseguirvi operazioni di basso livello, o associare in un secondo
+tempo uno \textit{stream} ad un \textit{file descriptor}.
In generale, se non necessitano specificatamente le funzionalità di basso
-livello, è opportuno usare sempre gli stream per la loro maggiore portabilità
-essendo questi ultimi definiti nello standard ANSI C; l'interfaccia con i file
-descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è
-pertanto di portabilità più limitata.
+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}
+\subsection{Caratteristiche specifiche dei file in Unix}
\label{sec:fileint_unix_spec}
Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
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, quando tratteremo l'input/output sui file,
-esaminando in dettaglio come tutto ciò viene realizzato.
+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
questa è, appunto, solo una convenzione.
-\section{L'architettura della gestione dei file}
+\section{L'architettura di funzionamento}
\label{sec:file_arch_func}
Per capire fino in fondo le proprietà di file e directory in un sistema
-unix-like ed il funzionamento delle relative funzioni di manipolazione occorre
-una breve introduzione sulla gestione dei medesimo 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}.
+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}.
In questa sezione esamineremo come viene implementato l'accesso ai file in
Linux, come il kernel può gestire diversi tipi di filesystem, descrivendo
-poi in maniera un po' più dettagliata il filesystem standard di Linux,
-l'\acr{ext2}, come esempio di un filesystem unix-like.
+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}.
% in particolare si riprenderà, approfondendolo sul piano