Nuova figura sui processi e rifiniture varie
[gapil.git] / fileintro.tex
index 3715f895158fb7405ddfb97480c89f198d2d0cbd..927dc4da827076a43c36d233593b5aa7e2d8d5cd 100644 (file)
@@ -1,10 +1,11 @@
 \chapter{L'architettura dei file}
 \label{cha:file_intro}
 
-Uno dei concetti fondamentali della architettura di unix è il cosiddetto
-\textit{everything is a file}, cioè il fatto che l'accesso ai vari dispositivi
-di input/output del computer viene effettuato attraverso un'interfaccia
-astratta che tratta le periferiche allo stesso modo degli usuali file di dati.
+Uno dei concetti fondamentali dell'architettura di un sistema Unix è il
+cosiddetto \textit{everything is a file}, cioè il fatto che l'accesso ai vari
+dispositivi di input/output del computer viene effettuato attraverso
+un'interfaccia astratta che tratta le periferiche allo stesso modo dei normali
+file di dati.
 
 Questo significa che si può accedere a qualunque periferica del computer,
 dalla seriale, alla parallela, alla console, e agli stessi dischi attraverso i
@@ -13,113 +14,100 @@ speciali agendo sui quali i programmi possono leggere, scrivere e compiere
 operazioni direttamente sulle periferiche, usando le stesse funzioni che si
 usano per i normali file di dati.
 
-In questo capitolo forniremo un'introduzione all'architettura della gestione
-dei file, sia nelle sue caratteristiche generiche comuni a tutti gli unix, che
-nelle particolarità che ha la specifica implementazione usata da Linux. Al
-contempo tratteremo l'organizzazione dei file in un sistema unix-like, e le
-varie caratteristiche distintive.
+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'organizzazione di file e directory}
-\label{sec:file_organization}
-
-Il primo passo nella trattazione dell'architettura della gestione dei file in
-un sistema unix-like, è quello dell'esame di come essi vengono organizzati e
-di quale è la struttura che hanno all'interno del sistema.
-
+\section{L'architettura dell'accesso}
+\label{sec:file_access_arch}
 
-\subsection{La struttura di file e directory}
-\label{sec:file_file_struct}
+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.
+% (approfondiremo tutto ciò in \secref{sec:file_arch_func}).
 
-Partiamo allora da come viene strutturata nel sistema la disposizione dei
-file: per potervi accedere il kernel usa una apposita interfaccia che permetta
-di accedere all'informazione tenuta sullo spazio grezzo disponibile sui
-dischi, cioè quello che si chiama un \textit{filesystem}\footnote{useremo per
-  brevità questo nome al posto della più prolissa traduzione italiana sistema
-  di file}, che descriveremo in dettaglio in \secref{sec:file_vfs}.
+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 e le loro caratteristiche.
 
-Sarà attraverso quest'ultimo che il kernel andrà a gestire l'accesso ai dati
-memorizzati all'interno del disco stesso, strutturando l'informazione in file
-e directory.  Per poter accedere ai file contenuti in un disco occorrerà
-perciò attivare il filesystem, questo viene fatto \textsl{montando} il disco
-(o la partizione del disco).
 
-%In generale un filesystem piazzerà opportunamente sul disco dei blocchi di
-%informazioni riservate che tengono conto degli inodes allocati, di quelli
-%liberi, e delle posizioni fisiche su disco dei dati contenuti nei file, per
+\subsection{L'organizzazione di file e directory}
+\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 (la directory
-di \textit{root}) 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.
+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
+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 dischi devono poi essere inseriti
-nell'albero utilizzando opportune subdirectory.
+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.
 
 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 già
-specificato in \secref{sec:file_vfs}, è 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 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 glibc depreca questo
-nome (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 processo con cui si associa ad un pathname uno specifico file è chiamato
+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 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}.
+  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}
@@ -127,9 +115,9 @@ sia la directory radice allora il riferimento 
 
 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}) 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.
+\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
+\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
@@ -146,7 +134,8 @@ dati) in base al loro contenuto, o tipo di accesso.
       \textit{regular file} & \textsl{file normale} &
       un file che contiene dei dati (l'accezione normale di file) \\
       \textit{directory} & \textsl{cartella o direttorio} &
-      un file che contiene una lista di nomi associati a degli inodes \\
+      un file che contiene una lista di nomi associati a degli \textit{inodes}
+      (vedi \secref{sec:file_vfs}).  \\
       \textit{symbolic link} & \textsl{collegamento simbolico} &
       un file che contiene un riferimento ad un altro file/directory \\
       \textit{char device} & \textsl{dispositivo a caratteri} &
@@ -190,61 +179,62 @@ In unix le modalit
 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
@@ -287,8 +277,9 @@ 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, 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
@@ -297,20 +288,20 @@ esempio il codice C normalmente si mette in file con l'estensione .c, ma
 questa è, appunto, solo una convenzione.
 
 
-\section{L'architettura della gestione dei file}
-\label{sec:file_architecture}
+\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
@@ -352,9 +343,10 @@ di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig.
 \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: filesystem, inode
-e file, corrispondenti a tre apposite strutture definite nel kernel.
+implementare. L'interfaccia comprende tutte le funzioni che riguardano i file;
+le operazioni sono suddivise su tre tipi di oggetti: \textit{filesystem},
+\textit{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
@@ -363,7 +355,6 @@ filesystem tutto quello che occorre 
 (\var{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
@@ -489,7 +480,7 @@ diversi filesystem (come quelli usati da Windows o MacOs) 
 
 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
-filesystem. Una delle caratteristiche di Linux rispetto agli altri unix è
+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 non entreremo nei dettagli di un filesystem specifico, ma
@@ -656,3 +647,8 @@ in questo modo 
 
 
 
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: