X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileunix.tex;h=e59fd0603d862100d8c68af41548434050e88836;hp=3a0f5a5d30371dc5bfa3d71403c2d391ac5e3119;hb=b38fb9f5c8fb8360f7ac296baa8f4a0bdd692d1c;hpb=276ae7fb9a1e43b6d5e5944071848094c8cc2c3b diff --git a/fileunix.tex b/fileunix.tex index 3a0f5a5..e59fd06 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -1,9 +1,9 @@ %% fileunix.tex %% -%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the -%% Free Software Foundation; with the Invariant Sections being "Prefazione", +%% Free Software Foundation; with the Invariant Sections being "Un preambolo", %% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the %% license is included in the section entitled "GNU Free Documentation %% License". @@ -34,7 +34,9 @@ tutte le implementazione di un sistema unix-like. \subsection{L'architettura dei \textit{file descriptor}} \label{sec:file_fd} -\index{file!descriptor|(} Per poter accedere al contenuto di un file occorre +\index{file!descriptor|(} + +Per poter accedere al contenuto di un file occorre creare un canale di comunicazione con il kernel che renda possibile operare su di esso (si ricordi quanto visto in sez.~\ref{sec:file_vfs_work}). Questo si fa aprendo il file con la funzione \func{open} che provvederà a localizzare @@ -91,6 +93,11 @@ file, fra cui: In fig.~\ref{fig:file_proc_file} si è riportato uno schema in cui è illustrata questa architettura, ed in cui si sono evidenziate le interrelazioni fra le varie strutture di dati sulla quale essa è basata. +Ritorneremo su questo schema più volte, dato che esso è fondamentale per +capire i dettagli del funzionamento dell'interfaccia dei \textit{file + descriptor}. +\index{file!descriptor|)} + \begin{figure}[htb] \centering \includegraphics[width=13cm]{img/procfile} @@ -98,11 +105,6 @@ varie strutture di dati sulla quale essa l'interfaccia dei \textit{file descriptor}.} \label{fig:file_proc_file} \end{figure} -Ritorneremo su questo schema più volte, dato che esso è fondamentale per -capire i dettagli del funzionamento dell'interfaccia dei \textit{file - descriptor}. -\index{file!descriptor|)} - @@ -115,23 +117,23 @@ 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}\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 -ingresso (nel caso della shell, è associato all'ingresso dal terminale, e -quindi alla lettura della tastiera). Il secondo file è il cosiddetto -\textit{standard output}, cioè il file su cui ci si aspetta debbano essere -inviati i dati in uscita (sempre nel caso della shell, è associato all'uscita -del terminale, e quindi alla scrittura sullo schermo). Il terzo è lo -\textit{standard error}, su cui viene inviato l'output relativo agli errori, -ed è anch'esso associato all'uscita del terminale. Lo standard POSIX.1 -provvede tre costanti simboliche, definite nell'header \file{unistd.h}, al -posto di questi valori numerici: +processo viene lanciato dalla shell con almeno tre file aperti. Questi, per +quanto appena 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 al cosiddetto \textit{standard input}; è cioè +il file da cui il processo si aspetta di ricevere i dati in ingresso. Il +secondo file è il cosiddetto \textit{standard output}, cioè quello su cui ci +si aspetta debbano essere inviati i dati in uscita. Il terzo è lo +\textit{standard error}, su cui viene inviata l'uscita relativa agli errori. +Nel caso della shell tutti questi file sono associati al terminale di +controllo, e corrispondono quindi alla lettura della tastiera per l'ingresso e +alla scrittura sul terminale per l'uscita. Lo standard POSIX.1 provvede, al +posto dei valori numerici, tre costanti simboliche, definite in +tab.~\ref{tab:file_std_files}. + \begin{table}[htb] \centering \footnotesize @@ -153,11 +155,11 @@ posto di questi valori numerici: \label{tab:file_std_files} \end{table} -In tab.~\ref{tab:file_std_files} si è utilizzata questa situazione come -esempio, facendo riferimento ad un programma in cui lo \textit{standard input} -è associato ad un file mentre lo \textit{standard output} e lo -\textit{standard error} sono entrambi associati ad un altro file (e quindi -utilizzano lo stesso inode\index{inode}). +In fig.~\ref{fig:file_proc_file} si è rappresentata una situazione diversa, +facendo riferimento ad un programma in cui lo \textit{standard input} è +associato ad un file mentre lo \textit{standard output} e lo \textit{standard + error} sono entrambi associati ad un altro file (e quindi utilizzano lo +stesso inode\index{inode}). Nelle vecchie versioni di Unix (ed anche in Linux fino al kernel 2.0.x) il numero di file aperti era anche soggetto ad un limite massimo dato dalle @@ -175,20 +177,18 @@ sez.~\ref{sec:sys_limits}). 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. - -La gran parte delle operazioni sui file si effettua attraverso queste cinque -funzioni, esse vengono chiamate anche funzioni di I/O non bufferizzato dato -che effettuano le operazioni di lettura e scrittura usando direttamente le -system call del kernel. +chiudere un file. La gran parte delle operazioni sui file si effettua +attraverso queste cinque funzioni, esse vengono chiamate anche funzioni di I/O +non bufferizzato dato che effettuano le operazioni di lettura e scrittura +usando direttamente le system call del kernel. \subsection{La funzione \func{open}} \label{sec:file_open} La funzione \funcd{open} è la funzione fondamentale per accedere ai file, ed è -quella che crea l'associazione fra un pathname ed un file descriptor, il suo -prototipo è: +quella che crea l'associazione fra un \itindex{pathname}\textit{pathname} ed +un file descriptor, il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/stat.h} @@ -217,9 +217,9 @@ prototipo dispositivo che non esiste. \item[\errcode{ETXTBSY}] si è cercato di accedere in scrittura all'immagine di un programma in esecuzione. - \item[\errcode{ELOOP}] si sono incontrati troppi link simbolici nel risolvere - pathname o si è indicato \const{O\_NOFOLLOW} e \param{pathname} è un link - simbolico. + \item[\errcode{ELOOP}] si sono incontrati troppi link simbolici nel + risolvere il \textit{pathname} o si è indicato \const{O\_NOFOLLOW} e + \param{pathname} è un link simbolico. \end{errlist} ed inoltre \errval{EACCES}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{EROFS}, \errval{EFAULT}, \errval{ENOSPC}, \errval{ENOMEM}, @@ -227,8 +227,9 @@ prototipo \end{functions} La funzione apre il file, usando il primo file descriptor libero, e crea -l'opportuna voce (cioè la struttura \struct{file}) nella file table. Viene -usato sempre il file descriptor con il valore più basso. +l'opportuna voce (cioè la struttura \struct{file}) nella \textit{file table}. +Viene sempre restituito come valore di ritorno il file descriptor con il +valore più basso disponibile. \begin{table}[!htb] \centering @@ -238,72 +239,104 @@ usato sempre il file descriptor con il valore pi \textbf{Flag} & \textbf{Descrizione} \\ \hline \hline % modalità di accesso al file - \const{O\_RDONLY} & apre il file in sola lettura. \\ - \const{O\_WRONLY} & apre il file in sola scrittura. \\ - \const{O\_RDWR} & apre il file in lettura/scrittura. \\ + \const{O\_RDONLY} & apre il file in sola lettura, le \acr{glibc} + definiscono anche \const{O\_READ} come sinonimo. \\ + \const{O\_WRONLY} & apre il file in sola scrittura, le \acr{glibc} + definiscono anche \const{O\_WRITE} come sinonimo. \\ + \const{O\_RDWR} & apre il file sia in lettura che in scrittura. \\ \hline % modalità di apertura del file \hline \const{O\_CREAT} & se il file non esiste verrà creato, con le regole di - titolarità del file viste in sez.~\ref{sec:file_ownership}. L'argomento - \param{mode} deve essere specificato. \\ - \const{O\_EXCL} & usato in congiunzione con \const{O\_CREAT} fa sì che - l'esistenza del file diventi un errore\protect\footnotemark\ che fa fallire - \func{open} con \errcode{EEXIST}. \\ - \const{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 (l'opzione ha senso - solo per le fifo, torneremo questo in sez.~\ref{sec:ipc_named_pipe}). \\ - \const{O\_NOCTTY} & se \param{pathname} si riferisce ad un dispositivo di - terminale, questo non diventerà il terminale di controllo, anche se il - processo non ne ha ancora uno (si veda sez.~\ref{sec:sess_ctrl_term}). \\ + titolarità del file viste in + sez.~\ref{sec:file_ownership}. Con questa opzione + l'argomento \param{mode} deve essere specificato. \\ + \const{O\_EXCL} & usato in congiunzione con \const{O\_CREAT} fa sì che + la precedente esistenza del file diventi un + errore\protect\footnotemark\ che fa fallire + \func{open} con \errcode{EEXIST}. \\ + \const{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 (l'opzione ha senso solo per le fifo, + torneremo questo in sez.~\ref{sec:ipc_named_pipe}). \\ + \const{O\_NOCTTY}& se \param{pathname} si riferisce ad un dispositivo di + terminale, questo non diventerà il terminale di + controllo, anche se il processo non ne ha ancora uno + (si veda sez.~\ref{sec:sess_ctrl_term}). \\ \const{O\_SHLOCK} & opzione di BSD, acquisisce uno shared lock (vedi - sez.~\ref{sec:file_locking}) sul file. Non è disponibile in Linux. \\ + sez.~\ref{sec:file_locking}) sul file. Non è + disponibile in Linux. \\ \const{O\_EXLOCK} & opzione di BSD, acquisisce uno lock esclusivo (vedi - sez.~\ref{sec:file_locking}) sul file. Non è disponibile in Linux. \\ - \const{O\_TRUNC} & se il file esiste ed è un file di dati e la modalità di - apertura consente la scrittura, allora la sua lunghezza verrà troncata a - zero. Se il file è un terminale o una fifo il flag verrà ignorato, negli - altri casi il comportamento non è specificato. \\ - \const{O\_NOFOLLOW} & se \param{pathname} è un link simbolico la chiamata - 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. \\ - \const{O\_DIRECTORY} & se \param{pathname} non è una directory la chiamata - fallisce. Questo flag è specifico di Linux ed è stato introdotto con il - 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}. \\ - \const{O\_LARGEFILE} & nel caso di sistemi a 32 bit che supportano file di - grandi dimensioni consente di aprire file le cui dimensioni non possono - essere rappresentate da numeri a 31 bit. \\ + sez.~\ref{sec:file_locking}) sul file. Non è + disponibile in Linux. \\ + \const{O\_TRUNC} & se il file esiste ed è un file di dati e la modalità di + apertura consente la scrittura, allora la sua + lunghezza verrà troncata a zero. Se il file è un + terminale o una fifo il flag verrà ignorato, negli + altri casi il comportamento non è specificato. \\ + \const{O\_NOFOLLOW}&se \param{pathname} è un link simbolico la chiamata + 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. \\ + \const{O\_DIRECTORY}& se \param{pathname} non è una directory la chiamata + fallisce. Questo flag è specifico di Linux ed è stato + introdotto con il 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}. \\ + \const{O\_LARGEFILE}& nel caso di sistemi a 32 bit che supportano file di + grandi dimensioni consente di aprire file le cui + dimensioni non possono essere rappresentate da numeri + a 31 bit. \\ \hline \hline % modalità di operazione col file \const{O\_APPEND} & il file viene aperto in append mode. Prima di ciascuna - 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\\ - \const{O\_NONBLOCK} & il file viene aperto in modalità non bloccante per - le operazioni di I/O (che tratteremo in sez.~\ref{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. \\ + scrittura la posizione corrente viene sempre impostata + alla fine del file. Con NFS si può avere una + corruzione del file se più di un processo scrive allo + stesso tempo.\footnotemark\\ + \const{O\_NONBLOCK}&il file viene aperto in modalità non bloccante per + le operazioni di I/O (che tratteremo in + sez.~\ref{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. \\ \const{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di - \const{O\_NONBLOCK}.\\ - \const{O\_ASYNC} & apre il file per l'I/O in modalità - asincrona (vedi sez.~\ref{sec:file_asyncronous_io}). Quando è impostato - viene generato il segnale \const{SIGIO} tutte le volte che sono disponibili - dati in input sul file. \\ - \const{O\_SYNC} & apre il file per l'input/output sincrono: ogni - \func{write} bloccherà fino al completamento della scrittura di tutti i - dati sull'hardware sottostante.\\ - \const{O\_FSYNC} & sinonimo di \const{O\_SYNC}. \\ - \const{O\_NOATIME} & blocca l'aggiornamento dei tempi di accesso dei - file (vedi sez.~\ref{sec:file_file_times}). Per molti filesystem questa - funzionalità non è disponibile per il singolo file ma come opzione in fase - di montaggio.\\ + \const{O\_NONBLOCK}.\\ + \const{O\_ASYNC} & apre il file per l'I/O in modalità asincrona (vedi + sez.~\ref{sec:file_asyncronous_io}). Quando è + impostato viene generato il segnale \const{SIGIO} + tutte le volte che sono disponibili dati in input + sul file. \\ + \const{O\_SYNC} & apre il file per l'input/output sincrono: ogni + \func{write} bloccherà fino al completamento della + scrittura di tutti i dati sull'hardware sottostante.\\ + \const{O\_FSYNC} & sinonimo di \const{O\_SYNC}, usato da BSD. \\ + \const{O\_DSYNC} & richiede una variante di I/O sincorno definita nello + standard POSIX; definita a partire dal kernel 2.1.130 + come sinonimo di \const{O\_SYNC}. \\ + \const{O\_RSYNC} & richiede una variante di I/O sincorno definita nello + standard POSIX; definita a partire dal kernel 2.1.130 + come sinonimo di \const{O\_SYNC}. \\ + \const{O\_NOATIME}& blocca l'aggiornamento dei tempi di accesso dei + file (vedi sez.~\ref{sec:file_file_times}). Per molti + filesystem questa funzionalità non è disponibile per + il singolo file ma come opzione generale da + specificare in fase di montaggio.\\ + \const{O\_DIRECT} & esegue l'I/O direttamente dai buffer in user space, ed + in maniera sincrona, in modo da scavalcare i + meccanismi di caching del kernel. In gebere questo + peggiora le prestazioni tranne per casi speciali in + cui sono le applicazioni\footnotemark a gestire il + caching. Per i kernel della serie 2.4 si deve + garantire che i buffer in user space siano allineati + alle dimensioni dei blocchi del filesystem; per il + kernel 2.6 basta che siano allineati a multipli di 512 + byte.\\ \hline \end{tabular} \caption{Valori e significato dei vari bit del \textit{file status flag}.} @@ -312,10 +345,10 @@ usato sempre il file descriptor con il valore pi \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 - \textsl{file di lock}\index{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 (vedi sez.~\ref{sec:ipc_file_lock}).} + \textsl{file di lock}\index{file!di lock} possono incorrere in una + \textit{race condition}\itindex{race~condition}. Si consiglia come + alternativa di usare un file con un nome univoco e la funzione \func{link} + per verificarne l'esistenza (vedi sez.~\ref{sec:ipc_file_lock}).} \footnotetext[3]{\textit{Denial of Service}\index{DoS}, si chiamano così attacchi miranti ad impedire un servizio causando una qualche forma di @@ -331,16 +364,26 @@ usato sempre il file descriptor con il valore pi un'ambiguità, dato che come vedremo in sez.~\ref{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 +\footnotetext[6]{l'opzione è stata introdotta dalla SGI in IRIX, e serve + sostanzialmente a permettere ad alcuni programmi (in genere database) la + gestione diretta della bufferizzazione dell'I/O in quanto essi sono in grado + di ottimizzarla al meglio per le loro prestazioni; l'opzione è presente + anche in FreeBSD, senza limiti di allineamento dei buffer. In Linux è stata + introdotta con il kernel 2.4.10, le versioni precedenti la ignorano.} + + +Questa caratteristica permette di prevedere qual è il valore del file descriptor che si otterrà al ritorno di \func{open}, e viene talvolta usata da alcune applicazioni per sostituire i file corrispondenti ai file standard visti in sez.~\ref{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à cioè il file descriptor 0). Il nuovo file descriptor non è -condiviso con nessun altro processo (torneremo sulla condivisione dei file, in -genere accessibile dopo una \func{fork}, in sez.~\ref{sec:file_sharing}) ed è -impostato per restare aperto attraverso una \func{exec} (come accennato in -sez.~\ref{sec:proc_exec}); l'offset è impostato all'inizio del file. +input (avrà cioè il file descriptor 0). + +Il nuovo file descriptor non è condiviso con nessun altro processo (torneremo +sulla condivisione dei file, in genere accessibile dopo una \func{fork}, in +sez.~\ref{sec:file_sharing}) ed è impostato per restare aperto attraverso una +\func{exec} (come accennato in sez.~\ref{sec:proc_exec}); l'offset è impostato +all'inizio del file. L'argomento \param{mode} indica i permessi con cui il file viene creato; i valori possibili sono gli stessi già visti in sez.~\ref{sec:file_perm_overview} @@ -500,8 +543,8 @@ Si tenga presente inoltre che usare \const{SEEK\_END} non assicura affatto che la 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 impostata in precedenza -(questa è una potenziale sorgente di \textit{race condition} -\index{race condition}, vedi sez.~\ref{sec:file_atomic}). +(questa è una potenziale sorgente di \itindex{race~condition}\textit{race + condition}, vedi sez.~\ref{sec:file_atomic}). Non tutti i file supportano la capacità di eseguire una \func{lseek}, in questo caso la funzione ritorna l'errore \errcode{EPIPE}. Questo, oltre che per @@ -570,19 +613,21 @@ con un numero di byte inferiore a quelli richiesti. Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket\index{socket}, come vedremo in sez.~\ref{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 \errcode{EINTR} e -\errcode{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 intraprendere è quella di rieseguire la funzione. -Torneremo in dettaglio sull'argomento in sez.~\ref{sec:sig_gen_beha}. La -seconda si verifica quando il file è in modalità non bloccante (vedi -sez.~\ref{sec:file_noblocking}) e non ci sono dati in ingresso: la funzione -allora ritorna immediatamente con un errore \errcode{EAGAIN}\footnote{BSD usa - per questo errore la costante \errcode{EWOULDBLOCK}, in Linux, con le - \acr{glibc}, questa è sinonima di \errcode{EAGAIN}.} che indica soltanto che -occorrerà provare a ripetere la lettura. +restituiscono sempre i dati ad un singolo blocco alla volta, o come le linee +seriali, che restituiscono solo i dati ricevuti fino al momento della lettura. + +Infine anche le due condizioni segnalate dagli errori \errcode{EINTR} ed +\errcode{EAGAIN} non sono propriamente degli 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 intraprendere è quella di +rieseguire la funzione. Torneremo in dettaglio sull'argomento in +sez.~\ref{sec:sig_gen_beha}. La seconda si verifica quando il file è aperto +in modalità non bloccante (vedi sez.~\ref{sec:file_noblocking}) e non ci sono +dati in ingresso: la funzione allora ritorna immediatamente con un errore +\errcode{EAGAIN}\footnote{BSD usa per questo errore la costante + \errcode{EWOULDBLOCK}, in Linux, con le \acr{glibc}, questa è sinonima di + \errcode{EAGAIN}.} che indica soltanto che non essendoci al momento dati +disponibili occorre provare a ripetere la lettura in un secondo tempo. La funzione \func{read} è una delle system call fondamentali, esistenti fin dagli albori di Unix, ma nella seconda versione delle \textit{Single Unix @@ -603,24 +648,35 @@ posizione \param{offset}, nel buffer \param{buf}. 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: + +La funzione prende esattamente gli stessi argomenti di \func{read} con lo +stesso significato, a cui si aggiunge l'argomento \func{offset} che indica una +posizione sul file. Indetico è il comportamento ed il valore di ritorno. La +funzione serve quando si vogliono leggere dati dal file senza modificare la +posizione corrente. + +L'uso di \func{pread} è equivalente all'esecuzione di una \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 sez.~\ref{sec:file_sharing}). Il valore di +\param{offset} fa sempre riferimento all'inizio del file. + +La funzione \func{pread} è disponibile anche in Linux, però diventa +accessibile solo attivando il supporto delle estensioni previste dalle +\textit{Single Unix Specification} con la definizione della macro: \begin{verbatim} #define _XOPEN_SOURCE 500 \end{verbatim} +e si ricordi di definire questa macro prima dell'inclusione del file di +dichiarazioni \file{unistd.h}. -Questa funzione serve quando si vogliono leggere dati dal file senza -modificare la posizione corrente. È equivalente all'esecuzione di una -\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 sez.~\ref{sec:file_sharing}). Il valore di -\param{offset} fa sempre riferimento all'inizio del file. \subsection{La funzione \func{write}} \label{sec:file_write} -Una volta che un file è stato aperto (con il permesso in scrittura) su può +Una volta che un file è stato aperto (con il permesso in scrittura) si può scrivere su di esso utilizzando la funzione \funcd{write}, il cui prototipo è: \begin{prototype}{unistd.h}{ssize\_t write(int fd, void * buf, size\_t count)} @@ -788,13 +844,13 @@ sez.~\ref{sec:file_locking}). 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 sez.~\ref{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. +fine del file e poi scrivere può condurre ad una +\itindex{race~condition}\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 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à @@ -808,9 +864,9 @@ Un altro caso tipico in cui creare un \textsl{file di lock}\index{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\index{race condition} da -parte di un altro processo che crea lo stesso file fra il controllo e la -creazione. +di nuovo avremmo la possibilità di una \textit{race + condition}\itindex{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 per \func{open} i due flag \const{O\_CREAT} e \const{O\_EXCL}. In questo modo l'operazione di controllo @@ -936,7 +992,7 @@ sull'altro (dato che quello che viene modificato 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}\index{close-on-exec} (vedi +di \func{dup} il flag di \textit{close-on-exec}\itindex{close-on-exec} (vedi sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}) viene sempre cancellato nella copia. @@ -951,7 +1007,7 @@ disponibile. Dato che questa è l'operazione più comune, è prevista una diversa versione della funzione, \funcd{dup2}, che permette di specificare esplicitamente -qual'è il valore di file descriptor che si vuole avere come duplicato; il suo +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)} @@ -972,9 +1028,9 @@ sar allo stesso valore per il file descriptor). La duplicazione dei file descriptor può essere effettuata anche usando la -funzione di controllo dei file \func{fnctl} (che esamineremo in +funzione di controllo dei file \func{fcntl} (che esamineremo in sez.~\ref{sec:file_fcntl}) con il parametro \const{F\_DUPFD}. L'operazione ha -la sintassi \code{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0 come valore per +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\footnote{a parte la sintassi ed i @@ -1036,9 +1092,9 @@ per \var{cmd} massimo numero di descrittori consentito. \item[\const{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}\index{close-on-exec}, identificato dalla costante + \textit{close-on-exec}\itindex{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}). Ritorna un + esecuzione di una \func{exec} (vedi sez.~\ref{sec:proc_exec}). Ritorna un valore nullo in caso di successo e -1 in caso di errore. \item[\const{F\_GETFD}] ritorna il valore del \textit{file descriptor flag} di \param{fd} o -1 in caso di errore; se \const{FD\_CLOEXEC} è impostato i file @@ -1139,7 +1195,6 @@ sez.~\ref{sec:file_asyncronous_operation} mentre quelle relative al \textit{file locking}\index{file!locking} saranno esaminate in sez.~\ref{sec:file_locking}). - 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 @@ -1171,8 +1226,8 @@ 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 è: \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 ed il terzo parametro (usualmente di tipo + Manipola il dispositivo sottostante, usando l'argomento \param{request} per + specificare l'operazione richiesta ed il terzo argomento (usualmente di tipo \param{char * argp} o \param{int argp}) per il trasferimento dell'informazione necessaria. @@ -1230,8 +1285,10 @@ effettuata attraverso \func{ioctl} in quasi tutte le implementazioni di Unix), qui riportiamo solo i valori di alcuni comandi che sono definiti per ogni file: \begin{basedescript}{\desclabelwidth{2.0cm}} -\item[\const{FIOCLEX}] Imposta il bit di \textit{close on exec}. -\item[\const{FIONCLEX}] Cancella il bit di \textit{close on exec}. +\item[\const{FIOCLEX}] Imposta il flag di + \textit{close-on-exec}\itindex{close-on-exec}. +\item[\const{FIONCLEX}] Cancella il flag di + \textit{close-on-exec}\itindex{close-on-exec}. \item[\const{FIOASYNC}] Abilita l'I/O asincrono. \item[\const{FIONBIO}] Abilita l'I/O in modalità non bloccante. \end{basedescript}