X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileio.tex;h=7b326993c04038bb18fab5dea3c210530d45183e;hp=dc5bdfa2d45b291a0e6ff3304af097350b9a5f30;hb=5a15091e17c25f37a6f53751ccde91f504006773;hpb=2f4922efce6bcac7c6ff10a4c5af7bebccb1f151 diff --git a/fileio.tex b/fileio.tex index dc5bdfa..7b32699 100644 --- a/fileio.tex +++ b/fileio.tex @@ -537,24 +537,23 @@ univoco con l'uso delle funzioni di sez.~\ref{sec:file_temp_file}. Una volta aperto il file vi si potrà leggere o scrivere a seconda che siano utilizzati \const{O\_RDWR} o \const{O\_WRONLY}, mentre l'uso di \func{O\_RDONLY} non è consentito, non avendo molto senso ottenere un file -descriptor da cui non si potrà comunque mai leggere nulla. L'unico altro flag -che può essere utilizzato insieme a \const{O\_TMPFILE} è \const{O\_EXCL}, che -in questo caso assume però un significato diverso da quello ordinario, dato -che in questo caso non avrebbe senso fallire se il file non esiste, dato che -questo è sempre vero. - -L'uso di \const{O\_EXCL} attiene all'altro possibile impiego di -\const{O\_TMPFILE} oltre a quello della creazione sicura di un file temporaneo -come sostituto di \func{tmpfile}: la possibilità di creare un eventuale -contenuto iniziale ed impostare permessi, proprietario e attributi estesi con -\func{fchmod}, \func{fchown} e \func{fsetxattr} operando sul file descriptor, -senza possibilità di \textit{race condition} ed interferenze esterne, per poi -far apparire il tutto sul filesystem in un secondo tempo utilizzando -\func{linkat} sul file descriptor (torneremo su questo in -sez.~\ref{sec:file_openat}) per dargli un nome. Questa operazione però non -sarà possibile se si è usato \const{O\_EXCL}, che in questo caso viene ad -assumere il significato di escludere la possibilità di far esistere il file -anche in un secondo tempo. +descriptor su un file che nasce vuoto per cui non si potrà comunque leggere +nulla. L'unico altro flag che può essere utilizzato insieme a +\const{O\_TMPFILE} è \const{O\_EXCL}, che in questo caso assume però un +significato diverso da quello ordinario, dato che in questo caso il file +associato al file descriptor non esiste comunque. + +L'uso di \const{O\_EXCL} attiene infatti all'altro possibile impiego di +\const{O\_TMPFILE} oltre a quello citato della creazione sicura di un file +temporaneo come sostituto sicuro di \func{tmpfile}: la possibilità di creare +un contenuto iniziale per un file ed impostarne permessi, proprietario e +attributi estesi con \func{fchmod}, \func{fchown} e \func{fsetxattr}, senza +possibilità di \textit{race condition} ed interferenze esterne, per poi far +apparire il tutto sul filesystem in un secondo tempo utilizzando \func{linkat} +sul file descriptor (torneremo su questo in sez.~\ref{sec:file_openat}) per +dargli un nome. Questa operazione però non sarà possibile se si è usato +\const{O\_EXCL}, che in questo caso viene ad assumere il significato di +escludere la possibilità di far esistere il file anche in un secondo tempo. % NOTE: per O_TMPFILE vedi: http://kernelnewbies.org/Linux_3.11 % https://lwn.net/Articles/558598/ http://lwn.net/Articles/619146/ @@ -848,24 +847,32 @@ Si ricordi che quando un processo termina tutti i suoi file descriptor vengono automaticamente chiusi, molti programmi sfruttano questa caratteristica e non usano esplicitamente \func{close}. In genere comunque chiudere un file senza controllare lo stato di uscita di \func{close} un è errore; molti filesystem -infatti implementano la tecnica del cosiddetto \textit{write-behind}, per cui -una \func{write} può avere successo anche se i dati non sono stati -effettivamente scritti su disco. In questo caso un eventuale errore di I/O -avvenuto in un secondo tempo potrebbe sfuggire, mentre verrebbe riportato alla -chiusura esplicita del file. Per questo motivo non effettuare il controllo può -portare ad una perdita di dati inavvertita.\footnote{in Linux questo - comportamento è stato osservato con NFS e le quote su disco.} +infatti implementano la tecnica del cosiddetto \itindex{write-behind} +\textit{write-behind}, per cui una \func{write} può avere successo anche se i +dati non sono stati effettivamente scritti su disco. In questo caso un +eventuale errore di I/O avvenuto in un secondo tempo potrebbe sfuggire, mentre +verrebbe riportato alla chiusura esplicita del file. Per questo motivo non +effettuare il controllo può portare ad una perdita di dati +inavvertita.\footnote{in Linux questo comportamento è stato osservato con NFS + e le quote su disco.} In ogni caso una \func{close} andata a buon fine non garantisce che i dati siano stati effettivamente scritti su disco, perché il kernel può decidere di ottimizzare l'accesso a disco ritardandone la scrittura. L'uso della funzione -\func{sync} (vedi sez.~\ref{sec:file_sync}) effettua esplicitamente il -\emph{flush} dei dati, ma anche in questo caso resta l'incertezza dovuta al -comportamento dell'hardware, che a sua volta può introdurre ottimizzazioni -dell'accesso al disco che ritardano la scrittura dei dati. Da questo deriva -l'abitudine di alcuni sistemisti di ripetere tre volte il comando omonimo -prima di eseguire lo shutdown di una macchina. - +\func{sync} (vedi sez.~\ref{sec:file_sync}) effettua esplicitamente lo scarico +dei dati, ma anche in questo caso resta l'incertezza dovuta al comportamento +dell'hardware, che a sua volta può introdurre ottimizzazioni dell'accesso al +disco che ritardano la scrittura dei dati. Da questo deriva l'abitudine di +alcuni sistemisti di ripetere tre volte il comando omonimo prima di eseguire +lo shutdown di una macchina. + +Si tenga comunque presente che ripetere la chiusura in caso di fallimento non +è opportuno, una volta chiamata \func{close} il file descriptor viene comunque +rilasciato, indipendentemente dalla presenza di errori, e se la riesecuzione +non comporta teoricamente problemi (se non la sua inutilità) se fatta +all'interno di un processo singolo, nel caso si usino i \textit{thread} si +potrebbe chiudere un file descriptor aperto nel contempo da un altro +\textit{thread}. \subsection{La gestione della posizione nel file} \label{sec:file_lseek} @@ -1039,11 +1046,11 @@ riporti sempre la fine del file e \const{SEEK\_DATA} il valore di \param{offset}. Inoltre la decisione di come riportare (o di non riportare) la presenza di un -buco in un file è lasciata all'implementazione del -filesystem, dato che esistono vari motivi per cui una sezione di un file può -non contenere dati ed essere riportata come tale (ad esempio può essere stata -preallocata con \func{fallocate}, vedi sez.~\ref{sec:file_fadvise}) oltre a -quelle classiche appena esposte. Questo significa che l'uso di questi nuovi +buco in un file è lasciata all'implementazione del filesystem, dato che oltre +a quelle classiche appena esposte esistono vari motivi per cui una sezione di +un file può non contenere dati ed essere riportata come tale (ad esempio può +essere stata preallocata con \func{fallocate}, vedi +sez.~\ref{sec:file_fadvise}). Questo significa che l'uso di questi nuovi valori non garantisce la mappatura della effettiva allocazione dello spazio disco di un file, per il quale esiste una specifica operazione di controllo (vedi sez.~\ref{sec:file_fcntl_ioctl}). @@ -1166,8 +1173,8 @@ 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_shared_access}). Il valore di -\param{offset} fa sempre riferimento all'inizio del file. +(vedi sez.~\ref{sec:file_shared_access}). 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 @@ -1198,6 +1205,10 @@ prototipo è: \begin{errlist} \item[\errcode{EAGAIN}] ci si sarebbe bloccati, ma il file era aperto in modalità \const{O\_NONBLOCK}. + \item[\errcode{EDESTADDRREQ}] si è eseguita una scrittura su un socket di + tipo \textit{datagram} (vedi sez.~\ref{sec:sock_type}) senza aver prima + connesso il corrispondente con \func{connect} (vedi + sez.~\ref{sec:UDP_sendto_recvfrom}). \item[\errcode{EFBIG}] si è cercato di scrivere oltre la dimensione massima consentita dal filesystem o il limite per le dimensioni dei file del processo o su una posizione oltre il massimo consentito. @@ -1205,13 +1216,14 @@ prototipo è: potuto scrivere qualsiasi dato. \item[\errcode{EINVAL}] \param{fd} è connesso ad un oggetto che non consente la scrittura o si è usato \const{O\_DIRECT} ed il buffer non è allineato. +% \item[\errcode{EPERM}] la scrittura è proibita da un \textit{file seal}. \item[\errcode{EPIPE}] \param{fd} è connesso ad una \textit{pipe} il cui altro capo è chiuso in lettura; in questo caso viene anche generato il segnale \signal{SIGPIPE}, se questo viene gestito (o bloccato o ignorato) la funzione ritorna questo errore. \end{errlist} - ed inoltre \errval{EBADF}, \errval{EFAULT}, \errval{EIO}, \errval{EISDIR}, - \errval{ENOSPC} nel loro significato generico.} + ed inoltre \errval{EBADF}, \errval{EDQUOT}, \errval{EFAULT}, \errval{EIO}, + \errval{EISDIR}, \errval{ENOSPC} nel loro significato generico.} \end{funcproto}