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
specificati da \var{mode}.
\bodydesc{La funzione ritorna il file descriptor in caso di successo e -1 in
- caso di errore. In questo caso la variabile \var{errno} viene settata ad
- uno dei valori:
+ caso di errore. In questo caso la variabile \var{errno} assumerà uno dei
+ valori:
\begin{errlist}
\item[\macro{EEXIST}] \var{pathname} esiste e si è specificato
\macro{O\_CREAT} e \macro{O\_EXCL}.
l'accesso in scrittura.
\item[\macro{ENOTDIR}] si è specificato \macro{O\_DIRECTORY} e \var{pathname}
non è una directory.
- \item[\macro{ENXIO}] si sono settati \macro{O\_NOBLOCK} o \macro{O\_WRONLY}
+ \item[\macro{ENXIO}] si sono impostati \macro{O\_NOBLOCK} o \macro{O\_WRONLY}
ed il file è una fifo che non viene letta da nessun processo o
\var{pathname} è un file di dispositivo ma il dispositivo è assente.
\item[\macro{ENODEV}] \var{pathname} si riferisce a un file di dispositivo
\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}). \\
+ processo non ne ha ancora uno (si veda \secref{sec:sess_ctrl_term}). \\
\macro{O\_SHLOCK} & opzione di BSD, acquisisce uno shared lock (vedi
\secref{sec:file_locking}) sul file. Non è disponibile in Linux. \\
\macro{O\_EXLOCK} & opzione di BSD, acquisisce uno lock esclusivo (vedi
opzione è ignorata. \\
\macro{O\_DIRECTORY} & se \var{pathname} non è una directory la chiamata
fallisce. Questo flag è specifico di Linux ed è stato introdotto con il
- kernel 2.1.126 per evitare dei DoS\protect\footnotemark\ quando
+ kernel 2.1.126 per evitare dei
+ \textit{DoS}\index{DoS}\protect\footnotemark\ quando
\func{opendir} viene chiamata su una
fifo o su un device di unità a nastri, non deve essere utilizzato al di
fuori dell'implementazione di \func{opendir}. \\
\hline
\hline % modalità di operazione col file
\macro{O\_APPEND} & il file viene aperto in append mode. Prima di ciascuna
- scrittura la posizione corrente viene sempre settata alla fine del
+ scrittura la posizione corrente viene sempre impostata alla fine del
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à
- asincrona (vedi \secref{sec:file_asyncronous_io}). Quando è settato viene
+ asincrona (vedi \secref{sec:file_asyncronous_io}). Quando è impostato viene
generato il segnale \macro{SIGIO} tutte le volte che sono disponibili
dati in input sul file. \\
\macro{O\_SYNC} & apre il file per l'input/output sincrono, ogni
\label{tab:file_open_flags}
\end{table}
-\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.}
+\footnotetext[2]{la pagina di manuale 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\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
Il nuovo file descriptor non è condiviso con nessun altro processo, (torneremo
sulla condivisione dei file, in genere accessibile dopo una \func{fork}, in
-\secref{sec:file_sharing}). Il nuovo file descriptor è settato di default per
-restare aperto attraverso una \func{exec} (come accennato in
-\secref{sec:proc_exec}) e l'offset è settato all'inizio del file.
+\secref{sec:file_sharing}). Il nuovo file descriptor è impostato per restare
+aperto attraverso una \func{exec} (come accennato in \secref{sec:proc_exec}) e
+l'offset è impostato all'inizio del file.
L'argomento \param{mode} specifica i permessi con cui il file viene
eventualmente creato; i valori possibili sono gli stessi già visti in
\item \textsl{i bit delle modalità di accesso}: specificano con quale modalità
si accederà al file: i valori possibili sono lettura, scrittura o
lettura/scrittura. Uno di questi bit deve essere sempre specificato quando
- si apre un file. Vengono settati alla chiamata da \func{open}, e possono
+ si apre un file. Vengono impostati alla chiamata da \func{open}, e possono
essere riletti con una \func{fcntl} (fanno parte del \textit{file status
flag}), ma non possono essere modificati.
\item \textsl{i bit delle modalità di apertura}: permettono di specificare
\item \textsl{i bit delle modalità di operazione}: permettono di specificare
alcune caratteristiche del comportamento delle future operazioni sul file
(come la \func{read} o la \func{write}). Anch'essi fanno parte del
- \textit{file status flag}. Il loro valore è settato alla chiamata di
+ \textit{file status flag}. Il loro valore è impostato alla chiamata di
\func{open}, ma possono essere riletti e modificati (insieme alle
caratteristiche operative che controllano) con una \func{fcntl}.
\end{itemize}
Chiude il descrittore \var{fd}.
\bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
- ed in questo caso \var{errno} è settata ai valori:
+ ed in questo caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EBADF}] \var{fd} non è un descrittore valido.
\item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
automaticamente spostata in avanti del numero di byte letti o scritti.
In genere (a meno di non avere richiesto la modalità \macro{O\_APPEND}) questa
-posizione viene settata a zero all'apertura del file. È possibile settarla ad
+posizione viene impostata a zero all'apertura del file. È possibile impostarla ad
un valore qualsiasi con la funzione \func{lseek}, il cui prototipo è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{unistd.h}
\funcdecl{off\_t lseek(int fd, off\_t offset, int whence)}
- Setta la posizione attuale nel file.
+ Imposta la posizione attuale nel file.
\bodydesc{La funzione ritorna valore della posizione corrente in caso di
- successo e -1 in caso di errore nel qual caso \var{errno} viene settata ad
- uno dei valori:
+ successo e -1 in caso di errore nel qual caso \var{errno} assumerà uno dei
+ valori:
\begin{errlist}
\item[\macro{ESPIPE}] \param{fd} è una pipe, un socket o una fifo.
\item[\macro{EINVAL}] \param{whence} non è un valore valido.
ed inoltre \macro{EBADF}.}
\end{functions}
-La nuova posizione è settata usando il valore specificato da \param{offset},
+La nuova posizione è impostata usando il valore specificato da \param{offset},
sommato al riferimento dato da \param{whence}; quest'ultimo può assumere i
seguenti valori\footnote{per compatibilità con alcune vecchie notazioni
questi valori possono essere rimpiazzati rispettivamente con 0, 1 e 2 o con
\end{basedescript}
Come accennato in \secref{sec:file_file_size} con \func{lseek} è possibile
-settare la posizione corrente anche al di la della fine del file, e alla
+impostare la posizione corrente anche al di la della fine del file, e alla
successiva scrittura il file sarà esteso. La chiamata non causa nessuna
attività di input/output, si limita a modificare la posizione corrente nel
kernel (cioè \var{f\_pos} in \var{file}, vedi \figref{fig:file_proc_file}).
Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che
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}).
+essersi spostata, ma noi scriveremo alla posizione impostata in precedenza.
+(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
Cerca di leggere \var{count} byte dal file \var{fd} al buffer \var{buf}.
\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e
- -1 in caso di errore, nel qual caso \var{errno} viene settata ad uno dei
- valori:
+ -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EINTR}] la funzione è stata interrotta da un segnale prima di
aver potuto leggere qualsiasi dato.
Con i \textsl{file regolari} questa è l'unica situazione in cui si può avere
un numero di byte letti inferiore a quello richiesto, ma questo non è vero
quando si legge da un terminale, da una fifo o da una pipe. In tal caso
-infatti, se non ci sono dati in ingresso, la \func{read} si blocca e ritorna
-solo quando ne arrivano; se il numero di byte richiesti eccede quelli
-disponibili la funzione ritorna comunque, ma con un numero di byte inferiore a
-quelli richiesti.
+infatti, se non ci sono dati in ingresso, la \func{read} si blocca (a meno di
+non aver selezionato la modalità non bloccante, vedi
+\secref{sec:file_noblocking}) e ritorna solo quando ne arrivano; se il numero
+di byte richiesti eccede quelli disponibili la funzione ritorna comunque, ma
+con un numero di byte inferiore a quelli richiesti.
Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
-come vedremo in \secref{sec:sock_io_behav}), o per certi dispositivi, come le
-unità a nastro, che restituiscono un singolo blocco di dati alla volta.
+come vedremo in \secref{sec:sock_io_behav}), o per la lettura da certi file di
+dispositivo, come le unità a nastro, che restituiscono sempre i dati ad un
+singolo blocco alla volta.
In realtà anche le due condizioni segnalate dagli errori \macro{EINTR} e
\macro{EAGAIN} non sono errori. La prima si verifica quando la \func{read} è
bloccata in attesa di dati in ingresso e viene interrotta da un segnale; in
-tal caso l'azione da prendere è quella di rieseguire la funzione. Torneremo
-sull'argomento in \secref{sec:sig_gen_beha}.
-
-La seconda si verifica quando il file è in modalità non bloccante e non ci
-sono dati in ingresso: la funzione allora ritorna immediatamente con un errore
-\macro{EAGAIN}\footnote{sotto BSD questo per questo errore viene usata la
- costante \macro{EWOULDBLOCK}, in GNU/Linux questa è sinonima di
- \macro{EAGAIN}.} che nel caso indica soltanto che occorrerà provare a
-ripetere la lettura.
-
-
-Nella seconda versione delle \textit{Single Unix
+tal caso l'azione da prendere è quella di rieseguire la funzione. Torneremo in
+dettaglio sull'argomento in \secref{sec:sig_gen_beha}.
+
+La seconda si verifica quando il file è in modalità non bloccante (vedi
+\secref{sec:file_noblocking}) e non ci sono dati in ingresso: la funzione
+allora ritorna immediatamente con un errore \macro{EAGAIN}\footnote{sotto BSD
+ questo per questo errore viene usata la costante \macro{EWOULDBLOCK}, in
+ Linux, con le glibc, questa è sinonima di \macro{EAGAIN}.} che nel caso
+indica soltanto che occorrerà provare a ripetere la lettura.
+
+La funzione \func{read} è una delle system call fondamentali, esistenti fin
+dagli albori di Unix, ma nella seconda versione delle \textit{Single Unix
Specification}\footnote{questa funzione, e l'analoga \func{pwrite} sono
state aggiunte nel kernel 2.1.60, il supporto nelle \acr{glibc}, compresa
l'emulazione per i vecchi kernel che non hanno la system call, è stato
- aggiunto con la versione 2.1.} (quello che viene chiamato normalmente Unix98,
-vedi \secref{sec:intro_opengroup}) è stata introdotta la definizione di
-un'altra funzione di lettura, \func{pread}, che diventa accessibile con la
-definizione:
-\begin{verbatim}
- #define _XOPEN_SOURCE 500
-\end{verbatim}
-il prototipo di questa funzione è:
+ aggiunto con la versione 2.1, in versioni precedenti sia del kernel che
+ delle librerie la funzione non è disponibile.} (quello che viene chiamato
+normalmente Unix98, vedi \secref{sec:intro_opengroup}) è stata introdotta la
+definizione di un'altra funzione di lettura, \func{pread}, il cui prototipo è:
\begin{prototype}{unistd.h}
{ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
-
+
Cerca di leggere \var{count} byte dal file \var{fd}, a partire dalla posizione
\var{offset}, nel buffer \var{buf}.
\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e -1
- in caso di errore, nel qual caso \var{errno} viene settata secondo i valori
- già visti per \func{read} e \func{lseek}.}
+ in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per
+ \func{read} e \func{lseek}.}
\end{prototype}
+\noindent che però diventa accessibile solo con la definizione della macro:
+\begin{verbatim}
+ #define _XOPEN_SOURCE 500
+\end{verbatim}
Questa funzione serve quando si vogliono leggere dati dal file senza
modificarne la posizione corrente. È equivalente alla esecuzione di una
-\func{read} e una \func{lseek}, ma permette di eseguire l'operazione
+\func{read} seguita da una \func{lseek} che riporti al valore precedente la
+posizione corrente sul file, ma permette di eseguire l'operazione
atomicamente. Questo può essere importante quando la posizione sul file viene
condivisa da processi diversi (vedi \secref{sec:file_sharing}). Il valore di
\var{offset} fa sempre riferimento all'inizio del file.
Scrive \var{count} byte dal buffer \var{buf} sul file \var{fd}.
\bodydesc{La funzione ritorna il numero di byte scritti in caso di successo
- e -1 in caso di errore, nel qual caso \var{errno} viene settata ad uno dei
- valori:
+ e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EINVAL}] \var{fd} è connesso ad un oggetto che non consente la
scrittura.
\var{count} byte dal buffer \var{buf}.
\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e -1
- in caso di errore, nel qual caso \var{errno} viene settata secondo i valori
- già visti per \func{write} e \func{lseek}.}
+ in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per
+ \func{write} e \func{lseek}.}
\end{prototype}
\noindent e per essa valgono le stesse considerazioni fatte per \func{pread}.
scrittura eccede la dimensione corrente del file questo verrà esteso
automaticamente con l'aggiornamento del campo \var{i\_size} nell'inode.
\item se un file è in modalità \macro{O\_APPEND} tutte le volte che viene
- effettuata una scrittura la posizione corrente viene prima settata alla
+ effettuata una scrittura la posizione corrente viene prima impostata alla
dimensione corrente del file letta dall'inode. Dopo la scrittura il file
viene automaticamente esteso.
\item l'effetto di \func{lseek} è solo quello di cambiare il campo \var{f\_pos}
nella struttura \var{file} della \textit{file table}, non c'è nessuna
operazione sul file su disco. Quando la si usa per porsi alla fine del file
- la posizione viene settata leggendo la dimensione corrente dall'inode.
+ la posizione viene impostata leggendo la dimensione corrente dall'inode.
\end{itemize}
\begin{figure}[htb]
corrente nel file varierà per entrambi i processi (in quanto verrà modificato
\var{f\_pos} che è la stesso per entrambi).
-Si noti inoltre che anche i flag di stato del file (quelli settati
+Si noti inoltre che anche i flag di stato del file (quelli impostati
dall'argomento \param{flag} di \func{open}) essendo tenuti nella voce della
\textit{file table}\footnote{per la precisione nel campo \var{f\_flags} di
\var{file}.}, vengono in questo caso condivisi. Ai file però sono associati
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.
+log). Come accennato in \secref{sec:file_lseek} impostare la posizione alla fine
+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 impostata 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
Crea una copia del file descriptor \param{oldfd}.
\bodydesc{La funzione ritorna il nuovo file descriptor in caso di successo e
- -1 in caso di errore, nel qual caso \var{errno} viene settata ad uno dei
+ -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei
valori:
\begin{errlist}
\item[\macro{EBADF}] \param{oldfd} non è un file aperto.
può fare riferimento a \figref{fig:file_dup}: l'effetto della funzione è
semplicemente quello di copiare il valore nella struttura \var{file\_struct},
cosicché anche il nuovo file descriptor fa riferimento alla stessa voce
-nella \textit{file table}.
+nella \textit{file table}; per questo si dice che il nuovo file descriptor è
+\textsl{duplicato}, da cui il nome della funzione.
\begin{figure}[htb]
\centering \includegraphics[width=13cm]{img/filedup}
\label{fig:file_dup}
\end{figure}
-In questo modo entrambi i file condivideranno eventuali lock, \textit{file
- status flag}, e posizione corrente: se ad esempio \func{lseek} modifica la
-posizione su uno dei due file descriptor essa sarà modificata anche sull'altro
-(al solito viene modificato lo stesso campo nella voce della \textit{file
- table} a cui entrambi fanno riferimento).
-
-L'unica differenza fra i due file descriptor è che ciascuno avrà il suo
-\textit{file descriptor flag}: nel caso di \func{dup} il flag di \textit{close
- on exec} viene sempre cancellato nella copia.
-
-Una diversa versione della funzione, \func{dup2} viene utilizzata per
-specificare esplicitamente il nuovo file descriptor; il suo prototipo è:
+Si noti che per quanto illustrato in\figref{fig:file_dup} i file descriptor
+duplicati condivideranno eventuali lock, \textit{file status flag}, e
+posizione corrente. Se ad esempio si esegue una \func{lseek} per modificare la
+posizione su uno dei due file descriptor, essa risulterà modificata anche
+sull'altro (dato che quello che viene modificato è lo stesso campo nella voce
+della \textit{file table} a cui entrambi fanno riferimento). L'unica
+differenza fra due file descriptor duplicati è che ciascuno avrà il suo
+\textit{file descriptor flag}; a questo proposito va specificato che nel caso
+di \func{dup} il flag di \textit{close on exec} viene sempre cancellato nella
+copia.
+
+L'uso principale di questa funzione è per la redirezione dell'input e
+dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec};
+diventa così possibile associare un file (o una pipe) allo standard input o
+allo standard output (torneremo sull'argomento in \secref{sec:ipc_pipe_use},
+quando tratteremo le pipe). Per fare questo in genere occorre prima chiudere
+il file che si vuole sostituire, cossicché il suo file descriptor possa esser
+restituito alla chiamata di \func{dup}, come primo file descriptor
+disponibile.
+
+Dato che questa è l'operazione più comune, è prevista una diversa versione
+della funzione, \func{dup2}, che permette di specificare esplicitamente qual'è
+il valore di file descriptor che si vuole avere come duplicato; il suo
+prototipo è:
\begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)}
Rende \param{newfd} una copia del file descriptor \param{oldfd}.
\bodydesc{La funzione ritorna il nuovo file descriptor in caso di successo e
- -1 in caso di errore, nel qual caso \var{errno} viene settata ad uno dei
- valori:
+ -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\macro{EBADF}] \param{oldfd} non è un file aperto o \param{newfd} ha un
valore fuori dall'intervallo consentito per i file descriptor.
descriptor aperti.
\end{errlist}}
\end{prototype}
-\noindent la funzione chiude il file descriptor \param{newfd} se è aperto.
+\noindent e qualora il file descriptor \param{newfd} sia già aperto (come
+avviene ad esempio nel caso della duplicazione di uno dei file standard) esso
+sarà prima chiuso e poi duplicato.
La duplicazione dei file descriptor può essere effettuata anche usando la
funzione di controllo dei file \func{fnctl} (che esamineremo in
-\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}.
+\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}.
L'operazione ha la sintassi \code{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
superiore, per cui per poterla usare come \func{dup2} occorrerebbe prima
effettuare una \func{close}, perdendo l'atomicità dell'operazione.
-L'uso principale di queste funzioni è per la redirezione dell'input e
-dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec};
-diventa così possibile associare un file (o una pipe) allo standard input o
-allo standard output, torneremo su questo uso in \secref{sec:ipc_pipe_use}
-quando tratteremo le pipe.
-
\subsection{La funzione \func{fcntl}}
\label{sec:file_fcntl}
sul file \param{fd}.
\bodydesc{La funzione ha valori di ritorno diversi a seconda
- dell'operazione. In caso di errore il valore di ritorno è -1 e la
- variabile \var{errno} viene settata ad un opportuno codice, quelli validi
- in generale sono:
+ dell'operazione. In caso di errore il valore di ritorno è sempre -1 ed il
+ codice dell'errore è restituito nella variabile \var{errno}; i codici
+ possibili dipendono dal tipo di operazione, l'unico valido in generale è:
\begin{errlist}
- \item[\macro{EBADF}] \param{oldfd} non è un file aperto.
+ \item[\macro{EBADF}] \param{fd} non è un file aperto.
\end{errlist}}
\end{functions}
\macro{EINVAL} se \param{arg} è negativo o maggiore del massimo consentito o
\macro{EMFILE} se il processo ha già raggiunto il massimo numero di
descrittori consentito.
-\item[\macro{F\_SETFD}] setta il valore del \textit{file descriptor flag}
+\item[\macro{F\_SETFD}] imposta il valore del \textit{file descriptor flag}
al valore specificato con \param{arg}. Al momento l'unico bit usato è
quello di \textit{close on exec}, identificato dalla costante
\macro{FD\_CLOEXEC}.
\item[\macro{F\_GETFD}] ritorna il valore del \textit{file descriptor flag} di
- \var{fd}, se \macro{FD\_CLOEXEC} è settato i file descriptor aperti vengono
- chiusi attraverso una \func{exec} altrimenti (il default) restano aperti.
+ \var{fd}, se \macro{FD\_CLOEXEC} è impostato i file descriptor aperti
+ vengono chiusi attraverso una \func{exec} altrimenti (il comportamento
+ predefinito) restano aperti.
\item[\macro{F\_GETFL}] ritorna il valore del \textit{file status flag},
- permette cioè di rileggere quei bit settati da \func{open} all'apertura del
+ permette cioè di rileggere quei bit impostati da \func{open} all'apertura del
file che vengono memorizzati (quelli riportati nella prima e terza sezione
di \tabref{tab:file_open_flags}).
-\item[\macro{F\_SETFL}] setta il \textit{file status flag} al valore
- specificato da \param{arg}, possono essere settati solo i bit riportati
- nella terza sezione di \tabref{tab:file_open_flags}.\footnote{NdA da
- verificare.}
+\item[\macro{F\_SETFL}] imposta il \textit{file status flag} al valore
+ specificato da \param{arg}, possono essere impostati solo i bit riportati
+ nella terza sezione di \tabref{tab:file_open_flags}.\footnote{la pagina di
+ manuale riporta come impostabili solo \macro{O\_APPEND},
+ \macro{O\_NONBLOCK} e \macro{O\_ASYNC}.}
\item[\macro{F\_GETLK}] se un file lock è attivo restituisce nella struttura
\param{lock} la struttura \type{flock} che impedisce l'acquisizione del
- blocco, altrimenti setta il campo \var{l\_type} a \macro{F\_UNLCK} (per i
+ blocco, altrimenti imposta il campo \var{l\_type} a \macro{F\_UNLCK} (per i
dettagli sul \textit{file locking} vedi \secref{sec:file_locking}).
\item[\macro{F\_SETLK}] richiede il file lock specificato da \param{lock} se
\var{l\_type} è \macro{F\_RDLCK} o \macro{F\_WRLLCK} o lo rilascia se
\var{l\_type} è \macro{F\_UNLCK}. Se il lock è tenuto da qualcun'altro
- ritorna immediatamente restituendo -1 e setta \var{errno} a \macro{EACCES} o
- \macro{EAGAIN} (per i dettagli sul \textit{file locking} vedi
+ ritorna immediatamente restituendo -1 e imposta \var{errno} a \macro{EACCES}
+ o \macro{EAGAIN} (per i dettagli sul \textit{file locking} vedi
\secref{sec:file_locking}).
\item[\macro{F\_SETLKW}] identica a \macro{F\_SETLK} eccetto per il fatto che
la funzione non ritorna subito ma attende che il blocco sia rilasciato. Se
- l'attesa viene interrotta da un segnale la funzione restituisce -1 e setta
+ l'attesa viene interrotta da un segnale la funzione restituisce -1 e imposta
\var{errno} a \macro{EINTR} (per i dettagli sul \textit{file locking} vedi
\secref{sec:file_locking}).
\item[\macro{F\_GETOWN}] restituisce il \acr{pid} del processo o il process
group che è preposto alla ricezione dei segnali \macro{SIGIO} e
\macro{SIGURG} per gli eventi associati al file descriptor \var{fd}. Il
process group è restituito come valore negativo.
-\item[\macro{F\_SETOWN}] setta il processo o process group che riceverà i
+\item[\macro{F\_SETOWN}] imposta il processo o process group che riceverà i
segnali \macro{SIGIO} e \macro{SIGURG} per gli eventi associati al file
- descriptor \var{fd}. I process group sono settati usando valori negativi.
+ descriptor \var{fd}. I process group sono impostati usando valori negativi.
\item[\macro{F\_GETSIG}] restituisce il valore del segnale mandato quando ci
- sono dati disponibili in input su un file descriptor aperto o settato in I/O
- asincrono. Il valore 0 indica il valore default (che è \macro{SIGIO}), un
- valore diverso da zero indica il segnale richiesto, (che può essere lo
- stesso \macro{SIGIO}).
-\item[\macro{F\_SETSIG}] setta il segnale da inviare quando diventa possibile
- effettuare I/O sul file descriptor in caso di I/O asincrono. Il valore zero
- indica di usare il segnale di default, \macro{SIGIO}. Un altro valore
- (compreso lo stesso \macro{SIGIO}) specifica il segnale voluto; l'uso di un
- valore diverso da zero permette inoltre, se si è installato il manipolatore
- del segnale come \var{sa\_sigaction} usando \macro{SA\_SIGINFO}, (vedi
- \secref{sec:sig_sigaction}), di rendere disponibili al manipolatore
- informazioni ulteriori informazioni riguardo il file che ha generato il
- segnale attraverso i valori restituiti in \var{siginfo\_t} (come vedremo in
- \secref{sec:file_asyncronous_io}).
+ sono dati disponibili in input su un file descriptor aperto o impostato in
+ I/O asincrono. Il valore 0 indica il valore predefinito (che è
+ \macro{SIGIO}), un valore diverso da zero indica il segnale richiesto, (che
+ può essere lo stesso \macro{SIGIO}).
+\item[\macro{F\_SETSIG}] imposta il segnale da inviare quando diventa
+ possibile effettuare I/O sul file descriptor in caso di I/O asincrono. Il
+ valore zero indica di usare il segnale predefinito, \macro{SIGIO}. Un altro
+ valore (compreso lo stesso \macro{SIGIO}) specifica il segnale voluto; l'uso
+ di un valore diverso da zero permette inoltre, se si è installato il
+ manipolatore del segnale come \var{sa\_sigaction} usando
+ \macro{SA\_SIGINFO}, (vedi \secref{sec:sig_sigaction}), di rendere
+ disponibili al manipolatore informazioni ulteriori informazioni riguardo il
+ file che ha generato il segnale attraverso i valori restituiti in
+ \type{siginfo\_t} (come vedremo in
+ \secref{sec:file_asyncronous_io}).\footnote{i due comandi \macro{F\_SETSIG}
+ e \macro{F\_GETSIG} sono una estensione specifica di Linux.}
\end{basedescript}
La maggior parte delle funzionalità di \func{fcntl} sono troppo avanzate per
poter essere affrontate in dettaglio a questo punto; saranno riprese più
-avanti quando affronteremo le problematiche ad esse relative.
+avanti quando affronteremo le problematiche ad esse relative (in particolare
+riprenderemo le tematiche relative all'I/O asincrono in
+\secref{sec:file_asyncronous_io} e quelle relative al \textit{file locking} in
+\secref{sec:file_locking}).
Per determinare le modalità di accesso inoltre è necessario estrarre i bit di
accesso (ottenuti con il comando \macro{F\_GETFL}); infatti la definizione
interagire con le stesse funzioni usate per i normali file di dati,
esisteranno sempre caratteristiche peculiari, specifiche dell'hardware e della
funzionalità che ciascuno di essi provvede, che non possono venire comprese in
-questa interfaccia astratta (un caso tipico è il settaggio della velocità di
+questa interfaccia astratta (un caso tipico è l'impostazione della velocità di
una porta seriale, o le dimensioni di un framebuffer).
Per questo motivo l'architettura del sistema ha previsto l'esistenza di una
\bodydesc{La funzione nella maggior parte dei casi ritorna 0, alcune
operazioni usano però il valore di ritorno per restituire informazioni. In
- caso di errore viene sempre restituito -1 e \var{errno} viene settata ad
- uno dei valori seguenti:
+ caso di errore viene sempre restituito -1 ed \var{errno} assumerà uno dei
+ valori:
\begin{errlist}
\item[\macro{ENOTTY}] il file \param{fd} non è associato con un device, o la
richiesta non è applicabile all'oggetto a cui fa riferimento \param{fd}.
\item l'esecuzione di una traccia audio di un CDROM.
\item i comandi di avanti veloce e riavvolgimento di un nastro.
\item il comando di espulsione di un dispositivo rimovibile.
-\item il settaggio della velocità trasmissione di una linea seriale.
-\item il settaggio della frequenza e della durata dei suoni emessi dallo
+\item l'impostazione della velocità trasmissione di una linea seriale.
+\item l'impostazione della frequenza e della durata dei suoni emessi dallo
speaker.
\end{itemize*}
\func{ioctl} in quasi tutte le implementazioni di Unix), qui riportiamo solo i
valori che sono definiti per ogni file:
\begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\macro{FIOCLEX}] Setta il bit di \textit{close on exec}.
+\item[\macro{FIOCLEX}] Imposta il bit di \textit{close on exec}.
\item[\macro{FIONCLEX}] Cancella il bit di \textit{close on exec}.
\item[\macro{FIOASYNC}] Abilita l'I/O asincrono.
-\item[\macro{FIONBIO}] Abilità l'I/O in modalità non bloccante.
+\item[\macro{FIONBIO}] Abilita l'I/O in modalità non bloccante.
\end{basedescript}
relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}.