Initial revision
[gapil.git] / files.tex
1 \chapter{I files}
2 \label{cha:files}
3
4 Uno dei concetti fondamentali del design di unix è il cosiddetto
5 \textit{everything is a file}, cioè il fatto che l'accesso alle periferiche
6 viene gestito attraverso un'interfaccia astratta che tratta nello stesso modo
7 sia i normali file di dati che le periferiche. Si può accedere cioè a queste
8 ultime (con l'eccezione delle interfacce di rete) attraverso i cosiddetti file
9 di dispositivo (i \textit{device files}) che permettono ai programmi di
10 interfacciarsi alle varie periferiche come la seriale, la parallela, la
11 console, e gli stessi dischi.
12
13 \section{Concetti generali sui files}
14 \label{sec:file_gen}
15
16 Per poter accedere ai singoli file su disco è necessario l'uso di un
17 \textit{filesystem}, cioè di un'interfaccia del kernel che permetta di
18 strutturare l'informazione tenuta sullo spazio grezzo disponibile sui dischi
19 in files e directory. Sarà quest'ultimo a gestire l'accesso ai dati
20 memorizzati all'interno del disco stesso, e l'uso delle normali directory e
21 files.
22
23 %In generale un filesystem piazzerà opportunamente sul disco dei blocchi di
24 %informazioni riservate che tengono conto degli inodes allocati, di quelli
25 %liberi, e delle posizioni fisiche su disco dei dati contenuti nei files, per
26
27 Per poter accedere ai file contenuti in un disco occorrerà poi attivare il
28 filesystem \textit{montando} il disco (o la partizione del disco). 
29
30 In unix, a differenza di quanto avviene in altri sistemi operativi, tutti i
31 file vengono tenuti all'interno di un unico albero la cui radice (la directory
32 di \textit{root}) viene montata all'avvio. Pertanto un file viene identificato
33 dall'utente usando il suo \textit{pathname}, cioè il percorso completo che si
34 deve fare a partire dalla radice, per accedere al file.
35
36 Dopo la fase di inizializzazione il kernel riceve dal boot loader
37 l'indicazione di quale dispositivo contiene il filesystem da usare come punto
38 di partenza e questo viene montato come radice dell'albero (cioè nella
39 directory \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti
40 nell'albero utilizzando opportune sottodirectory (in genere sotto
41 \texttt{/mnt}) .
42
43 Alcuni filesystem speciali (come \texttt{/proc} che contiene un'interfaccia ad
44 alcune strutture interne del kernel) sono generati automaticamente dal kernel
45 stesso, ma anche essi devono essere montati all'interno dell'albero.
46
47 All'interno dello stesso albero si potranno poi inserire anche gli altri
48 oggetti visti attraverso l'interfaccia che manipola i files come le FIFO, i
49 link, i socket e gli stessi i file di dipositivo (questi ultimi, per
50 convenzione, sono inseriti nella directory \texttt{/dev}).
51
52 \subsection{Il \textit{virtual filesystem} di linux}
53 \label{sec:file_vfs}
54
55 Esamineremo adesso come viene implementato l'accesso ai files in linux. Questa
56 sezione riporta informazioni sui dettagli di come il kernel gestisce i files,
57 ed è basata sul documento di Richard Goochs distribuito coi sorgenti del
58 kernel (\texttt{linux/Documentation/vfs.txt}).
59
60 L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
61 una prima lettura; è bene però tenere presente che vengono intodotti qui
62 alcuni termini che potranno comparire in seguito, come \textit{imode},
63 \textit{dentry}, \textit{dcache}.
64
65 In linux il concetto di \textit{everything is a file} è stato implementato
66 attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
67 l'interfaccia astratta che il kernel rende disponibile ai programmi in user
68 space attraverso la quale vengono manipolati i files, esso provvede anche
69 un'astrazione delle operazioni di manipolazione sui files che permette la
70 coesistenza di diversi filesystem all'interno dello stesso kernel.
71
72 La funzione più importante implementata dal VFS è la system call \texttt{open}
73 che permette di aprire un file. Dato un pathname viene eseguita una ricerca
74 dentro la \textit{directory entry cache} (la \textit{dcache}) una tabella di
75 hash che contiene tutte le \textit{directory entry} (in breve \textit{dentry})
76 che permette di associare in maniera rapida ed efficiente il pathname a una
77 specifica dentry.
78
79 Una singola dentry contiene in genere il puntatore ad un \textit{inode};
80 quest'ultimo è la struttura base che sta sul disco e che identifica un singolo
81 oggetto del VFS che può essere un file, una directory, una FIFO, un file di
82 dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal
83 VFS (sui tipi di files possibili torneremo in seguito).
84
85 Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono
86 usate per motivi di velocità, gli inodes invece vivono su disco e vengono
87 copiati in memoria quando serve, ed ogni cambiamento viene copiato
88 all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS
89 ed è ad essi che puntano le singole dentry.
90
91 La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
92 files, ovviamente per non riempire tutta la memoria questa vista è parziale
93 (la dcache cioè contiene solo le dentry per i file per i quali è stato
94 richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve
95 creare una nuova dentry e caricare l'inode corrispondente in memoria. 
96
97 Questo procedimento viene eseguito dalla metodo \texttt{lookup()} dell'inode
98 della directory che contiene il file; esso viene installato dallo specifico
99 filesystem su cui l'inode va a vivere.
100
101 Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
102 diventa possibile accedere a operazioni sul file come la \texttt{open} per
103 aprire il file o la \texttt{stat} per leggere i dati dell'inode e passarli in
104 user space.
105
106 L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
107 una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla
108 dentry e una struttura \verb|f_ops| che contiene i puntatotori ai metodi che
109 implementano le operazioni disponibili sul file. In questo modo i processi in
110 use space possono accedere alle operazioni attraverso detti metodi, che
111 saranno diversi a seconda del tipo di file (o dispositivo) aperto. Un elenco
112 delle operazioni disponibili è riportato in \ntab.
113
114 % La struttura file viene poi inserita nella tavola dei file
115 % , non
116 % tutte le operazioni possibili sono definite per tutti i dispositivi; un elenco
117 % delle operazioni definite in linux è riportato in \ntab.
118
119 \begin{table}[htb]
120   \centering
121   \begin{tabular}[c]{c l}
122     \textbf{funzione} & \textbf{operazione} \\
123     \hline
124     open & apre il file \\
125     read & legge dal file \\
126     write & scrive sul file \\ 
127     llseek & sposta la posizione corrente sul file \\
128     ioctl & accede alle operazioni di controllo (tramite la \texttt{ioctl})\\
129     readdir & per leggere il contenuto di una directory \\
130     poll & \\
131     mmap & chiamata dalla system call \texttt{mmap} \\
132     release & chiamata quando l'ultima referenza a un file aperto è chiusa\\
133     fsync & chiamata dalla system call \texttt{fsync} \\
134     fasync & chiamate da \texttt{fcntl} quando è abilitato il modo asincrono
135     per l'I/O su file. \\
136     \hline
137   \end{tabular}
138   \caption{Operazioni sui file definite nel VFS.}
139   \label{tab:file_operations}
140 \end{table}
141
142 In questo modo per ciascun file diventano utilizzabili una serie di operazioni
143 (non è dette che tutte siano disponibili), che costituiscono l'interfaccia
144 astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad
145 utilizzare la opportuna routine dichiarata in \verb|f_ops| appropriata al tipo
146 di file in questione. 
147
148 Così sarà possibile scrivere sulla porta seriale come su un file di dati
149 normale; ovviamente certe operazioni (nel caso la \textit{seek}) non saranno
150 disponibili, però con questo sistema l'utilizzo di diversi filesystem è
151 immediato e (relativamente) trasparente per l'utente ed il programmatore.
152
153 \subsection{Proprietari e permessi}
154 \label{sec:file_perms}
155
156 In unix è implementata da qualunque filesystem standard una forma elementare
157 (ma adatta alla maggior parte delle esigenze) di controllo di accesso ai
158 files. Torneremo sull'argomento in dettaglo più avanti, qui ci limitiamo ad
159 una introduzione dei concetti essenziali.
160
161 Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo unix,
162 e non è detto che sia applicabile (ed infatti non è vero per il filesystem di
163 windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
164 di implementare le ACL (\textit{Access Control List}) che sono un meccanismo
165 di controllo di accesso molto più sofisticato.
166
167 Ad ogni file unix associa sempre l'utente che ne è proprietario (il cosiddetto
168 \textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
169 gid spiegato in \ref{sec:intro_usergroup}, e un insieme di permessi che sono
170 divisi in tre classi, e cioè attribuiti rispettivamente al proprietario, a
171 qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti gli
172 altri utenti.
173
174 I permessi sono espressi da un insieme di 12 bit, di questi i nove meno
175 significativi sono usati a gruppi di tre per indicare i permessi base di
176 lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere
177 \textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al
178 proprietario, al gruppo, a tutti. I restanti tre bit sono usati per indicare
179 alcune caratteristiche più complesse (\textit{suid}, \textit{sgid}, e
180 \textit{sticky}) su cui torneremo in seguito.
181
182 Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
183 processo cerca l'accesso al file esso controlla i propri uid e gid
184 confrontandoli con quelli del file e se l'operazione richiesta è compatibile
185 con i permessi associati al file essa viene eseguita, altrimenti viene
186 bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
187 viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
188 pertanto accesso senza restrizione a qualunque file del sistema.
189
190 In realtà il procedimento è più complesso di quanto descritto in maniera
191 elementare qui, in quanto ad un processo sono associati diversi
192 identificatori, torneremo su questo in maggiori dettagli in seguito in
193 \ref{sec:proc_perms}.
194
195 \subsection{I tipi di files}
196 \label{sec:file_types}
197
198 Come detto in precedenza esistono vari tipi di oggetti implementati del VFS
199 per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco
200 dei vari tipi di file è il seguente:
201  
202 \begin{table}[htb]
203   \begin{center}
204     \begin{tabular}[c]{l l l}
205       \textit{regular file} & \textsl{file normale} &
206       un file che contiene dei dati (l'accezione normale di file) \\
207       \textit{directory} & \textsl{cartella o direttorio} &
208       un file che contiene una lista di nomi associati a degli inodes \\
209       \textit{symbolic link} & \textsl{collegamento simbolico} &
210       un file che contiene un riferimento ad un altro file/directory \\
211       \textit{char device} & \textsl{dispositivo a caratteri} &
212       un file che identifica una periferica ad accesso sequenziale \\
213       \textit{block device} & \textsl{dispositivo a blocchi} &
214       un file che identifica una periferica ad accesso diretto \\
215       \textit{fifo} & \textsl{tubo} &
216       un file speciale che identifica una linea di comunicazione software
217       (unidirezionale) \\
218       \textit{socket} & \textsl{presa}
219       un file speciale che identifica una linea di comunicazione software
220       (bidirezionale) \\
221     \end{tabular}
222     \caption{Tipologia dei file definiti nel VFS}
223     \label{tab:file_types}
224   \end{center}
225 \end{table}
226
227 Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi
228 di file (in questo caso file di dati) in base al loro contenuto, o tipo di
229 accesso.  Una delle differenze principali con altri sistemi operativi (come il
230 VMS o windows) è che per unix tutti i file di dati sono identici e contengono
231 un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
232 dal sistema file di diverso contenuto o formato (come nel caso di quella fra
233 file di testo e binari che c'è in windows) né c'è una strutturazione a record
234 per il cosiddetto ``accesso diretto'' come nel caso del VMS.
235
236 Una seconda differenza è nel formato dei file ascii; in unix la fine riga è
237 codificata in maniera diversa da windows o macintosh, in particolare il fine
238 riga è il carattere \texttt{LF} al posto del \texttt{CR} del mac e del
239 \texttt{CR LF} di windows. Questo può causare alcuni problemi qualora si
240 facciano assunzioni sul terminatore della riga.
241
242
243 \section{Una panoramica sull'I/O sui file}
244 \label{sec:file_io_base}
245
246 Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo
247 crea un canale di comunicazione che permette di eseguire una serie di
248 operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e
249 questo chiuderà il canale di comuniczione impedendo ogni ulteriore operazione.
250
251
252 \subsection{Le due interfacce ai file}
253 \label{sec:file_base_api}
254
255 In unix le modalità di accesso ai file e le relative insterfacce di
256 programmazione sono due, basate su due diversi meccanismi di connessione. 
257
258 La prima è quella dei cosiddetti \textit{file descriptor} (descrittore di
259 file), che è specifica di unix e che provvede un accesso diretto a basso
260 livello non bufferizzato, con un'interfaccia primitiva ed essenziale; i file
261 descriptors sono rappresetati da numeri interi (cioè semplici variabili di
262 tipo \texttt{int}). L'interfaccia è definita nell'header \texttt{unistd.h}.
263
264 La seconda è quella degli \textit{stream}, che provvede un'interfaccia più
265 complessa e un'accesso bufferizzato, questa è anche l'intefaccia standard
266 usata dal linguaggio C e che perciò si trova anche su tutti i sistemi non
267 unix. Gli stream sono più complessi e sono rappresentati da puntatori ad un
268 opportuno oggetto, cioè del tipo \texttt{FILE *}. L'interfaccia è definita
269 nell'header \texttt{stdio.h}.
270
271 Entrambe le interfacce possono essere usate per l'accesso ai file come agli
272 altri oggetti del VFS (pipes, socket, device), ma per poter accedere alle
273 operazioni di controllo sul particolare tipo di oggetto del VFS scelto occorre
274 usare l'interfaccia a basso livello dei file descriptor. Allo stesso modo
275 devono essere usati i file descriptor se si vuole ricorrere a modalità
276 speciali di I/O come il polling o il non-bloccante (vedi \ref{sec:file_bohhhhh}).
277
278 Gli stream però forniscono un'interfaccia di alto livello costruita sopra
279 quella dei file descriptor, e tratta tutti i file nello stesso modo, con
280 l'eccezione di poter scegliere tre diversi stili di bufferizzazione.  Il
281 maggior vantaggio degli stream è che l'interfaccia per le operazioni di
282 input/output è enormemente più ricca di quella dei file descriptor, che
283 provvedono solo funzioni elementari per la lettura/scrittura diretta di
284 blocchi di bytes.  In particolare dispongono di tutte le funzioni di
285 formattazione per l'input e l'output adatte per manipolare anche i dati in
286 forma di linee o singoli caratteri. 
287
288 In ogni caso, dato che gli stream sono implementati sopra l'interfaccia a
289 basso livello dei file decriptor, è sempre possibile extrarre il file
290 descriptor da uno stream ed eseguirvi operazioni di basso livello, o associare
291 in un secondo tempo uno stream ad un file descriptor.
292
293 In generale, se non necessitano specificamente le funzionalità di basso
294 livello, è opportuno usare sempre gli stream per la loro maggiore portabilità
295 essendo questi ultimi definito nello stadard ISO C; l'interfaccia con i file
296 descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è
297 pertanto di portabilità più limitata.
298
299 \subsection{Caratteristiche specifiche dei file in unix}
300 \label{sec:files_spec_unix}
301
302 Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
303 specifiche di unix che devono essere tenute in conto nell'acceso ai file. È
304 infatti normale che più processi o programmi possano accedere
305 contemporaneamente allo stesso file e devono poter eseguire le loro operazioni
306 indipendentemente da quello che fanno gli altri processi.
307
308 Per questo motivo le strutture usate per all'accesso ai file sono relative al
309 processo che effettua l'accesso.  All'apertura di ogni file infatti viene
310 creata all'interno del processo una apposita struttura in cui sono memorizzati
311 tutti gli attributi del medesimo, che viene utilizzata per tutte le
312 operazioni. Questa è una struttura che resta locale al processo stesso; in
313 questo modo processi diversi possono usare le proprie strutture locali per
314 accedere ai file (che può essere sempre lo stesso) in maniera assolutamente
315 indipendente.
316
317 Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i
318 sistemi POSIX uno degli attibuti di un file aperto è la posizione corrente nel
319 file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione
320 successiva. Essa è rappresentata da un numero intero che indica il numero di
321 bytes dall'inizio del file, che viene (a meno che non si apra il file in
322 append) inizializzato a zero all'apertura del medesimo. 
323
324
325 Questo è uno dei dati che viene mantento nella suddetta struttura, per cui
326 ogni processo avrà la sua posizione corrente nel file, che non sarà
327 influenzata da quello che altri processi possono fare. Anzi, aprire un file
328 significa appuntio creare ed inizializzare una tale struttura, per cui se si
329 apre due volte lo stesso file all'interno dello stesso processo, si otterrano
330 due file descriptor o due stream che avreanno ancora un posizione corrente nel
331 file assolutamente independente.
332
333 Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di
334 accesso è un riferimento all'inode del file, pertanto anche se il file viene
335 cancellato da un altro processo, sarà sempre possibile mantenere l'accesso,
336 e lo spazio su disco non verrà rilasciato fintanto che il file non sarà chiuso
337 e l'ultimo riferimento cancellato. È pertanto possibile (e pratica comune)
338 aprire un file provvisorio per cancellarlo immediatamente dopo; in questo modo
339 all'uscita del programma il file scomparità definitivamente dal disco, ma il
340 file ed il suo contenuto saranno disponibili per tutto il tempo in cui il
341 processo è attivo.
342
343
344 \subsection{L'accesso ai files: nomi e direcory}
345 \label{sec:file_names}
346
347 L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
348 medesimi nella gerarchia di directory descritta in \ref{sec:file_base}; una
349 directory comunque, come già specificato in \ref{sec:file_vfs}, è solo un
350 particolare tipo di file che il sistema riconosce come tale, che contiene le
351 informazioni che associano un inode ad un nome. Per questo, anche se è usuale
352 parlare di ``file in una directory'' in realtà una directory contiene solo dei
353 riferimenti ai file, non i file stessi.
354
355 I nomi contenuti nelle directory sono chiamati componenti (\textit{file name
356   components}), un file può essere indicato rispetto alla directory corrente
357 semplicemente specificando il nome da essa contenuto. Una directory contiene
358 semplicemente un elenco di questi componenti, che possono corrispondere a un
359 qualunque oggetto del filesystem, compresa un'altra directory.
360
361 Un nome di file è composto da una serie di componenti separati da una
362 \texttt{/} (in linux più \texttt{/} consecutive sono considerate equivalenti
363 ad una sola). Il nome completo di un file viene usualmente chiamato
364 \textit{pathname}, anche se questo può generare confusione, dato che con
365 \textit{path} si indica anche un insieme di directory su cui effettuare una
366 ricerca (ad esempio quello in cui si cercano i comandi).
367
368 Il processo con cui si associa ad un pathname uno specifico file (cioè si
369 identifica l'inode a cui fare riferimento) è chiamato risoluzione del nome
370 (\textit{file name resoluzion} o \textit{pathname resolution}).
371 La risoluzione viene fatta esaminando il pathname da destra a sinistra e
372 localizzando ogni componente nella directory indicata dal componente
373 precedente: ovviamente perchè il procedimento funzioni occorre che i
374 componenti indicati come directory esistano e siano effettivamente directory,
375 inoltre i permessi devono consenite l'accesso.
376
377
378 Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice
379 del processo che (a meno di un \textit{chroot} su cui torneremo in seguito) è
380 la stessa per tutti i processi ed equivale alla radice dell'albero
381 (\ref{sec:file_gen}): in questo caso si parla di un pathname
382 \textsl{assoluto}. Altrimenti la ricerca parte dalla directory di lavoro
383 corrente (\texit{current working directory}, su cui pure torneremo più avanti)
384 ed il pathname è detto \textsl{relativo}.
385
386 I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono
387 inseriti in ogni directory; 
388
389
390 %La struttura fondamentale che contiene i dati essenziali relativi ai file è il
391 %cosiddetto \textit{inode}; questo conterrà informazioni come il
392 %tipo di file (file di dispositivo, directory, file di dati, per un elenco
393 %completo vedi \ntab), i permessi (vedi \ref{sec:file_perms}), le date (vedi
394 %\ref{sec:file_times}).