Esamineremo in questo capitolo la prima delle due interfacce di programmazione
-per i file, quella dei \textit{file descriptor}, nativa di Unix. Questa è
-l'interfaccia di basso livello provvista direttamente dalle system call, che
-non prevede funzionalità evolute come la bufferizzazione o funzioni di lettura
-o scrittura formattata, e sulla quale è costruita anche l'interfaccia definita
-dallo standard ANSI C che affronteremo al \capref{cha:files_std_interface}.
+per i file, quella dei \textit{file descriptor}\index{file descriptor},
+nativa di Unix. Questa è l'interfaccia di basso livello provvista direttamente
+dalle system call, che non prevede funzionalità evolute come la
+bufferizzazione o funzioni di lettura o scrittura formattata, e sulla quale è
+costruita anche l'interfaccia definita dallo standard ANSI C che affronteremo
+al \capref{cha:files_std_interface}.
canale di comunicazione impedendo ogni ulteriore operazione.
All'interno di ogni processo i file aperti sono identificati da un intero non
-negativo, chiamato appunto \textit{file descriptor}. Quando un file viene
-aperto la funzione \func{open} restituisce questo numero, tutte le ulteriori
-operazioni saranno compiute specificando questo stesso valore come argomento
-alle varie funzioni dell'interfaccia.
+negativo, chiamato appunto \textit{file descriptor}\index{file descriptor}.
+Quando un file viene aperto la funzione \func{open} restituisce questo numero,
+tutte le ulteriori operazioni saranno compiute specificando questo stesso
+valore come argomento alle varie funzioni dell'interfaccia.
Per capire come funziona il meccanismo occorre spiegare a grandi linee come è
che il kernel gestisce l'interazione fra processi e file. Il kernel mantiene
\item una tabella che contiene un puntatore alla relativa voce nella
\textit{file table} per ogni file aperto.
\end{itemize*}
-il \textit{file descriptor} in sostanza è l'intero positivo che indicizza
-quest'ultima tabella.
+il \textit{file descriptor}\index{file descriptor} in sostanza è l'intero
+positivo che indicizza quest'ultima tabella.
La \textit{file table} è una tabella che contiene una voce per ciascun file
che è stato aperto nel sistema. In Linux è costituita da strutture di tipo
\end{figure}
Ritorneremo su questo schema più volte, dato che esso è fondamentale per
capire i dettagli del funzionamento dell'interfaccia dei \textit{file
- descriptor}.
+ descriptor}\index{file descriptor}.
\subsection{I file standard}
\label{sec:file_std_descr}
-Come accennato i \textit{file descriptor} non sono altro che un indice nella
-tabella dei file aperti di ciascun processo; per questo motivo essi vengono
-assegnati in successione tutte le volte che si apre un nuovo file (se non ne è
-stato chiuso nessuno in precedenza).
+Come accennato i \textit{file descriptor}\index{file descriptor} non sono
+altro che un indice nella tabella dei file aperti di ciascun processo; per
+questo motivo essi vengono assegnati in successione tutte le volte che si apre
+un nuovo file (se non ne è stato chiuso nessuno in precedenza).
In tutti i sistemi unix-like esiste una convenzione generale per cui ogni
processo viene lanciato con almeno tre file aperti. Questi, per quanto appena
-detto, avranno come \textit{file descriptor} i valori 0, 1 e 2. Benché questa
-sia soltanto una convenzione, essa è seguita dalla gran parte delle
-applicazioni, e non aderirvi potrebbe portare a gravi problemi di
-interoperabilità.
+detto, avranno come \textit{file descriptor}\index{file descriptor} i valori
+0, 1 e 2. Benché questa sia soltanto una convenzione, essa è seguita dalla
+gran parte delle applicazioni, e non aderirvi potrebbe portare a gravi
+problemi di interoperabilità.
Il primo file è sempre associato a quello che viene chiamato \textit{standard
input}. È cioè il file da cui il processo si aspetta di ricevere i dati in
\hline % modalità di accesso al file
\macro{O\_RDONLY} & apre il file in sola lettura. \\
\macro{O\_WRONLY} & apre il file in sola scrittura. \\
- \macro{O\_RDWR} & apre il file lettura/scrittura. \\
+ \macro{O\_RDWR} & apre il file in lettura/scrittura. \\
\hline % modalità di apertura del file
\hline
\macro{O\_CREAT} & se il file non esiste verrà creato, con le regole di
\func{open} con \macro{EEXIST}. \\
\macro{O\_NONBLOCK} & apre il file in modalità non bloccante. Questo
valore specifica anche una modalità di operazione (vedi sotto), e
- comporta che \func{open} ritorni immediatamente (torneremo su
- questo in \secref{sec:file_noblocking}). \\
+ comporta che \func{open} ritorni immediatamente (l'opzione ha senso
+ solo per le fifo, torneremo questo in \secref{sec:ipc_named_pipe}). \\
\macro{O\_NOCTTY} & se \var{pathname} si riferisce ad un device di
terminale, questo non diventerà il terminale di controllo, anche se il
processo non ne ha ancora uno (si veda \secref{sec:sess_xxx}). \\
file. Può causare corruzione del file con NFS se più di un processo scrive
allo stesso tempo.\footnotemark\\
\macro{O\_NONBLOCK} & il file viene aperto in modalità non bloccante per
- le operazioni di I/O: questo significa il fallimento di \func{read} in
- assenza di dati da leggere e quello di \func{write} in caso di
- impossibilità di scrivere immediatamente. L'opzione è effettiva solo per
- le fifo e per alcuni file di dispositivo. \\
+ le operazioni di I/O (che tratteremo in \secref{sec:file_noblocking}):
+ questo significa il fallimento di \func{read} in assenza di dati da
+ leggere e quello di \func{write} in caso di impossibilità di scrivere
+ immediatamente. Questa modalità ha senso solo per le fifo e per alcuni
+ file di dispositivo. \\
\macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di
\macro{O\_NONBLOCK}.\\
\macro{O\_ASYNC} & apre il file per l'I/O in modalità
\footnotetext[2]{la man page di \func{open} segnala che questa opzione è
difettosa su NFS, e che i programmi che la usano per stabilire un file di
- lock possono incorrere in una race condition. Si consiglia come alternativa
- di usare un file con un nome univoco e la funzione \func{link} per
- verificarne l'esistenza.}
+ lock possono incorrere in una race condition\index{race condition}. Si
+ consiglia come alternativa di usare un file con un nome univoco e la
+ funzione \func{link} per verificarne l'esistenza.}
-\footnotetext[3]{Denial of Service, si chiamano così attacchi miranti ad
- impedire un servizio causando una qualche forma di carico eccessivo per il
- sistema, che resta bloccato nelle risposte all'attacco.}
+\footnotetext[3]{\textit{Denial of Service}, si chiamano così attacchi miranti
+ ad impedire un servizio causando una qualche forma di carico eccessivo per
+ il sistema, che resta bloccato nelle risposte all'attacco.}
\footnotetext[4]{il problema è che NFS non supporta la scrittura in append, ed
il kernel deve simularla, ma questo comporta la possibilità di una race
successiva scrittura avvenga alla fine del file, infatti se questo è stato
aperto anche da un altro processo che vi ha scritto, la fine del file può
essersi spostata, ma noi scriveremo alla posizione settata in precedenza.
-(questa è una potenziale sorgente di \textit{race condition}, vedi
-\secref{sec:file_atomic}).
+(questa è una potenziale sorgente di
+\textit{race condition}\index{race condition}, vedi \secref{sec:file_atomic}).
Non tutti i file supportano la capacità di eseguire una \func{lseek}, in
questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per
Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui
vari processi devono scrivere alla fine di un file (ad esempio un file di
log). Come accennato in \secref{sec:file_lseek} settare la posizione alla fine
-del file e poi scrivere può condurre ad una \textit{race condition}: infatti
-può succedere che un secondo processo scriva alla fine del file fra la
-\func{lseek} e la \func{write}; in questo caso, come abbiamo appena visto, il
-file sarà esteso, ma il nostro primo processo avrà ancora la posizione
-corrente settata con la \func{lseek} che non corrisponde più alla fine del
-file, e la successiva \func{write} sovrascriverà i dati del secondo processo.
+del file e poi scrivere può condurre ad una
+\textit{race condition}\index{race condition}:
+infatti può succedere che un secondo processo scriva alla fine
+del file fra la \func{lseek} e la \func{write}; in questo caso, come abbiamo
+appena visto, il file sarà esteso, ma il nostro primo processo avrà ancora la
+posizione corrente settata con la \func{lseek} che non corrisponde più alla
+fine del file, e la successiva \func{write} sovrascriverà i dati del secondo
+processo.
Il problema è che usare due system call in successione non è un'operazione
atomica; il problema è stato risolto introducendo la modalità
creare un file di lock, bloccandosi se il file esiste. In questo caso la
sequenza logica porterebbe a verificare prima l'esistenza del file con una
\func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la
-possibilità di una race condition da parte di un altro processo che crea lo
-stesso file fra il controllo e la creazione.
+possibilità di una race condition\index{race condition} da parte di un altro
+processo che crea lo stesso file fra il controllo e la creazione.
Per questo motivo sono stati introdotti pe \func{open} i due flag
\macro{O\_CREAT} e \macro{O\_EXCL}. In questo modo l'operazione di controllo