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 restituisce il file descriptor, e tutte le successive
-operazioni devono passare il \textit{file descriptors} come argomento.
+operazioni devono passare il \textit{file descriptor} come argomento.
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
strutture di dati sulla quale essa è basata.
\begin{figure}[htb]
\centering
- \includegraphics[width=14cm]{img/procfile.eps}
+ \includegraphics[width=14cm]{img/procfile}
\caption{Schema della architettura dell'accesso ai file attraverso
l'interfaccia dei \textit{file descriptor}}
\label{fig:file_proc_file}
che non esiste.
\item \macro{ETXTBSY} si è cercato di accedere in scrittura all'immagine di
un programma in esecuzione.
- \item \macro{ELOOP} si sono incotrati troppi link simbolici nel risolvere
+ \item \macro{ELOOP} si sono incontrati troppi link simbolici nel risolvere
pathname o si è indicato \macro{O\_NOFOLLOW} e \var{pathname} è un link
simbolico.
\end{errlist}
La funzione apre il file, usando il primo file descriptor libero, e crea
l'opportuna voce (cioè la struttura \var{file}) nella file table. Viene usato
-sempre il file descriptor con il valore più basso, questa caratteristica
-permette di prevedere qual'è il valore che si otterrà e viene talvolta usata
+sempre il file descriptor con il valore più basso. Questa caratteristica
+permette di prevedere qual'è il valore che si otterrà, e viene talvolta usata
da alcune applicazioni per sostituire i file corrispondenti ai file standard
di \secref{sec:file_std_descr}: se ad esempio si chiude lo standard input e si
apre subito dopo un nuovo file questo diventerà il nuovo standard input (avrà
\hline
\textbf{Flag} & \textbf{Descrizione} \\
\hline
- \hline % modailtà di accesso al file
+ \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. \\
- \hline % modalita di apertura del file
+ \hline % modalità di apertura del file
\hline
\macro{O\_CREAT} & se il file non esiste verrà creato, con le regole di
titolarità del file viste in \secref{sec:file_ownership}. Il parametro
\macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di
\macro{O\_NONBLOCK}.\\
\macro{O\_ASYNC} & apre il file per l'input/output in modalità
- asincrona. Non è supportato in Linux. \\
+ asincrona. Quando è settato viene generato un segnale di \macro{SIGIO}
+ tutte le volte che è disponibile dell'input sul file. \\
\macro{O\_SYNC} & apre il file per l'input/output sincrono, ogni
\func{write} bloccherà fino al completamento della scrittura di tutti dati
sul sull'hardware sottostante.\\
di montaggio.\\
\hline
\end{tabular}
- \caption{Costanti definite in \file{fcntl.h} per indicare i vari bit
- usabili per il specificare parametro \var{flags} di \func{open}.}
+ \caption{Valori e significato dei vari bit del \textit{file status flag}.}
\label{tab:file_open_flags}
\end{table}
\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}
+ 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
- condition}
+ condition, vedi \secref{sec:file_atomic}.}
\footnotetext[5]{l'opzione origina da SVr4, dove però causava il ritorno da
una \func{read} con un valore nullo e non con un errore, questo introduce
una ambiguità, dato che come vedremo in \secref{sec:file_read} il ritorno di
- zero da parte di \func{read} ha il significato di una end-of-file}
+ zero da parte di \func{read} ha il significato di una end-of-file.}
Il nuovo file descriptor non è condiviso con nessun altro processo, (torneremo
Come già accennato in \secref{sec:file_fd} a ciascun file aperto è associata
una \textsl{posizione corrente nel file} (il cosiddetto \textit{file offset},
mantenuto nel campo \var{f\_pos} di \var{file}) espressa da un numero intero
-positivo come numero di bytes dall'inizio del file. Tutte le operazioni di
+positivo come numero di byte dall'inizio del file. Tutte le operazioni di
lettura e scrittura avvengono a partire da questa posizione che viene
automaticamente spostata in avanti del numero di byte letti o scritti.
seguenti valori\footnote{per compatibilità con alcune vecchie notazioni
questi valori possono essere rimpiazzati rispettivamente con 0, 1 e 2 o con
\macro{L\_SET}, \macro{L\_INCR} e \macro{L\_XTND}}:
-\begin{description}
-\item \macro{SEEK\_SET} si fa riferimento all'inizio del file: il valore di
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{SEEK\_SET}] si fa riferimento all'inizio del file: il valore di
\var{offset} è la nuova posizione.
-\item \macro{SEEK\_CUR} si fa riferimento alla posizione corrente del file:
+\item[\macro{SEEK\_CUR}] si fa riferimento alla posizione corrente del file:
\var{offset} che può essere negativo e positivo.
-\item \macro{SEEK\_END} si fa riferimento alla fine del file: il valore di
+\item[\macro{SEEK\_END}] si fa riferimento alla fine del file: il valore di
\var{offset} può essere negativo e positivo.
-\end{description}
+\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
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}, e quando si vuole
-essere sicuri di scrivere alla fine del file questo deve essere posto in
-modalità \macro{O\_APPEND}.
+(questa è una potenziale sorgente di \textit{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
il cui prototipo è:
\begin{prototype}{unistd.h}{ssize\_t read(int fd, void * buf, size\_t count)}
- La funzione cerca di leggere \var{count} bytes dal file \var{fd} al buffer
+ La funzione cerca di leggere \var{count} byte dal file \var{fd} al buffer
\var{buf}.
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:
\begin{errlist}
\item \macro{EINTR} la funzione è stata interrotta da un segnale prima di
- aver potuto leggere quasiasi dato.
+ aver potuto leggere qualsiasi dato.
\item \macro{EAGAIN} la funzione non aveva nessun dato da restituire e si
era aperto il file in modalità \macro{O\_NONBLOCK}.
\end{errlist}
La funzione tenta di leggere \var{count} byte a partire dalla posizione
corrente nel file; dopo la lettura la posizione è spostata automaticamente in
-avanti del numero di bytes letti. Se \var{count} è zero la funzione
+avanti del numero di byte letti. Se \var{count} è zero la funzione
restituisce zero senza nessun altro risultato.
Si deve sempre tener presente che non è detto che la funzione \func{read}
comportamento normale e non un errore, che però bisogna sempre tenere
presente.
-La prima e più ovvia di queste ragioni è che si è chiesto di leggere più bytes
+La prima e più ovvia di queste ragioni è che si è chiesto di leggere più byte
di quanto il file ne contenga. In questo caso il file viene letto fino alla
sua fine, e la funzione ritorna regolarmente il numero di byte letti
effettivamente. Se ripetessimo la lettura \func{read} restituirebbe uno zero.
Lo standard Unix98\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
- aggiutno con la versione 2.1} (vedi \secref{sec:intro_opengroup}) prevede la
+ aggiunto con la versione 2.1} (vedi \secref{sec:intro_opengroup}) prevede la
definizione di un'altra funzione di lettura, \func{pread}, che diventa
accessibile con la definizione:
\begin{verbatim}
\begin{prototype}{unistd.h}
{ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
-La funzione cerca di leggere \var{count} bytes dal file \var{fd}, a partire
+La funzione cerca di leggere \var{count} byte dal file \var{fd}, a partire
dalla posizione \var{offset}, nel buffer \var{buf}.
La funzione ritorna il numero di byte letti in caso di successo e -1 in caso
Per scrivere su un file si usa la funzione \func{write}, il cui prototipo è:
\begin{prototype}{unistd.h}{ssize\_t write(int fd, void * buf, size\_t count)}
- La funzione scrive \var{count} bytes dal buffer \var{buf} sul file \var{fd}.
+ La funzione scrive \var{count} byte dal buffer \var{buf} sul file \var{fd}.
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:
\macro{SIGPIPE}, se questo viene gestito (o bloccato o ignorato) la
funzione ritorna questo errore.
\item \macro{EINTR} la funzione è stata interrotta da un segnale prima di
- aver potuto scerivere quasiasi dato.
+ aver potuto scrivere qualsiasi dato.
\item \macro{EAGAIN} la funzione non aveva nessun dato da restituire e si
era aperto il file in modalità \macro{O\_NONBLOCK}.
\end{errlist}
Come nel caso di \func{read} la funzione tenta di scrivere \var{count} byte a
partire dalla posizione corrente nel file e sposta automaticamente la
-posizione in avanti del numero di bytes scritti. Se il file è aperto in
+posizione in avanti del numero di byte scritti. Se il file è aperto in
modalità \macro{O\_APPEND} i dati vengono sempre scritti alla fine del file.
Lo standard POSIX richiede che i dati scritti siano immediatamente disponibili
ad una \func{read} chiamata dopo che la \func{write} che li ha scritti è
supportino questa capacità.
Se \var{count} è zero la funzione restituisce zero senza fare nient'altro. Per
-i file ordinari il numero di bytes scritti è sempre uguale a quello indicato
+i file ordinari il numero di byte scritti è sempre uguale a quello indicato
da \var{count}, a meno di un errore. Negli altri casi si ha lo stesso
comportamento di \func{read}.
{ssize\_t pwrite(int fd, void * buf, size\_t count, off\_t offset)}
La funzione cerca di scrivere sul file \var{fd}, a partire dalla posizione
-\var{offset}, \var{count} bytes dal buffer \var{buf}.
+\var{offset}, \var{count} byte dal buffer \var{buf}.
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
\section{Caratteristiche avanzate}
\label{sec:file_adv_func}
-In questa sezione approfondireme alcune delle caratteristiche più sottili
+In questa sezione approfondiremo alcune delle caratteristiche più sottili
della gestione file in un sistema unix-like, esaminando in dettaglio il
comportamento delle funzioni base, inoltre tratteremo alcune funzioni che
permettono di eseguire operazioni avanzate con i file.
\begin{figure}[htb]
\centering
- \includegraphics[width=14cm]{img/filemultacc.eps}
+ \includegraphics[width=14cm]{img/filemultacc}
\caption{Schema dell'accesso allo stesso file da parte di due processi
diversi}
\label{fig:file_mult_acc}
\begin{figure}[htb]
\centering
- \includegraphics[width=14cm]{img/fileshar.eps}
+ \includegraphics[width=14cm]{img/fileshar}
\caption{Schema dell'accesso ai file da parte di un processo figlio}
\label{fig:file_acc_child}
\end{figure}
È comunque possibile che due file descriptor di due processi diversi puntino
alla stessa voce nella \textit{file table}; questo è ad esempio il caso dei
-file aperti che venfono ereditati dal processo figlio all'esecuzione di una
+file aperti che vengono ereditati dal processo figlio all'esecuzione di una
\func{fork} (si ricordi quanto detto in \secref{sec:proc_fork}). La situazione
è illustrata in \figref{fig:file_acc_child}; dato che il processo figlio
riceve una copia dello spazio di indirizzi del padre, riceverà anche una copia
In questo modo padre e figlio avranno gli stessi file descriptor che faranno
riferimento alla stessa voce nella \textit{file table}, condividendo così la
-posizione corrente sul file. Questo ha le cosenguenze descritte a suo tempo in
+posizione corrente sul file. Questo ha le conseguenze descritte a suo tempo in
\secref{sec:proc_fork}: in caso di scrittura contemporanea la posizione
corrente nel file varierà per entrambi i processi (in quanto verrà modificato
\var{f\_pos} che è la stesso per entrambi).
Come si è visto in un sistema unix è sempre possibile per più processi
accedere in contemporanea allo stesso file, e che le operazioni di lettura e
-scrittura saranno fatte in base alla posizione corrente nel file. Ovviamente
-senza prevedere opportuni meccanismi di sincronizzazione le operazioni
-potranno mescolarsi in maniera imprevedibile. L'unica garanzia è che se si è
-in modalità \macro{O\_APPEND} il sistema assicura che si scriva (con il
-procedimento appena esposto) sempre alla fine del file.
-
+scrittura possono essere fatte da ogni processo in maniera autonoma in base
+ad una posizione corrente nel file che è locale a ciascuno di essi.
+
+Se dal punto di vista della lettura dei dati questo non comporta nessun
+problema, quando si andrà a scrivere le operazioni potranno mescolarsi in
+maniera imprevedibile. Il sistema però fornisce in alcuni casi la possibilità
+di eseguire alcune operazioni di scrittura in maniera coordinata anche senza
+utilizzare meccanismi di sincronizzazione più complessi (come il \textit{file
+ locking}, che esamineremo in \secref{cha:file_advanced}).
+
+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.
+
+Il problema è che usare due system call in successione non è una operazione
+atomica; il problema è stato risolto introducendo la modalità
+\macro{O\_APPEND}, in questo caso infatti, come abbiamo visto, è il kernel che
+aggiorna automaticamente la posizione alla fine del file prima di effettuare
+la scrittura, e poi estende il file. Tutto questo avviene all'interno di una
+singola system call (la \func{write}) che non essendo interrompibile da un
+altro processo costituisce una operazione atomica.
+
+Un altro caso tipico in cui è necessaria l'atomicità è quello in cui si vuole
+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.
+
+Per questo motivo sono stati introdotti i due flag \macro{O\_CREAT} e
+\macro{O\_EXCL}, in questo modo l'operazione di controllo dell'esistenza del
+file (con relativa uscita dalla funzione con un errore) e creazione in caso di
+assenza, diventa atomica essendo svolta tutta all'interno di una singola
+\func{open}.
\subsection{La funzioni \func{dup} e \func{dup2}}
\label{sec:file_dup}
+Abbiamo già visto in \secref{sec:file_sharing} come un processo figlio
+condivida gli stessi file descriptor del padre; è possibile però ottenere un
+comportamento analogo all'interno di uno stesso processo \textit{duplicando}
+un file descriptor. Per far questo si usa la funzione \func{dup} il cui
+prototipo è:
+\begin{prototype}{unistd.h}{int dup(int oldfd)}
+
+ La funzione crea una copia del file descriptor \param{oldfd}.
+
+ 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:
+ \begin{errlist}
+ \item \macro{EBADF} \param{oldfd} non è un file aperto.
+ \item \macro{EMFILE} si è raggiunto il numero massimo consentito di file
+ descriptor aperti.
+ \end{errlist}
+\end{prototype}
+La funzione ritorna, come \func{open}, il primo file descriptor libero. Il
+file descriptor è una copia esatta del precedente ed entrambi possono essere
+interscambiati nell'uso. Per capire meglio il funzionamento della funzione si
+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}.
\begin{figure}[htb]
- \centering \includegraphics[width=14cm]{img/filedup.eps}
+ \centering \includegraphics[width=14cm]{img/filedup}
\caption{Schema dell'accesso ai file duplicati}
\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 è:
+\begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)}
+
+ La funzione rende \param{newfd} una copia del file descriptor \param{oldfd}.
+
+ 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:
+ \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.
+ \item \macro{EMFILE} si è raggiunto il numero massimo consentito di file
+ descriptor aperti.
+ \end{errlist}
+\end{prototype}
+\noindent la funzione chiude il file descriptor \param{newfd} se è aperto.
+
+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}.
+
+L'operazione ha la sintassi \func{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
+come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
+differenza, a parte i codici di errore, è che \func{dup2} chiude il nuovo file
+se è già aperto mentre \func{fcntl} apre il primo disponibile con un valore
+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 più avanti quando tratteremo le
+pipe.
+
\subsection{La funzione \func{fcntl}}
\label{sec:file_fcntl}
+Oltre alle operazioni base esaminate in \secref{sec:file_base_func} esistono
+tutta una serie di operazioni ausiliarie che è possibile eseguire su un file
+descriptor. Per queste operazioni di manipolazione delle varie proprietà di un
+file descriptor viene usata la funzione \func{fcntl} il cui prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{fcntl.h}
+ \funcdecl{int fcntl(int fd, int cmd)}
+ \funcdecl{int fcntl(int fd, int cmd, long arg)}
+ \funcdecl{int fcntl(int fd, int cmd, struct flock * lock)}
+ La funzione esegue una delle possibili operazioni specificate da \param{cmd}
+ sul file \param{fd}.
+
+ 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:
+ \begin{errlist}
+ \item \macro{EBADF} \param{oldfd} non è un file aperto.
+ \end{errlist}
+\end{functions}
+
+Il comportamento di questa funzione è determinato dal valore del comando
+\param{cmd} che le viene fornito; in \secref{sec:file_dup} abbiamo incontrato
+un esempio per la duplicazione dei file descriptor, una lista dei possibili
+valori è riportata di seguito:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{F\_DUPFD}] trova il primo file descriptor disponibile di valore
+ maggiore o uguale ad \param{arg} e ne fa una copia di \var{fd}. In caso di
+ successo ritorna il nuovo file descriptor. Gli errori possibili sono
+ \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}
+ 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.
+\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
+ 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} (da verificare).
+\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
+ 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
+ \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
+ \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
+ sengali \macro{SIGIO} e \macro{SIGURG} per gli eventi associati al file
+ descriptor \var{fd}. I process group sono settati usando valori negativi.
+\item[\macro{F\_GETSIG}] restituisce il segnale mandato quando ci sono dati
+ disponibili in input sul file descriptor. Il valore 0 indica il default (che
+ è \macro{SIGIO}), un valore diverso da zero indica il segnale richiesto,
+ (che può essere lo stesso \macro{SIGIO}), nel qual caso al manipolatore del
+ segnale, se installato con \macro{SA\_SIGINFO}, vengono rese disponibili
+ informazioni ulteriori informazioni.
+\item[\macro{F\_SETSIG}] setta il segnale da inviare quando diventa possibile
+ effettuare I/O sul file descriptor. Il valore zero indica il default
+ (\macro{SIGIO}), ogni altro valore permette di rendere disponibile al
+ manipolatore del segnale ulteriori informazioni se si è usata
+ \macro{SA\_SIGINFO}.
+\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.
+
+Per determinare le modalità di accesso inoltre può essere necessario usare la
+
\subsection{La funzione \func{ioctl}}
\label{sec:file_ioctl}
+Benché il concetto di \textit{everything is a file} si sia dimostratato molto
+valido anche per l'interazione con i più vari dispositivi, con cui si può
+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
+una porta seriale, o le dimensioni di un framebuffer).
+
+Per questo motivo l'architettura del sistema ha previsto l'esistenza di una
+funzione speciale, \func{ioctl}, con cui poter compiere operazioni specifiche
+per ogni singolo dispositivo. Il prototipo di questa funzione è:
+
+\begin{prototype}{sys/ioctl.h}{int ioctl(int fd, int request, ...)}
+
+ La funzione manipola il sottostante dispositivo, usando il parametro
+ \param{request} per specificare l'operazione richiesta e il terzo parametro
+ (che usualmente è di tipo \param{char * argp}) per passare o ricevere
+ l'informazione necessaria al dispositivo.
+
+ La funzione nella maggior parte dei casi ritorna 0, alcune operazioni usano
+ però il valore di ritorno per restituire informazoni. In caso di errore
+ viene sempre restituito -1 e \var{errno} viene settata ad uno dei valori
+ seguenti:
+ \begin{errlist}
+ \item \macro{ENOTTY} il file \param{fd} non è associato con un device.
+ \item \macro{EINVAL} gli argomenti \param{request} o \param{argp} non sono
+ validi.
+ \end{errlist}
+ ed inoltre \macro{EBADF} e \macro{EFAULT}.
+\end{prototype}
+
+La funzione serve in sostanza per fare tutte quelle operazioni che non si
+adattano all'architettura di I/O di unix e che non è possibile effettuare con
+le funzioni esaminate finora. Per questo motivo non è possibile fare altro che
+una descrizione generica; torneremo ad esaminarla in seguito, quando si
+tratterà di applicarla ad alcune problematiche specifiche.
+