Grande ristrutturazione volta alla eliminazione del capitolo 4, i cui
[gapil.git] / fileintro.tex
index dfd3081dc67781aa9984a8052d20dc99818db1ea..995129189d236fba35bf549e48a1364276c2cba9 100644 (file)
-\chapter{I files: introduzione}
-\label{cha:files_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.
-
-Questo significa che si può accedere cioè a qualunque periferica del computer,
-dalla seriale, alla parallela, alla console, e agli stessi dischi attraverso i
-cosiddetti file di dispositivo (i \textit{device files}). Questi sono dei file
-speciali agendo sui quali i programmi possono leggere, scrivere e compiere
-operazioni direttamente sulle perferiche, usando le stesse funzioni che si
-usano per i normali file di dati.
-
-In questo capitolo forniremo un'introduzione alle principali caratteristiche
-di questa interfaccia, su come essa viene implementata in linux e su come sono
-organizzati i file nel sistema.
-
-
-\section{I file in un sistema unix-like}
-\label{sec:fileintr_overview}
-
-Visto il ruolo fondamentale che i files vengono ad assumere in un sistema
-unix, è anzitutto opportuno fornire un'introduzione dettagliata su come essi
-vengono trattati dal sistema. In particolare occorre tenere presente dov'è che
-si situa il limite fondamentale fra kernel space e user space che tracciavamo
-al Cap.~\ref{cha:intro_unix}.
-
-Partiamo allora da come viene strutturata nel sistema la disposizione dei
-file: per potervi accedere il kernel usa una apposita interfaccia che permetta
-di strutturare l'informazione tenuta sullo spazio grezzo disponibile sui
-dischi, cioè quello che si chiama un \textit{filesystem}. 
-
-Sarà attraverso quest'ultimo che il kernel andrà a gestire l'accesso ai dati
-memorizzati all'interno del disco stesso, strutturando l'informazione in files
-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 files, per
-
-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.
-
-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 \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti
-nell'albero utilizzando opportune subdirectory.
-
-Alcuni filesystem speciali (come \texttt{/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 files come le FIFO, i
-link, i socket e gli stessi i file di dispositivo (questi ultimi, per
-convenzione, sono inseriti nella directory \texttt{/dev}).
-
-\subsection{Il \textit{virtual filesystem} di linux}
-\label{sec:fileintr_vfs}
-
-Esamineremo adesso come viene implementato l'accesso ai files in linux. Questa
-sezione riporta informazioni sui dettagli di come il kernel gestisce i files,
-ed è basata sul documento di Richard Goochs distribuito coi sorgenti del
-kernel (\texttt{linux/Documentation/vfs.txt}).
-
-L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
-una prima lettura; è bene però tenere presente che vengono introdotti qui
-alcuni termini che potranno comparire in seguito, come \textit{inode},
-\textit{dentry}, \textit{dcache}.
-
-In linux il concetto di \textit{everything is a file} è stato implementato
-attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
-l'interfaccia astratta che il kernel rende disponibile ai programmi in user
-space attraverso la quale vengono manipolati i files; esso provvede anche
-un'astrazione delle operazioni di manipolazione sui files che permette la
-coesistenza di diversi filesystem all'interno dello stesso albero.
-
-La funzione più importante implementata dal VFS è la system call \texttt{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 ``files'' 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 dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono
-usate per motivi di velocità, gli inodes invece stanno su disco e vengono
-copiati in memoria quando serve, ed ogni cambiamento viene copiato
-all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS
-ed è ad essi che puntano le singole dentry.
-
-La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
-files, 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 \texttt{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.
-
-Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
-diventa possibile accedere alle varie operazioni sul file come la
-\texttt{open} per aprire il file o la \texttt{stat} per leggere i dati
-dell'inode e passarli in user space.
-
-L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
-una struttura di tipo \texttt{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. Un elenco
-delle operazioni disponibili è riportato in \ntab.
-
-\begin{table}[htb]
-  \centering
-  \begin{tabular}[c]{c p{7cm}}
-    \textbf{funzione} & \textbf{operazione} \\
-    \hline
-    \textit{open}    & apre il file \\
-    \textit{read}    & legge dal file \\
-    \textit{write}   & scrive sul file \\ 
-    \textit{llseek}  & sposta la posizione corrente sul file \\
-    \textit{ioctl}   & accede alle operazioni di controllo 
-                       (tramite la \texttt{ioctl})\\
-    \textit{readdir} & per leggere il contenuto di una directory \\
-    \textit{poll}    & \\
-    \textit{mmap}    & chiamata dalla system call \texttt{mmap}. 
-                       mappa il file in memoria\\
-    \textit{release} & chiamata quando l'ultima referenza a un file 
-                       aperto è chiusa\\
-    \textit{fsync}   & chiamata dalla system call \texttt{fsync} \\
-    \textit{fasync}  & chiamate da \texttt{fcntl} quando è abilitato 
-                       il modo asincrono per l'I/O su file. \\
-    \hline
-  \end{tabular}
-  \caption{Operazioni sui file definite nel VFS.}
-  \label{tab:fileintr_file_operations}
-\end{table}
-
-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
-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
-diversi filesystem (come quelli usati da Windows o MacOs) è immediato e
-(relativamente) trasparente per l'utente ed il programmatore.
-
-\subsection{Il controllo di accesso}
-\label{sec:fileintr_access_ctrl}
-
-In unix è implementata da qualunque filesystem standard una forma elementare
-(ma adatta alla maggior parte delle esigenze) di controllo di accesso ai
-files. Torneremo sull'argomento in dettaglio più avanti, qui ci limitiamo ad
-una introduzione dei concetti essenziali.
-
-Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo Unix,
-e non è detto che sia applicabile (ed infatti non è vero per il filesystem di
-Windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
-di implementare le ACL (\textit{Access Control List}) che sono un meccanismo
-di controllo di accesso molto più sofisticato.
-
-Ad ogni file Unix associa sempre l'utente che ne è proprietario (il cosiddetto
-\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
-gid spiegato in Sez.~\ref{sec:intro_usergroup}, e un insieme di permessi che
-sono divisi in tre classi, e cioè attribuiti rispettivamente al proprietario,
-a qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti
-gli altri utenti.
-
-I permessi sono espressi da un insieme di 12 bit: di questi i nove meno
-significativi sono usati a gruppi di tre per indicare i permessi base di
-lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere
-\textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al
-proprietario, al gruppo, a tutti (una descrizione più dettagliata dei vari
-permessi associati ai file è riportata in \ref{sec:filedir_suid_sgid}).  I
-restanti tre bit sono usati per indicare alcune caratteristiche più complesse
-(\textit{suid}, \textit{sgid}, e \textit{sticky}) su cui pure torneremo in
-seguito (vedi \ref{sec:filedir_suid_sgid} e \ref{sec:filedir_stiky}).
-
-Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
-processo cerca l'accesso al file esso controlla i propri uid e gid
-confrontandoli con quelli del file e se l'operazione richiesta è compatibile
-con i permessi associati al file essa viene eseguita, altrimenti viene
-bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
-viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
-pertanto accesso senza restrizione a qualunque file del sistema.
-
-In realtà il procedimento è più complesso di quanto descritto in maniera
-elementare qui; inoltre ad un processo sono associati diversi identificatori,
-torneremo su questo in maggiori dettagli in seguito in \ref{sec:proc_perms}.
-
-\subsection{I tipi di files}
-\label{sec:fileintr_file_types}
-
-Come detto in precedenza esistono vari tipi di oggetti implementati del VFS
-per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco
-dei vari tipi di file è il seguente:
-\begin{table}[htb]
-  \begin{center}
-    \begin{tabular}[c]{l l p{7cm}}
-    \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Descrizione} \\
-    \hline
-      \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 \\
-      \textit{symbolic link} & \textsl{collegamento simbolico} &
-      un file che contiene un riferimento ad un altro file/directory \\
-      \textit{char device} & \textsl{dispositivo a caratteri} &
-      un file che identifica una periferica ad accesso sequenziale \\
-      \textit{block device} & \textsl{dispositivo a blocchi} &
-      un file che identifica una periferica ad accesso diretto \\
-      \textit{fifo} & \textsl{tubo} &
-      un file speciale che identifica una linea di comunicazione software
-      (unidirezionale) \\
-      \textit{socket} & \textsl{manicotto} &
-      un file speciale che identifica una linea di comunicazione software
-      (bidirezionale) \\
-    \hline
-    \end{tabular}
-    \caption{Tipologia dei file definiti nel VFS}
-    \label{tab:fileintr_file_types}
-  \end{center}
-\end{table}
-
-Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi
-di file (in questo caso file di dati) in base al loro contenuto, o tipo di
-accesso.  Una delle differenze principali con altri sistemi operativi (come il
-VMS o Windows) è che per Unix tutti i file di dati sono identici e contengono
-un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
-dal sistema file di diverso contenuto o formato (come nel caso di quella fra
-file di testo e binari che c'è in windows) né c'è una strutturazione a record
-per il cosiddetto ``accesso diretto'' come nel caso del VMS.
-%  (con i kernel
-% della serie 2.4 è disponibile una forma di accesso diretto ai dischi il
-% \textit{raw access} che però non ha nulla a che fare con questo).
-
-Una seconda differenza è nel formato dei file ascii; in Unix la fine riga è
-codificata in maniera diversa da Windows o MacIntosh, in particolare il fine
-riga è il carattere \texttt{LF} (o \verb|\n|) al posto del \texttt{CR}
-(\verb|\r|) del mac e del \texttt{CR LF} di windows. Questo può causare alcuni
-problemi qualora si facciano assunzioni sul terminatore della riga.
-
-
-\section{Una panoramica sull'uso dei file}
-\label{sec:fileintr_io_overview}
-
-Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo
-crea un canale di comunicazione che permette di eseguire una serie di
-operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e
-questo chiuderà il canale di comunicazione impedendo ogni ulteriore
-operazione.
-
-\subsection{Le due interfacce ai file}
-\label{sec:fileintr_io_api}
-
-In unix le modalità di accesso ai file e le relative interfacce di
-programmazione sono due, basate su due diversi meccanismi di connessione. 
-
-La prima è l'interfaccia standard di unix, quella che il manuale delle glibc
-chiama interfaccia dei descrittore di file (o \textit{file descriptor}).  È
-un'interfaccia specifica di unix e provvede un accesso non bufferizzato.
-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 descriptors sono rappresentati da numeri interi (cioè
-semplici variabili di tipo \texttt{int}).  L'interfaccia è definita
-nell'header \texttt{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).  Questa è
-l'interfaccia standard usata dal linguaggio 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 \texttt{FILE *}.
-L'interfaccia è definita nell'header \texttt{stdio.h}.
-
-Entrambe le interfacce possono essere usate per l'accesso ai file come agli
-altri oggetti del VFS (pipes, 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
-\ref{sec:file_bohhhhh}).
-
-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 bytes.  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.
-
-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.
-
-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.
-
-\subsection{Caratteristiche specifiche dei file in unix}
-\label{sec:fileint_unix_spec}
-
-Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
-specifiche di Unix che devono essere tenute in conto nell'accesso ai file. È
-infatti normale che più processi o programmi possano accedere
-contemporaneamente allo stesso file e devono poter eseguire le loro operazioni
-indipendentemente da quello che fanno gli altri processi.
-
-Per questo motivo le strutture usate per all'accesso ai file sono relative al
-processo che effettua l'accesso.  All'apertura di ogni file infatti viene
-creata all'interno del processo una apposita struttura in cui sono memorizzati
-tutti gli attributi del medesimo, che viene utilizzata per tutte le
-operazioni. Questa è una struttura che resta locale al processo stesso; in
-questo modo processi diversi possono usare le proprie strutture locali per
-accedere ai file (che può essere sempre lo stesso) in maniera assolutamente
-indipendente.
-
-Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i
-sistemi POSIX uno degli attributi di un file aperto è la posizione corrente nel
-file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione
-successiva. Essa è rappresentata da un numero intero che indica il numero di
-bytes dall'inizio del file, che viene (a meno che non si apra il file in
-append) inizializzato a zero all'apertura del medesimo.
-
-Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui
-ogni processo avrà la sua posizione corrente nel file, che non sarà
-influenzata da quello che altri processi possono fare. Anzi, aprire un file
-significa appunto creare ed inizializzare una tale struttura, per cui se si
-apre due volte lo stesso file all'interno dello stesso processo, si otterrano
-due file descriptor o due stream che avranno ancora una posizione corrente nel
-file assolutamente indipendente.
-
-Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di
-accesso è un riferimento all'inode del file, pertanto anche se il file viene
-cancellato da un altro processo, sarà sempre possibile mantenere l'accesso ai
-dati, e lo spazio su disco non verrà rilasciato fintanto che il file non sarà
-chiuso e l'ultimo riferimento cancellato. È pertanto possibile (e pratica
-comune) aprire un file provvisorio per 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.
-
+%% fileintro.tex
+%%
+%% Copyright (C) 2000-2011 Simone Piccardi.  Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
+
+%\chapter{L'architettura dei file}
+%\label{cha:file_intro}
+
+% capitolo eliminato, inglobando altrove
+
+% 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 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 third MacOS
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: