X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileunix.tex;h=40d022815a8fcd909a6e729af3538ed765c63f81;hp=e99db645c82b063a12aba310d51f619567a085b4;hb=9790ea16d447835b894169fa997314fd5fb0ebd5;hpb=327a8452b33c9626ebec4cfe6c9d6daad54f4b19 diff --git a/fileunix.tex b/fileunix.tex index e99db64..40d0228 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -1,6 +1,7 @@ -\chapter{I file: l'interfaccia standard unix} +\chapter{I file: l'interfaccia standard Unix} \label{cha:file_unix_interface} + 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 @@ -13,7 +14,7 @@ dallo standard ANSI C che affronteremo al \capref{cha:files_std_interface}. \section{L'architettura di base} \label{sec:file_base_arch} -In questa sezione faremo una breve introduzione sulla architettura su cui è +In questa sezione faremo una breve introduzione sull'architettura su cui è basata dell'interfaccia dei \textit{file descriptor}, che, sia pure con differenze nella realizzazione pratica, resta sostanzialmente la stessa in tutte le implementazione di un sistema unix-like. @@ -68,7 +69,7 @@ file, fra cui: campo \var{f\_pos}). \item un puntatore all'inode\footnote{nel kernel 2.4.x si è in realtà passati ad un puntatore ad una struttura \var{dentry} che punta a sua volta - all'inode passando per la nuova struttura del VFS} del file. + all'inode passando per la nuova struttura del VFS.} del file. %\item un puntatore alla tabella delle funzioni \footnote{la struttura % \var{f\_op} descritta in \secref{sec:file_vfs_work}} che si possono usare % sul file. @@ -81,7 +82,7 @@ varie strutture di dati sulla quale essa \centering \includegraphics[width=13cm]{img/procfile} \caption{Schema della architettura dell'accesso ai file attraverso - l'interfaccia dei \textit{file descriptor}} + l'interfaccia dei \textit{file descriptor}.} \label{fig:file_proc_file} \end{figure} Ritorneremo su questo schema più volte, dato che esso è fondamentale per @@ -153,7 +154,7 @@ restano i limiti imposti dall'amministratore (vedi \secref{sec:sys_limits}). \section{Le funzioni base} \label{sec:file_base_func} -L'interfaccia standard unix per l'input/output sui file è basata su cinque +L'interfaccia standard Unix per l'input/output sui file è basata su cinque funzioni fondamentali: \func{open}, \func{read}, \func{write}, \func{lseek} e \func{close}, usate rispettivamente per aprire, leggere, scrivere, spostarsi e chiudere un file. @@ -245,7 +246,7 @@ sempre il file descriptor con il valore pi zero. Se il file è un terminale o una fifo il flag verrà ignorato, negli altri casi il comportamento non è specificato. \\ \macro{O\_NOFOLLOW} & se \var{pathname} è un link simbolico la chiamata - fallisce. Questa è una estensione BSD aggiunta in Linux dal kernel 2.1.126. + fallisce. Questa è un'estensione BSD aggiunta in Linux dal kernel 2.1.126. Nelle versioni precedenti i link simbolici sono sempre seguiti, e questa opzione è ignorata. \\ \macro{O\_DIRECTORY} & se \var{pathname} non è una directory la chiamata @@ -264,15 +265,16 @@ sempre il file descriptor con il valore pi 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 una \func{read} in - assenza di dati da leggere e quello di una \func{write} in caso di + 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. \\ \macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di \macro{O\_NONBLOCK}.\\ - \macro{O\_ASYNC} & apre il file per l'input/output in modalità - asincrona. Quando è settato viene generato un segnale di \macro{SIGIO} - tutte le volte che è disponibile dell'input sul file. \\ + \macro{O\_ASYNC} & apre il file per l'I/O in modalità + asincrona (vedi \secref{sec:file_asyncronous_io}). Quando è settato 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 \func{write} bloccherà fino al completamento della scrittura di tutti dati sul sull'hardware sottostante.\\ @@ -303,7 +305,7 @@ sempre il file descriptor con il valore pi \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 + un'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.} Questa caratteristica permette di prevedere qual'è il valore del file @@ -317,7 +319,7 @@ Il nuovo file descriptor non 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}) ed l'offset è settato all'inizio del file. +\secref{sec:proc_exec}) e l'offset è settato 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 @@ -450,7 +452,7 @@ La nuova posizione 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 - \macro{L\_SET}, \macro{L\_INCR} e \macro{L\_XTND}}: + \macro{L\_SET}, \macro{L\_INCR} e \macro{L\_XTND}.}: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\macro{SEEK\_SET}] si fa riferimento all'inizio del file: il valore di \var{offset} è la nuova posizione. @@ -480,9 +482,9 @@ essersi spostata, ma noi scriveremo alla posizione settata in precedenza. 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 i tre casi citati nel prototipo, vale anche per tutti quei dispositivi che non -supportano questa funzione, come ad esempio per le \acr{tty}\footnote{altri +supportano questa funzione, come ad esempio per le \acr{tty}.\footnote{altri sistemi, usando \macro{SEEK\_SET}, in questo caso ritornano il numero di - caratteri che vi sono stati scritti}. Lo standard POSIX però non specifica + caratteri che vi sono stati scritti.} Lo standard POSIX però non specifica niente al proposito. Infine alcuni device, ad esempio \file{/dev/null}, non causano un errore ma restituiscono un valore indefinito. @@ -536,44 +538,42 @@ come valore di ritorno. 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:signal_xxx}. - -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}. @@ -581,10 +581,15 @@ Cerca di leggere \var{count} byte dal file \var{fd}, a partire dalla posizione in caso di errore, nel qual caso \var{errno} viene settata secondo 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. @@ -636,7 +641,7 @@ i file ordinari il numero di byte scritti da \var{count}, a meno di un errore. Negli altri casi si ha lo stesso comportamento di \func{read}. -Anche per \func{write} lo standard Unix98 definisce una analoga \func{pwrite} +Anche per \func{write} lo standard Unix98 definisce un'analoga \func{pwrite} per scrivere alla posizione indicata senza modificare la posizione corrente nel file, il suo prototipo è: \begin{prototype}{unistd.h} @@ -731,7 +736,7 @@ corrente nel file varier Si noti inoltre che anche i flag di stato del file (quelli settati 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 + \var{file}.}, vengono in questo caso condivisi. Ai file però sono associati anche altri flag, dei quali l'unico usato al momento è \macro{FD\_CLOEXEC}, detti \textit{file descriptor flags}. Questi ultimi sono tenuti invece in \var{file\_struct}, e perciò sono specifici di ciascun processo e non vengono @@ -765,14 +770,13 @@ file sar 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 +Il problema è che usare due system call in successione non è un'operazione atomica; il problema è stato risolto introducendo la modalità \macro{O\_APPEND}. In questo caso infatti, come abbiamo descritto in precedenza, è 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. +essendo interrompibile da un altro processo costituisce un'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 @@ -798,10 +802,10 @@ secondo tempo rispetto al momento della esecuzione della \func{write}. Per questo motivo, quando è necessaria una sincronizzazione dei dati, il sistema mette a disposizione delle funzioni che provvedono a forzare lo -scarico dei dati dai buffer del kernel\footnote{come già accennato neanche +scarico dei dati dai buffer del kernel.\footnote{come già accennato neanche questo da la garanzia assoluta che i dati siano integri dopo la chiamata, l'hardware dei dischi è in genere dotato di un suo meccanismo interno che - può ritardare ulteriormente la scrittura effettiva.}. La prima di queste + può ritardare ulteriormente la scrittura effettiva.} La prima di queste funzioni è \func{sync} il cui prototipo è: \begin{prototype}{unistd.h}{int sync(void)} @@ -847,10 +851,10 @@ di \var{fstat} come i tempi del file). Si tenga presente che questo non comporta la sincronizzazione della directory che contiene il file (e scrittura della relativa voce su -disco) che deve essere effettuata esplicitamente\footnote{in realtà per +disco) che deve essere effettuata esplicitamente.\footnote{in realtà per il filesystem \acr{ext2}, quando lo si monta con l'opzione \cmd{sync}, il kernel provvede anche alla sincronizzazione automatica delle voci - delle directory.}. + delle directory.} \subsection{La funzioni \func{dup} e \func{dup2}} @@ -880,7 +884,8 @@ 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}. +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} @@ -888,18 +893,30 @@ nella \textit{file table}. \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}. @@ -914,11 +931,13 @@ specificare esplicitamente il nuovo file descriptor; il suo prototipo 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 @@ -927,12 +946,6 @@ se 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_pipes} quando -tratteremo le pipe. - \subsection{La funzione \func{fcntl}} \label{sec:file_fcntl} @@ -983,7 +996,8 @@ valori 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). + nella terza sezione di \tabref{tab:file_open_flags}.\footnote{NdA 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 @@ -1006,17 +1020,21 @@ valori \item[\macro{F\_SETOWN}] setta 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. -\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\_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. 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}. + 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}). \end{basedescript} La maggior parte delle funzionalità di \func{fcntl} sono troppo avanzate per @@ -1026,7 +1044,7 @@ avanti quando affronteremo le problematiche ad esse relative. Per determinare le modalità di accesso inoltre è necessario estrarre i bit di accesso (ottenuti con il comando \macro{F\_GETFL}); infatti la definizione corrente non assegna bit separati a \macro{O\_RDONLY}, \macro{O\_WRONLY} e -\macro{O\_RDWR}\footnote{posti rispettivamente ai valori 0, 1 e 2}, per cui il +\macro{O\_RDWR},\footnote{posti rispettivamente ai valori 0, 1 e 2.} per cui il valore si ottiene eseguendo un AND binario del valore di ritorno di \func{fcntl} con la maschera \macro{O\_ACCMODE} anch'essa definita in \file{fcntl.h}. @@ -1050,14 +1068,16 @@ per ogni singolo dispositivo. Il prototipo di questa funzione \begin{prototype}{sys/ioctl.h}{int ioctl(int fd, int request, ...)} Manipola il dispositivo sottostante, usando il parametro \param{request} per specificare l'operazione richiesta e il terzo parametro (usualmente di tipo - \param{char * argp}) per il trasferimento dell'informazione necessaria. + \param{char * argp} o \param{int argp}) per il trasferimento + dell'informazione necessaria. \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: \begin{errlist} - \item[\macro{ENOTTY}] il file \param{fd} non è associato con un device. + \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[\macro{EINVAL}] gli argomenti \param{request} o \param{argp} non sono validi. \end{errlist} @@ -1066,9 +1086,45 @@ per ogni singolo dispositivo. Il prototipo di questa funzione La funzione serve in sostanza per fare tutte quelle operazioni che non si adattano al design dell'architettura dei file e che non è possibile effettuare -con le funzioni esaminate finora. Per questo motivo non è possibile fare altro -che darne una descrizione generica; torneremo ad esaminarla in seguito, quando -si tratterà di applicarla ad alcune problematiche specifiche. +con le funzioni esaminate finora. Esse vengono selezionate attraverso il +valore di \param{request} e gli eventuali risultati possono essere restituiti +sia attraverso il valore di ritorno che attraverso il terzo argomento +\param{argp}. Sono esempi delle operazioni gestite con una \func{ioctl}: +\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 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 + speaker. +\end{itemize*} + +In generale ogni dispositivo ha un suo insieme di possibili diverse operazioni +effettuabili attraverso \func{ioctl}, che sono definite nell'header file +\file{sys/ioctl.h}, e devono essere usate solo sui dispositivi cui fanno +riferimento. Infatti anche se in genere i valori di \param{request} sono +opportunamente differenziati a seconda del dispositivo\footnote{il kernel usa + un apposito \textit{magic number} per distinguere ciascun dispositivo nella + definizione delle macro da usare per \param{request}, in modo da essere + sicuri che essi siano sempre diversi, ed il loro uso causi al più un errore. + Si veda il capitolo quinto di \cite{LinDevDri} per una trattazione + dettagliata dell'argomento.} in alcuni casi, relativi a valori assegnati +prima che questa differenziazione diventasse pratica corrente si potrebbe +avere + +Per questo motivo non è possibile fare altro che darne una descrizione +generica; 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), 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{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. +\end{basedescript} +relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}. %%% Local Variables: