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
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
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}
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}
\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}
\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
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
\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
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
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
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}
\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}
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}
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
%%% 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