From: Simone Piccardi Date: Wed, 9 Mar 2005 11:44:39 +0000 (+0000) Subject: Correzioni varie ed aggiuno O_DIRECT X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=419f06363260b291c2242aec48ec450f44ba2006 Correzioni varie ed aggiuno O_DIRECT --- diff --git a/fileunix.tex b/fileunix.tex index 3e9560c..c0305b7 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -91,6 +91,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 +103,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,22 +115,22 @@ 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à. +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 (nel caso -della shell, è associato all'input del terminale, cioè alla lettura della -tastiera). Il secondo file è il cosiddetto \textit{standard output}, cioè -quello su cui ci si aspetta debbano essere inviati i dati in uscita (sempre -nel caso della shell, è associato all'output del terminale, cioè alla -scrittura sullo schermo). Il terzo è lo \textit{standard error}, su cui viene -inviata l'uscita relativa agli errori, ed è anch'esso associato al terminale. -Lo standard POSIX.1 provvede, al posto di questi valori numerici, tre costanti -simboliche, definite in tab.~\ref{tab:file_std_files}. +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 @@ -175,12 +175,10 @@ 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}} @@ -229,7 +227,8 @@ prototipo La funzione apre il file, usando il primo file descriptor libero, e crea l'opportuna voce (cioè la struttura \struct{file}) nella \textit{file table}. -Viene usato sempre il file descriptor con il valore più basso. +Viene sempre restituito come valore di ritorno il file descriptor con il +valore più basso disponibile. \begin{table}[!htb] \centering @@ -239,17 +238,19 @@ Viene 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. \\ + 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 - l'esistenza del file diventi un + 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 @@ -292,9 +293,9 @@ Viene usato sempre il file descriptor con il valore pi \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\\ + 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 @@ -313,11 +314,28 @@ Viene usato sempre il file descriptor con il valore pi \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\_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 in fase di montaggio.\\ + 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}.} @@ -345,16 +363,26 @@ Viene 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.} +\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} @@ -584,19 +612,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 @@ -617,24 +647,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)}