\chapter{La gestione dell'I/O su file}
\label{cha:file_IO_interface}
-
Esamineremo in questo capitolo le due interfacce di programmazione che
consentono di gestire i dati mantenuti nei file. Cominceremo con quella nativa
del sistema, detta dei \itindex{file~descriptor} \textit{file descriptor}, che
La duplicazione dei file descriptor può essere effettuata anche usando la
funzione di controllo dei file \func{fcntl} (che esamineremo in
-sez.~\ref{sec:file_fcntl_ioctl}) con il parametro \const{F\_DUPFD}. L'operazione ha
-la sintassi \code{fcntl(oldfd, F\_DUPFD, newfd)} e se si usa 0 come valore per
-\param{newfd} diventa equivalente a \func{dup}. La sola differenza fra le due
-funzioni (a parte la sintassi ed i diversi codici di errore) è che \func{dup2}
-chiude il file descriptor \param{newfd} se questo è già aperto, garantendo che
-la duplicazione sia effettuata esattamente su di esso, invece \func{fcntl}
-restituisce il primo file descriptor libero di valore uguale o maggiore
-di \param{newfd}, per cui se \param{newfd} è aperto la duplicazione avverrà su
-un altro file descriptor.
+sez.~\ref{sec:file_fcntl_ioctl}) con il parametro \const{F\_DUPFD}.
+L'operazione ha la sintassi \code{fcntl(oldfd, F\_DUPFD, newfd)} e se si usa 0
+come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
+differenza fra le due funzioni (a parte la sintassi ed i diversi codici di
+errore) è che \func{dup2} chiude il file descriptor \param{newfd} se questo è
+già aperto, garantendo che la duplicazione sia effettuata esattamente su di
+esso, invece \func{fcntl} restituisce il primo file descriptor libero di
+valore uguale o maggiore di \param{newfd}, per cui se \param{newfd} è aperto
+la duplicazione avverrà su un altro file descriptor.
Su Linux inoltre è presente una terza funzione di sistema non
standard,\footnote{la funzione è stata introdotta con il kernel 2.6.27 e resa
possibili valori per \var{cmd}, e del relativo significato, dei codici di
errore restituiti e del tipo del terzo argomento (cui faremo riferimento con
il nome indicato nel precedente prototipo), è riportata di seguito:
-\begin{basedescript}{\desclabelwidth{2.0cm}}
+\begin{basedescript}{\desclabelwidth{1.8cm}}
\item[\const{F\_DUPFD}] trova il primo file descriptor disponibile di valore
maggiore o uguale ad \param{arg}, e ne fa un duplicato
di \param{fd}, ritorna il nuovo file descriptor in caso di successo e $-1$
\macro{\_POSIX\_C\_SOURCE} ad un valore adeguato secondo quanto visto in
sez.~\ref{sec:intro_gcc_glibc_std}).
-\item[\const{F\_GETFD}] ritorna il valore dei \textit{file descriptor flags} di
- \param{fd} in caso di successo o $-1$ in caso di errore, il terzo argomento
- viene ignorato. Non sono previsti errori diversi da \errval{EBADF}. Al
- momento l'unico flag usato è quello di \itindex{close-on-exec}
- \textit{close-on-exec}, identificato dalla costante \const{FD\_CLOEXEC}, che
- serve a richiedere che il file venga chiuso nella esecuzione di una
- \func{exec} (vedi sez.~\ref{sec:proc_exec}). Un valore nullo significa
- pertanto che il flag non è impostato.
+\item[\const{F\_GETFD}] restituisce il valore dei \textit{file descriptor
+ flags} di \param{fd} in caso di successo o $-1$ in caso di errore, il
+ terzo argomento viene ignorato. Non sono previsti errori diversi da
+ \errval{EBADF}. Al momento l'unico flag usato è quello di
+ \itindex{close-on-exec} \textit{close-on-exec}, identificato dalla costante
+ \const{FD\_CLOEXEC}, che serve a richiedere che il file venga chiuso nella
+ esecuzione di una \func{exec} (vedi sez.~\ref{sec:proc_exec}). Un valore
+ nullo significa pertanto che il flag non è impostato.
\item[\const{F\_SETFD}] imposta il valore dei \textit{file descriptor flags}
al valore specificato con \param{arg}, ritorna un valore nullo in caso di
dell'argomento \param{flags} di \func{open} che vengono memorizzati nella
relativa voce della \textit{file table} all'apertura del file, vale a dire
quelli riportati in tab.~\ref{tab:open_access_mode_flag} e
- tab.~\ref{tab:open_operation_flag}).
+ tab.~\ref{tab:open_operation_flag}). Si ricordi che quando si usa la
+ funzione per determinare le modalità di accesso con cui è stato aperto il
+ file è necessario estrarre i bit corrispondenti nel \textit{file status
+ flag} con la maschera \const{O\_ACCMODE} come già accennato in
+ sez.~\ref{sec:file_open_close}.
\item[\const{F\_SETFL}] imposta il valore dei \textit{file status flags} al
valore specificato da \param{arg}, ritorna un valore nullo in caso di
amministratore.\footnote{per la precisione occorre la capacità
\itindex{capabilities} \const{CAP\_LEASE}.}
- Il comando è specifico di Linux ed utilizzabile solo se si è definita la
- macro \macro{\_GNU\_SOURCE}. Il comando è presente a partire dai kernel
- della serie 2.4.x, quando è stato introdotto il supporto \textit{file
- lease}, per cui un processo che detiene un \textit{lease} su un file
- riceve una notifica qualora un altro processo cerchi di eseguire una
- \func{open} o una \func{truncate} su di esso. Questa funzionalità è trattata
- in dettaglio in sez.~\ref{sec:file_asyncronous_lease}.
+ Il supporto il supporto per i \textit{file lease}, che consente ad un
+ processo che detiene un \textit{lease} su un file di riceve una notifica
+ qualora un altro processo cerchi di eseguire una \func{open} o una
+ \func{truncate} su di esso è stato introdotto a partire dai kernel della
+ serie 2.4 Il comando è specifico di Linux ed utilizzabile solo se si è
+ definita la macro \macro{\_GNU\_SOURCE}. Questa funzionalità è trattata in
+ dettaglio in sez.~\ref{sec:file_asyncronous_lease}.
\item[\const{F\_NOTIFY}] attiva il meccanismo di notifica asincrona per cui
viene riportato al processo chiamante, tramite il segnale \signal{SIGIO} (o
dai kernel della serie 2.4.x, è trattata in dettaglio in
sez.~\ref{sec:file_asyncronous_lease}.
-\item[\const{F\_GETPIPE\_SZ}]
+\item[\const{F\_GETPIPE\_SZ}] restituisce in caso di successo la dimensione
+ del buffer associato alla \textit{pipe} \param{fd} (vedi
+ sez.~\ref{sec:ipc_pipes}) o $-1$ in caso di errore, il terzo argomento viene
+ ignorato. Non sono previsti errori diversi da \errval{EBADF}, che viene
+ restituito anche se il file descriptor non è una pipe. Il comando è
+ specifico di Linux, è disponibile solo a partire dal kernel 2.6.35, ed è
+ utilizzabile solo se si è definita la macro \macro{\_GNU\_SOURCE}.
-\item[\const{F\_SETPIPE\_SZ}]
+\item[\const{F\_SETPIPE\_SZ}] imposta la dimensione del buffer associato alla
+ \textit{pipe} \param{fd} (vedi sez.~\ref{sec:ipc_unix}) ad un valore uguale
+ o superiore a quello indicato dall'argomento \param{arg}. Ritorna un valore
+ nullo in caso di successo o $-1$ in caso di errore. Oltre a \errval{EBADF}
+ gli errori possibili sono \errcode{EBUSY} se si cerca di ridurre la
+ dimensione del buffer al di sotto della quantità di dati effettivamente
+ presenti su di esso ed \errcode{EPERM} se un processo non priviligiato cerca
+ di impostare un valore troppo alto. La dimensione minima del buffer è pari
+ ad una pagina di memoria, a cui verrà comunque arrotondata ogni dimensione
+ inferiore, il valore specificato viene in genere arrotondato per eccesso al
+ valore ritenuto più opportuno dal sistema, pertanto una volta eseguita la
+ modifica è opportuno rileggere la nuova dimensione con
+ \const{F\_GETPIPE\_SZ}. I processi non privilegiati\footnote{{per la
+ precisione occorre la capacità \itindex{capabilities}
+ \const{CAP\_SYS\_RESOURCE}.}} non possono impostare un valore valore
+ superiore a quello indicato da \sysctlfile{fs/pipe-size-max}. Il comando è
+ specifico di Linux, è disponibile solo a partire dal kernel 2.6.35, ed è
+ utilizzabile solo se si è definita la macro \macro{\_GNU\_SOURCE}.
\end{basedescript}
La maggior parte delle funzionalità controllate dai comandi di \func{fcntl}
-sono molto avanzate e richiedono degli approfondimenti ulteriori rispetto a
-quanto illustrato adesso; saranno pertanto riprese più avanti quando
-affronteremo le problematiche ad esse relative. In particolare le tematiche
-relative all'I/O asincrono e ai vari meccanismi di notifica saranno trattate
-in maniera esaustiva in sez.~\ref{sec:file_asyncronous_operation} mentre
-quelle relative al \itindex{file~locking} \textit{file locking} saranno
-esaminate in sez.~\ref{sec:file_locking}). L'uso di questa funzione con i
-socket verrà trattato in sez.~\ref{sec:sock_ctrl_func}.
+sono avanzate e richiedono degli approfondimenti ulteriori, saranno pertanto
+riprese più avanti quando affronteremo le problematiche ad esse relative. In
+particolare le tematiche relative all'I/O asincrono e ai vari meccanismi di
+notifica saranno trattate in maniera esaustiva in
+sez.~\ref{sec:file_asyncronous_operation} mentre quelle relative al
+\itindex{file~locking} \textit{file locking} saranno esaminate in
+sez.~\ref{sec:file_locking}). L'uso di questa funzione con i socket verrà
+trattato in sez.~\ref{sec:sock_ctrl_func}.
La gran parte dei comandi di \func{fcntl} (\const{F\_DUPFD}, \const{F\_GETFD},
\const{F\_SETFD}, \const{F\_GETFL}, \const{F\_SETFL}, \const{F\_GETLK},
-\const{F\_SETLK} e \const{F\_SETLKW}) sono presenti da molto tempo, sono
-previsti da SVr4 e 4.3BSD e standardizzati in POSIX.1-2001 che inoltre prevede
-gli ulteriori \const{F\_GETOWN} e \const{F\_SETOWN}. Pertanto nell'elenco si
-sono indicate esplicitamente soltanto le ulteriori richieste in termini delle
-macro di funzionalità di sez.~\ref{sec:intro_gcc_glibc_std} soltanto per le
+\const{F\_SETLK} e \const{F\_SETLKW}) sono previsti da SVr4 e 4.3BSD e
+standardizzati in POSIX.1-2001 che inoltre prevede gli ulteriori
+\const{F\_GETOWN} e \const{F\_SETOWN}. Pertanto nell'elenco si sono indicate
+esplicitamente soltanto le ulteriori richieste in termini delle macro di
+funzionalità di sez.~\ref{sec:intro_gcc_glibc_std} soltanto per le
funzionalità inserite in standard successivi o specifiche di Linux.
-Si tenga presente infine che quando si usa la funzione per determinare le
-modalità di accesso con cui è stato aperto il file (attraverso l'uso del
-comando \const{F\_GETFL}) è necessario estrarre i bit corrispondenti nel
-\textit{file status flag} che si è ottenuto. Infatti la definizione corrente
-di quest'ultimo non assegna bit separati alle tre diverse modalità
-\const{O\_RDONLY}, \const{O\_WRONLY} e \const{O\_RDWR}.\footnote{in Linux
- queste costanti sono poste rispettivamente ai valori 0, 1 e 2.} Per questo
-motivo il valore della modalità di accesso corrente si ottiene eseguendo un
-AND binario del valore di ritorno di \func{fcntl} con la maschera
-\const{O\_ACCMODE} (anch'essa definita in \headfile{fcntl.h}), che estrae i
-bit di accesso dal \textit{file status flag}.
-
-
% \subsection{La funzione \func{ioctl}}
% \label{sec:file_ioctl}
-Benché il concetto di \textit{everything is a file} si sia dimostrato molto
-valido anche per l'interazione con i dispositivi più vari, fornendo una
-interfaccia che permette di interagire con essi tramite le stesse funzioni
-usate per i normali file di dati, esisteranno sempre caratteristiche
-peculiari, specifiche dell'hardware e della funzionalità che ciascun
-dispositivo può provvedere, che non possono venire comprese in questa
+Benché l'interfaccia di gestione dell'I/O sui file di cui abbiamo parlato
+finora si sia dimostrata valida anche per l'interazione diretta con le
+periferiche attraverso i loro file di dispositivo, consentendo di usare le
+stesse funzioni utilizzate per i normali file di dati, esistono però
+caratteristiche peculiari, specifiche dell'hardware e delle funzionalità che
+ciascun dispositivo può provvedere, che non possono venire comprese in questa
interfaccia astratta come ad esempio l'impostazione della velocità di una
porta seriale, o le dimensioni di un framebuffer.
Per questo motivo nell'architettura del sistema è stata prevista l'esistenza
-di una funzione apposita, \funcd{ioctl}, con cui poter compiere le operazioni
-specifiche di ogni dispositivo particolare, usando come riferimento il solito
-file descriptor. Il prototipo di questa funzione è:
+di una apposita funzione di sistema, \funcd{ioctl}, come meccanismo generico
+per compiere operazioni specializzate; il suo prototipo è:
\begin{funcproto}{
\fhead{sys/ioctl.h}
ed inoltre \errval{EBADF} e \errval{EFAULT} nel loro significato generico.}
\end{funcproto}
-La funzione esegue l'operazione di controllo specificata da \param{request}
-sul file descriptor \param{fd} e serve in sostanza come meccanismo generico
-per fare tutte quelle operazioni che non rientrano nell'interfaccia ordinaria
-della gestione dei file e che non è possibile effettuare con le funzioni
-esaminate finora. La funzione richiede che si passi come primo argomento un
-file descriptor regolarmente aperto, e l'operazione da compiere viene
-selezionata attraverso il valore dell'argomento \param{request}. Il terzo
+
+La funzione richiede che si passi come primo argomento un file
+descriptor \param{fd} regolarmente aperto, mentre l'operazione da compiere
+deve essere incata dal valore dell'argomento \param{request}. Il terzo
argomento dipende dall'operazione prescelta; tradizionalmente è specificato
come \code{char * argp}, da intendersi come puntatore ad un area di memoria
-generica,\footnote{all'epoca della creazione di questa funzione infatti ancora
- non era stato introdotto il tipo \ctyp{void}.} ma per certe operazioni può
-essere omesso, e per altre è un semplice intero.
+generica (all'epoca della creazione di questa funzione infatti ancora non era
+stato introdotto il tipo \ctyp{void}) ma per certe operazioni può essere
+omesso, e per altre è un semplice intero.
Normalmente la funzione ritorna zero in caso di successo e $-1$ in caso di
-errore, ma per alcune operazione il valore di ritorno, che nel caso viene
-impostato ad un valore positivo, può essere utilizzato come parametro di
-uscita. È più comune comunque restituire i risultati all'indirizzo puntato dal
-terzo argomento.
+errore, ma per alcune operazioni il valore di ritorno, che nel caso viene
+impostato ad un valore positivo, può essere utilizzato come indicazione del
+risultato della stessa. È più comune comunque restituire i risultati
+all'indirizzo puntato dal terzo argomento.
Data la genericità dell'interfaccia non è possibile classificare in maniera
sistematica le operazioni che si possono gestire con \func{ioctl}, un breve
\begin{itemize*}
\item il cambiamento dei font di un terminale.
\item l'esecuzione di una traccia audio di un CDROM.
-\item i comandi di avanti veloce e riavvolgimento di un nastro.
+\item i comandi di avanti veloce e di riavvolgimento di un nastro.
\item il comando di espulsione di un dispositivo rimovibile.
\item l'impostazione della velocità trasmissione di una linea seriale.
\item l'impostazione della frequenza e della durata dei suoni emessi dallo
Data la assoluta specificità della funzione, il cui comportamento varia da
dispositivo a dispositivo, non è possibile fare altro che dare una descrizione
-sommaria delle sue caratteristiche; torneremo ad esaminare in
-seguito\footnote{per l'uso di \func{ioctl} con i socket si veda
- sez.~\ref{sec:sock_ctrl_func}.} quelle relative ad alcuni casi specifici (ad
-esempio la gestione dei terminali è effettuata attraverso \func{ioctl} in
-quasi tutte le implementazioni di Unix), qui riportiamo solo l'elenco delle
-operazioni che sono predefinite per qualunque file,\footnote{in particolare
- queste operazioni sono definite nel kernel a livello generale, e vengono
- sempre interpretate per prime, per cui, come illustrato in \cite{LinDevDri},
- eventuali operazioni specifiche che usino lo stesso valore verrebbero
- ignorate.} caratterizzate dal prefisso \texttt{FIO}:
+sommaria delle sue caratteristiche; torneremo ad esaminare in seguito quelle
+relative ad alcuni casi specifici, ad esempio la gestione dei terminali è
+effettuata attraverso \func{ioctl} in quasi tutte le implementazioni di Unix,
+mentre per l'uso di \func{ioctl} con i socket si veda
+sez.~\ref{sec:sock_ctrl_func}.
+
+Riportiamo qui solo l'elenco delle operazioni che sono predefinite per
+qualunque file, caratterizzate dal prefisso \texttt{FIO}. Queste operazioni
+sono definite nel kernel a livello generale, e vengono sempre interpretate per
+prime, per cui, come illustrato in \cite{LinDevDri}, eventuali operazioni
+specifiche che usino lo stesso valore verrebbero ignorate:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{FIOCLEX}] imposta il flag di \itindex{close-on-exec}
\textit{close-on-exec} sul file, in questo caso, essendo usata come
% TODO aggiungere FIBMAP e FIEMAP, vedi http://lwn.net/Articles/260795/,
% http://lwn.net/Articles/429345/
-
Si noti però come la gran parte di queste operazioni specifiche dei file (per
essere precisi le prime sei dell'elenco) siano effettuabili in maniera
generica anche tramite l'uso di \func{fcntl}. Le due funzioni infatti sono
al fatto che alle origini di Unix i progettisti considerarono che era
necessario trattare diversamente rispetto alle operazione di controllo delle
modalità di I/O file e dispositivi usando \func{fcntl} per i primi e
-\func{ioctl} per i secondi;\footnote{all'epoca tra l'altro i dispositivi che
- usavano \func{ioctl} erano sostanzialmente solo i terminali, il che spiega
- l'uso comune di \errcode{ENOTTY} come codice di errore.} oggi non è più così
-ma le due funzioni sono rimaste.
+\func{ioctl} per i secondi, all'epoca tra l'altro i dispositivi che usavano
+\func{ioctl} erano sostanzialmente solo i terminali, il che spiega l'uso
+comune di \errcode{ENOTTY} come codice di errore. Oggi non è più così ma le
+due funzioni sono rimaste.
% TODO trovare qualche posto per la eventuale documentazione delle seguenti
% (bassa/bassissima priorità)
% EXT4_IOC_MOVE_EXT (dal 2.6.31)
-
-
% \chapter{}
\section{L'interfaccia standard ANSI C}