X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileio.tex;h=053fd25308cef6833942ac4596d5e25beec7e85a;hp=7b326993c04038bb18fab5dea3c210530d45183e;hb=565dcb356f097ee32f889ee9120ad165d431500e;hpb=5a15091e17c25f37a6f53751ccde91f504006773 diff --git a/fileio.tex b/fileio.tex index 7b32699..053fd25 100644 --- a/fileio.tex +++ b/fileio.tex @@ -1083,20 +1083,23 @@ il cui prototipo è: per \param{size} o si è usato \const{O\_DIRECT} ed il buffer non è allineato. \item[\errval{EIO}] si è tentata la lettura dal terminale di controllo - essendo in background (vedi sez.~\ref{sec:term_io_design}). + essendo in background ignorando o bloccando \const{SIGTTIN} (vedi + sez.~\ref{sec:term_io_design}) o per errori di basso livello sul supporto. \end{errlist} ed inoltre \errval{EBADF}, \errval{EFAULT} e \errval{EISDIR}, nel loro significato generico.} \end{funcproto} La funzione tenta di leggere \param{count} byte dal file \param{fd} a partire -dalla posizione corrente, scrivendoli nel buffer \param{buf}. Dopo la lettura -la posizione sul file è spostata automaticamente in avanti del numero di byte -letti. Se \param{count} è zero la funzione restituisce zero senza nessun altro -risultato. Inoltre che non è detto che la funzione \func{read} restituisca il -numero di byte richiesto, ci sono infatti varie ragioni per cui la funzione -può restituire un numero di byte inferiore: questo è un comportamento normale, -e non un errore, che bisogna sempre tenere presente. +dalla posizione corrente, scrivendoli nel buffer \param{buf}.\footnote{fino ad + un massimo di \const{0x7ffff000} byte, indipendentemente che l'architettura + sia a 32 o 64 bit.} Dopo la lettura la posizione sul file è spostata +automaticamente in avanti del numero di byte letti. Se \param{count} è zero la +funzione restituisce zero senza nessun altro risultato. Inoltre che non è +detto che la funzione \func{read} restituisca il numero di byte richiesto, ci +sono infatti varie ragioni per cui la funzione può restituire un numero di +byte inferiore: questo è un comportamento normale, e non un errore, che +bisogna sempre tenere presente. 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 @@ -1122,7 +1125,7 @@ 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, o come le linee seriali, che restituiscono solo i dati ricevuti fino al momento della lettura, o i terminali, per i quali si -applicano inoltre ulteriori condizioni che approfondiremo in +applicano anche ulteriori condizioni che approfondiremo in sez.~\ref{sec:sess_terminal_io}. Infine anche le due condizioni segnalate dagli errori \errcode{EINTR} ed @@ -1165,26 +1168,29 @@ funzione di sistema, \funcd{pread}, il cui prototipo è: La funzione prende esattamente gli stessi argomenti di \func{read} con lo stesso significato, a cui si aggiunge l'argomento \param{offset} che indica -una posizione sul file. Identico è 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 +una posizione sul file a partire dalla quale verranno i \param{count} +byte. Identico è il comportamento ed il valore di ritorno, ma la posizione +corrente sul file resterà invariata. Il valore di \param{offset} fa sempre +riferimento all'inizio del file. + +L'uso di \func{pread} è equivalente all'esecuzione di una \func{lseek} alla +posizione indicata da \param{offset} seguita da una \func{read}, seguita da +un'altra \func{lseek} che riporti al valore iniziale della 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_shared_access}). Il valore di \param{offset} fa -sempre riferimento all'inizio del file. +(vedi sez.~\ref{sec:file_shared_access}) ed è particolarmente utile in caso di +programmazione \textit{multi-thread} (vedi sez.~\ref{cha:threads}) quando +all'interno di un processo si vuole che le operazioni di un \textit{thread} +non possano essere influenzata da eventuali variazioni della posizione sul +file effettuate da altri \textit{thread}. 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{Example} -#define _XOPEN_SOURCE 500 -\end{Example} -e si ricordi di definire questa macro prima dell'inclusione del file di -dichiarazioni \headfile{unistd.h}. - +\textit{Single Unix Specification} con un valore della macro +\macro{\_XOPEN\_SOURCE} maggiore o uguale a 500 o a partire dalla \acr{glibc} +2.12 con un valore dalla macro \macro{\_POSIX\_C\_SOURCE} maggiore o uguale al +valore \val{200809L}. Si ricordi di definire queste macro prima +dell'inclusione del file di dichiarazione \headfile{unistd.h}. \subsection{Le funzioni per la scrittura di un file} @@ -1245,9 +1251,10 @@ Per i file ordinari il numero di byte scritti è sempre uguale a quello indicato da \param{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 un'analoga \funcd{pwrite} -per scrivere alla posizione indicata senza modificare la posizione corrente -nel file, il suo prototipo è: +Anche per \func{write} lo standard Unix98 (ed i successivi POSIX.1-2001 e +POSIX.1-2008) definiscono un'analoga \funcd{pwrite} per scrivere alla +posizione indicata senza modificare la posizione corrente nel file, il suo +prototipo è: \begin{funcproto}{ \fhead{unistd.h} @@ -1260,7 +1267,11 @@ nel file, il suo prototipo è: \func{write} e \func{lseek}.} \end{funcproto} -\noindent e per essa valgono le stesse considerazioni fatte per \func{pread}. +\noindent per questa funzione valgono le stesse considerazioni fatte per +\func{pread}, a cui si aggiunge il fatto che su Linux, a differenza di quanto +previsto dallo standard POSIX che richiederebbe di ignorarlo, se si è aperto +il file con \const{O\_APPEND} i dati saranno comunque scritti in coda al file, +ignorando il valore di \param{offset}. \section{Caratteristiche avanzate} @@ -1285,14 +1296,14 @@ diversi. \begin{figure}[!htb] \centering - \includegraphics[width=12cm]{img/filemultacc} + \includegraphics[width=11cm]{img/filemultacc} \caption{Schema dell'accesso allo stesso file da parte di due processi diversi} \label{fig:file_mult_acc} \end{figure} -Il primo caso è quello in cui due processi diversi aprono lo stesso file su -disco; sulla base di quanto visto in sez.~\ref{sec:file_fd} avremo una +Il primo caso è quello in cui due processi indipendenti aprono lo stesso file +su disco; sulla base di quanto visto in sez.~\ref{sec:file_fd} avremo una situazione come quella illustrata in fig.~\ref{fig:file_mult_acc}: ciascun processo avrà una sua voce nella \textit{file table} referenziata da un diverso file descriptor nella sua \kstruct{file\_struct}. Entrambe le voci @@ -1304,7 +1315,7 @@ la sua modalità di accesso e versioni proprie di tutte le proprietà che vengono mantenute nella sua voce della \textit{file table}. Questo ha conseguenze specifiche sugli effetti della possibile azione simultanea sullo stesso file, in particolare occorre tenere presente che: -\begin{itemize} +\begin{itemize*} \item ciascun processo può scrivere indipendentemente, dopo ciascuna \func{write} la posizione corrente sarà cambiata solo nel processo scrivente. Se la scrittura eccede la dimensione corrente del file questo @@ -1313,23 +1324,25 @@ stesso file, in particolare occorre tenere presente che: \item se un file è in modalità \const{O\_APPEND} tutte le volte che viene effettuata una scrittura la posizione corrente viene prima impostata alla dimensione corrente del file letta dalla struttura \kstruct{inode}. Dopo la - scrittura il file viene automaticamente esteso. + scrittura il file viene automaticamente esteso. Questa operazione avviene + atomicamente, ogni altro processo che usi \const{O\_APPEND} vedrà la + dimensione estesa e continuerà a scrivere in coda al file. \item l'effetto di \func{lseek} è solo quello di cambiare il campo \var{f\_pos} nella struttura \kstruct{file} della \textit{file table}, non c'è nessuna operazione sul file su disco. Quando la si usa per porsi alla - fine del file la posizione viene impostata leggendo la dimensione corrente - dalla struttura \kstruct{inode}. -\end{itemize} + fine del file la posizione viene impostata leggendo la attuale dimensione + corrente dalla struttura \kstruct{inode}. +\end{itemize*} \begin{figure}[!htb] \centering - \includegraphics[width=12cm]{img/fileshar} + \includegraphics[width=11cm]{img/fileshar} \caption{Schema dell'accesso ai file da parte di un processo figlio} \label{fig:file_acc_child} \end{figure} Il secondo caso è quello in cui due file descriptor di due processi diversi -puntino alla stessa voce nella \textit{file table}. Questo è ad esempio il +puntano alla stessa voce nella \textit{file table}. Questo è ad esempio il caso dei file aperti che vengono ereditati dal processo figlio all'esecuzione di una \func{fork} (si ricordi quanto detto in sez.~\ref{sec:proc_fork}). La situazione è illustrata in fig.~\ref{fig:file_acc_child}; dato che il processo @@ -1363,11 +1376,11 @@ caso di condivisione della stessa voce della \textit{file table}. Si tenga presente dunque che in un sistema unix-like è sempre possibile per più processi accedere in contemporanea allo stesso file e che non esistono, a differenza di altri sistemi operativi, dei meccanismi di blocco o di -restrizione dell'accesso impliciti se più processi vogliono accedere allo +restrizione dell'accesso impliciti quando più processi vogliono accedere allo stesso file. Questo significa che le operazioni di lettura e scrittura vengono -sempre fatte da ogni processo in maniera autonoma, utilizzando una posizione -corrente nel file che normalmente (a meno di non trovarsi nella situazione di -fig.~\ref{fig:file_acc_child}) è locale a ciascuno di essi. +sempre fatte da ogni processo in maniera indipendente, utilizzando una +posizione corrente nel file che normalmente, a meno di non trovarsi nella +situazione di fig.~\ref{fig:file_acc_child}, è locale a ciascuno di essi. Dal punto di vista della lettura dei dati questo comporta la possibilità di poter leggere dati non coerenti in caso di scrittura contemporanea da parte di @@ -1382,12 +1395,13 @@ esamineremo in 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}; -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 primo processo, avrà una posizione corrente che aveva -impostato con la \func{lseek} che non corrisponde più alla fine del file, e la -sua successiva \func{write} sovrascriverà i dati del secondo processo. +fine del file con \func{lseek} e poi scrivere con \func{write} 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 primo processo, +avrà una posizione corrente che aveva impostato con \func{lseek} che non +corrisponde più alla fine del file, e la sua successiva \func{write} +sovrascriverà i dati del secondo processo. Il problema deriva dal fatto che usare due \textit{system call} in successione non è mai un'operazione atomica dato che il kernel può interrompere @@ -1406,9 +1420,9 @@ realizza un'operazione atomica. Abbiamo già visto in sez.~\ref{sec:file_shared_access} 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 di sistema \funcd{dup}, -il cui prototipo è: +comportamento analogo all'interno di uno stesso processo con la cosiddetta +\textit{duplicazione} di un file descriptor. Per far questo si usa la funzione +di sistema \funcd{dup}, il cui prototipo è: \begin{funcproto}{ \fhead{unistd.h} @@ -1421,7 +1435,7 @@ il cui prototipo è: \begin{errlist} \item[\errcode{EBADF}] \param{oldfd} non è un file aperto. \item[\errcode{EMFILE}] si è raggiunto il numero massimo consentito di file - descriptor aperti. + descriptor aperti (vedi sez.~\ref{sec:sys_resource_limit}). \end{errlist} } \end{funcproto} @@ -1437,7 +1451,7 @@ questo motivo si dice che il nuovo file descriptor è ``\textsl{duplicato}'', da cui il nome della funzione. \begin{figure}[!htb] - \centering \includegraphics[width=12cm]{img/filedup} + \centering \includegraphics[width=11cm]{img/filedup} \caption{Schema dell'accesso ai file duplicati} \label{fig:file_dup} \end{figure} @@ -1469,8 +1483,8 @@ standard che si vuole redirigere e poi aprire direttamente con \func{open} il file vi si vuole far corrispondere, invece di duplicare un file descriptor che si è già aperto. La risposta sta nel fatto che il file che si vuole redirigere non è detto sia un file regolare, ma potrebbe essere, come accennato, anche -una \textit{fifo} o un socket, oppure potrebbe essere un file associato ad un file -descriptor che si è ereditato già aperto (ad esempio attraverso un'altra +una \textit{fifo} o un socket, oppure potrebbe essere un file associato ad un +file descriptor che si è ereditato già aperto (ad esempio attraverso una \func{exec}) da un processo antenato del padre, del quale non si conosce il nome. Operando direttamente con i file descriptor \func{dup} consente di ignorare le origini del file descriptor che si duplica e funziona in maniera @@ -4483,7 +4497,7 @@ con uno dei valori \const{FSETLOCKING\_INTERNAL} o %%% TeX-master: "gapil" %%% End: -% LocalWords: nell' du vm Documentation Urlich Drepper futimesat times +% LocalWords: nell' du vm Documentation Urlich Drepper futimesat times l'I % LocalWords: futimens fs Tread all'I ll TMPFILE EDQUOT extN Minix UDF XFS % LocalWords: shmem Btrfs ubifs tmpfile fchmod fchown fsetxattr fchdir PF -% LocalWords: fstatfs sull' +% LocalWords: fstatfs sull' SIGTTIN EDESTADDRREQ datagram connect