X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileunix.tex;h=c2412e8139397171bae5f769e764872b4626e44c;hp=e1ca3abab354aa54b93571f9ea39a96a401b3fc3;hb=21c0479726e1e1554f5ed48c29e412637b695e74;hpb=88fefd4ca97449596a2b8689e89de5e66d9d6758 diff --git a/fileunix.tex b/fileunix.tex index e1ca3ab..c2412e8 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -15,7 +15,8 @@ ANSI C. In questa sezione faremo una breve introduzione sulla architettura su cui è basata dell'interfaccia dei \textit{file descriptor}, che, sia pure con -differenze di implementazione, è comune ad ogni implementazione di unix. +differenze nella realizzazione pratica, resta sostanzialmente la stessa in +ogni implementazione di unix. \subsection{L'architettura dei \textit{file descriptor}} @@ -79,7 +80,7 @@ strutture di dati sulla quale essa \centering \includegraphics[width=14cm]{img/procfile.eps} \caption{Schema della architettura dell'accesso ai file attraverso - l'interfaccia dei \textit{file descroptor}} + l'interfaccia dei \textit{file descriptor}} \label{fig:file_proc_file} \end{figure} Ritorneremo su questo schema più volte, dato che esso è fondamentale per @@ -179,7 +180,6 @@ prototipo La funzione ritorna il file descriptor in caso di successo e -1 in caso di errore. In questo caso la variabile \var{errno} viene settata ad uno dei valori: - \begin{errlist} \item \macro{EEXIST} \var{pathname} esiste e si è specificato \macro{O\_CREAT} e \macro{O\_EXCL}. @@ -212,51 +212,8 @@ di \secref{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 -\secref{sec:file_sharing}). Il nuovo file descriptor è settato di default per -restare aperto attraverso una \func{exec} (come accennato in -\secref{sec:proc_exec}) ed l'offset è settato all'inizio del file. - -Il parametro \var{mode} specifica i permessi con cui il file viene -eventualmente creato; i valori possibili sono gli stessi già visti in -\secref{sec:file_perm_overview} e possono essere specificati come OR binario -delle costanti descritte in \tabref{tab:file_bit_perm}. Questi permessi -filtrati dal valore di \file{umask} (vedi \secref{sec:file_umask}) per il -processo. - -La funzione prevede diverse opzioni, che vengono specificate usando vari bit -del parametro \var{flags}. Alcuni di questi bit vanno anche a costituire il -flag di stato del file (o \textit{file status flag}), che è mantenuto nel -campo \var{f\_flags} della struttura \var{file} (al solito si veda lo schema -di \curfig). Essi sono divisi in tre categorie principali: -\begin{itemize} -\item \textsl{i bit delle modalità di accesso}: specificano con quale modalità - si accederà al file: i valori possibili sono lettura, scrittura o - lettura/scrittura. Uno di questi bit deve essere sempre specificato quando - si apre un file. Vengono settati alla chiamata da \func{open}, e possono - essere riletti con una \func{fcntl} (fanno parte del \textit{file status - flag}), ma non modificati. -\item \textsl{i bit delle modalità di apertura}: permettono di specificare - alcune delle caratteristiche del comportamento di \func{open} quando viene - eseguita. Hanno effetto solo al momento della chiamata della funzione e non - sono memorizzati nè possono essere riletti. -\item \textsl{i bit delle modalità di operazione}: permettono di specificare - alcune caratteristiche del comportamento delle future operazioni sul file - (come la \func{read} o la \func{write}). Anch'essi fanno parte del - \textit{file status flag}. Il loro valore è settato alla chiamata di - \func{open}, ma possono essere riletti e modificati (insieme alle - caratteristiche operative che controllano) con una \func{fcntl}. -\end{itemize} - -In \ntab\ si sono riportate, ordinate e divise fra loro secondo le tre -modalità appena elencate, le costanti mnemoniche associate a ciascuno di -questi bit, dette costanti possono essere combinate fra di loro con un OR -aritmetico per costruire il valore (in forma di maschera binaria) del -parametro \var{flags} da passare alla \func{open} per specificarne il -comportamento. -\begin{table}[!htbp] +\begin{table}[!htb] \centering \footnotesize \begin{tabular}[c]{|l|p{12cm}|} @@ -344,6 +301,50 @@ comportamento. \label{tab:file_open_flags} \end{table} +Il nuovo file descriptor non è condiviso con nessun altro processo, (torneremo +sulla condivisione dei file, in genere accessibile dopo una \func{fork}, in +\secref{sec:file_sharing}). Il nuovo file descriptor è settato di default per +restare aperto attraverso una \func{exec} (come accennato in +\secref{sec:proc_exec}) ed l'offset è settato all'inizio del file. + +Il parametro \var{mode} specifica i permessi con cui il file viene +eventualmente creato; i valori possibili sono gli stessi già visti in +\secref{sec:file_perm_overview} e possono essere specificati come OR binario +delle costanti descritte in \tabref{tab:file_bit_perm}. Questi permessi +filtrati dal valore di \file{umask} (vedi \secref{sec:file_umask}) per il +processo. + +La funzione prevede diverse opzioni, che vengono specificate usando vari bit +del parametro \var{flags}. Alcuni di questi bit vanno anche a costituire il +flag di stato del file (o \textit{file status flag}), che è mantenuto nel +campo \var{f\_flags} della struttura \var{file} (al solito si veda lo schema +di \curfig). Essi sono divisi in tre categorie principali: +\begin{itemize} +\item \textsl{i bit delle modalità di accesso}: specificano con quale modalità + si accederà al file: i valori possibili sono lettura, scrittura o + lettura/scrittura. Uno di questi bit deve essere sempre specificato quando + si apre un file. Vengono settati alla chiamata da \func{open}, e possono + essere riletti con una \func{fcntl} (fanno parte del \textit{file status + flag}), ma non modificati. +\item \textsl{i bit delle modalità di apertura}: permettono di specificare + alcune delle caratteristiche del comportamento di \func{open} quando viene + eseguita. Hanno effetto solo al momento della chiamata della funzione e non + sono memorizzati nè possono essere riletti. +\item \textsl{i bit delle modalità di operazione}: permettono di specificare + alcune caratteristiche del comportamento delle future operazioni sul file + (come la \func{read} o la \func{write}). Anch'essi fanno parte del + \textit{file status flag}. Il loro valore è settato alla chiamata di + \func{open}, ma possono essere riletti e modificati (insieme alle + caratteristiche operative che controllano) con una \func{fcntl}. +\end{itemize} + +In \tabref{tab:file_open_flags} si sono riportate, ordinate e divise fra loro +secondo le tre modalità appena elencate, le costanti mnemoniche associate a +ciascuno di questi bit, dette costanti possono essere combinate fra di loro +con un OR aritmetico per costruire il valore (in forma di maschera binaria) +del parametro \var{flags} da passare alla \func{open} per specificarne il +comportamento. + Nelle prime versioni di unix i flag specificabili per \func{open} erano solo quelli relativi alle modalità di accesso del file. Per questo motivo per creare un nuovo file c'era una system call apposita, \func{creat}, il cui @@ -357,44 +358,382 @@ prototipo adesso questa funzione resta solo per compatibilità con i vecchi programmi. +\subsection{La funzione \func{close}} +\label{sec:file_close} +La funzione \func{close} permette di chiudere un file, in questo modo il file +descriptor ritorna disponibile; il suo prototipo è: +\begin{prototype}{unistd.h}{int close(int fd)} + Chiude il descrittore \var{fd}. + + La funzione ritorna 0 in caso di successo e -1 n caso di errore. In questo + caso \var{errno} è settata ai valori: + \begin{errlist} + \item \macro{EBADF} \var{fd} non è un descrittore valido. + \item \macro{EINTR} la funzione è stata interrotta da un segnale. + \end{errlist} + ed \macro{EIO}. +\end{prototype} +La chiusura di un file rilascia ogni blocco (il \textit{file locking} è +trattato in \secref{sec:file_locking}) che il processo poteva avere acquisito +su di esso; se \var{fd} è ultimo (di eventuali copie) riferimento ad un file +aperto, tutte le risorse nella file table vengono rilasciate. Infine se il +file descriptor era l'ultimo riferimento ad un file su disco quest'ultimo +viene cancellato. + +Si ricordi che quando un processo termina anche tutti i sui file descriptor +vengono chiusi, molti programmi sfruttano questa caratteristica e non usano +esplicitamente \func{close}. In genere comunque chiudere un file senza +controllarne lo stato di uscita è errore; infatti molti filesystem +implementano la tecnica del \textit{write-behind}, per cui una \func{write} +può avere successo anche se i dati non sono stati scritti, un eventuale errore +di I/O allora può sfuggire, ma verrà riportato alla chiusura del file: per +questo motivo non effettuare il controllo può portare ad una perdita di dati +inavvertita; 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} 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). -\subsection{La funzione \func{close}} -\label{sec:file_close} \subsection{La funzione \func{lseek}} \label{sec:file_lseek} +Come già accennato in \secref{sec:file_fd} a ciascun file aperto è associata +una \textsl{posizione corrente nel file} (il cosiddetto \textit{file offset}, +mantenuto nel campo \var{f\_pos} di \var{file}) espressa da un numero intero +positivo come numero di bytes dall'inizio del file. Tutte le operazioni di +lettura e scrittura avvengono a partire da questa posizione che viene +automaticamente spostata in avanti del numero di byte letti o scritti. + +In genere (a meno di non avere richiesto la modalità \macro{O\_APPEND}) questa +posizione viene settata a zero all'apertura del file. È possibile settarla ad +un valore qualsiasi con la funzione \func{lseek}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{unistd.h} + \funcdecl{off\_t lseek(int fd, off\_t offset, int whence)} + La funzione setta la posizione attuale nel file. + + La funzione ritorna valore della posizione corrente in caso di successo e -1 + in caso di errore nel qual caso \var{errno} viene settata ad uno dei valori: + \begin{errlist} + \item \macro{ESPIPE} \var{fd} è una pipe, un socket o una fifo. + \item \macro{EINVAL} \var{whence} non è un valore valido. + \end{errlist} + e \macro{EBADF}. +\end{functions} + +La nuova posizione è settata usando il valore specificato da \var{offset}, +sommato al riferimento dato da \var{whence}; quest'ultimo può assumere i +seguenti valori\footnote{per compatibilità con alcune vecchie notazioni + questi valori possono essere rimpiazzati rispettivamente con 0, 1 e 2 o con + \macro{L\_SET}, \macro{L\_INCR} e \macro{L\_XTND}}: +\begin{description} +\item \macro{SEEK\_SET} si fa riferimento all'inizio del file: il valore di + \var{offset} è la nuova posizione. +\item \macro{SEEK\_CUR} si fa riferimento alla posizione corrente del file: + \var{offset} che può essere negativo e positivo. +\item \macro{SEEK\_END} si fa riferimento alla fine del file: il valore di + \var{offset} può essere negativo e positivo. +\end{description} + +Come accennato in \secref{sec:file_file_size} con \func{lseek} è possibile +settare la posizione corrente anche al di la della fine del file, e alla +successiva scrittura il file sarà esteso. La chiamata non causa nessuna +attività di input/output, si limita a modificare la posizione corrente nel +kernel (cioè \var{f\_pos} in \var{file}, vedi \figref{fig:file_proc_file}). + +Dato che la funzione ritorna la nuova posizione, usando il valore zero per +\func{offset} si può riottenere la posizione corrente nel file chiamando la +funzione con \func{lseek(fd, 0, SEEK\_CUR}. + +Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che +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 settata in precedenza. +Questa è una potenziale sorgente di \textit{race condition}, e quando si vuole +essere sicuri di scrivere alla fine del file questo deve essere posto in +modalità \macro{O\_APPEND}. + +Non tutti i file supportano la capacità di eseguire una \func{lseek}, in +questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per +i tre casi citati nel prototipo, vale anche per tutti quei dispositivi che non +supportano questa funzione, come ad esempio per le \acr{tty}\footnote{altri + sistemi, usando \macro{SEEK\_SET} in questo caso ritornano il numero di + caratteri che vi sono stati scritti}. Lo standard POSIX però non specifica +niente al proposito. Infine alcuni device, ad esempio \file{/dev/null}, non +causano un errore ma restituiscono un valore indefinito. + + \subsection{La funzione \func{read}} \label{sec:file_read} +Per leggere da un file precedentemente aperto, si può la funzione \func{read}, +il cui prototipo è: +\begin{prototype}{unistd.h}{ssize\_t read(int fd, void * buf, size\_t count)} + + La funzione cerca di leggere \var{count} bytes dal file \var{fd} al buffer + \var{buf}. + + La funzione ritorna il numero di byte letti in caso di successo e -1 in + caso di errore, nel qual caso \var{errno} viene settata ad uno dei valori: + \begin{errlist} + \item \macro{EINTR} la funzione è stata interrotta da un segnale prima di + aver potuto leggere quasiasi dato. + \item \macro{EAGAIN} la funzione non aveva nessun dato da restituire e si + era aperto il file in modalità \macro{O\_NONBLOCK}. + \end{errlist} + ed inoltre \macro{EBADF}, \macro{EIO}, \macro{EISDIR}, \macro{EBADF}, + \macro{EINVAL} e \macro{EFAULT} ed eventuali altri errori dipendenti dalla + natura dell'oggetto connesso a \var{fd}. +\end{prototype} + +La funzione tenta di leggere \var{count} byte a partire dalla posizione +corrente nel file; dopo la lettura la posizione è spostata automaticamente in +avanti del numero di bytes letti. Se \var{count} è zero la funzione +restituisce zero senza nessun altro risultato. + +Si deve sempre tener presente 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 però bisogna sempre tenere +presente. + +La prima e più ovvia di queste ragioni è che si è chiesto di leggere più bytes +di quanto il file ne contenga. In questo caso il file viene letto fino alla +sua fine, e la funzione ritorna regolarmente il numero di byte letti +effettivamente. Se ripetessimo la lettura \func{read} restituirebbe uno zero. +La condizione raggiungimento della fine del file non è un errore, e viene +segnalata appunto da un valore di ritorno di \func{read} nullo, ripetere la +lettura non avrebbe nessun effetto se non quello di continuare a ricevere zero +come valore di ritorno. + +Con i \textsl{file regolari} questa è l'unica situazione in cui si può avere +un numero di byte letti inferiore a quello richiesto, ma la situazione è +invece normale quando si legge da un terminale, o su una pipe. In tal caso +infatti, se non ci sono dati in ingresso, la \func{read} si blocca e ritorna +solo quando ne arrivano; se il numero di byte richiesti eccede quelli +disponibili la funzione ritorna comunque, ma con un numero di byte inferiore. + +Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket, +come vedremo in \secref{sec:sock_io_behav}), o per certi dispositivi come le +unità a nastro che restituiscono un singolo blocco di dati alla volta. + +In realtà anche le due condizioni segnalate dagli errori \func{EINTR} e +\func{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 prendere è quella di rieseguire la funzione. Torneremo +sull'argomento in \secref{sec:signal_xxx}. + +La seconda si verifica quando il file è in modalità non bloccante e non ci +sono dati in ingresso: la funzione allora ritorna immediatamente con un errore +\macro{EAGAIN}\footnote{sotto BSD questo per questo errore viene usata la + costante \macro{EWOULDBLOCK}, in GNU/Linux questa è sinonima di + \macro{EAGAIN}.} indicando che occorrerà provare a ripetere la lettura. + + +Lo standard Unix98\footnote{questa funzione, e l'analoga \func{pwrite} sono + state aggiunte nel kernel 2.1.60, il supporto nelle \acr{glibc}, compresa + l'emulazione per i vecchi kernel che non hanno la system call, è stato + aggiutno con la versione 2.1} (vedi \secref{sec:intro_opengroup}) prevede la +definizione di un'altra funzione di lettura, \func{pread}, che diventa +accessibile con la definizione: +\begin{verbatim} + #define _XOPEN_SOURCE 500 +\end{verbatim} +il prototipo di questa funzione è: +\begin{prototype}{unistd.h} +{ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)} + +La funzione cerca di leggere \var{count} bytes dal file \var{fd}, a partire +dalla posizione \var{offset}, nel buffer \var{buf}. + +La funzione ritorna il numero di byte letti in caso di successo e -1 in caso +di errore, nel qual caso \var{errno} viene settata secondo i valori già visti +per \func{read} e \func{lseek}. +\end{prototype} + +Questa funzione serve quando si vogliono leggere dati dal file senza +modificarne la posizione corrente. È equivalente alla esecuzione di una +\func{read} e una \func{lseek}, ma dato che la posizione sul file può essere +condivisa fra vari processi (vedi \secref{sec:file_sharing}), essa permette di +eseguire l'operazione atomicamente. Il valore di \var{offset} fa riferimento +all'inizio del file. + + \subsection{La funzione \func{write}} \label{sec:file_write} +Per scrivere su un file si usa la funzione \func{write}, il cui prototipo è: +\begin{prototype}{unistd.h}{ssize\_t write(int fd, void * buf, size\_t count)} + + La funzione scrive \var{count} bytes dal buffer \var{buf} sul file \var{fd}. + + La funzione ritorna il numero di byte scritti in caso di successo e -1 in + caso di errore, nel qual caso \var{errno} viene settata ad uno dei valori: + \begin{errlist} + \item \macro{EINVAL} \var{fd} è connesso ad un oggetto che non consente la + scrittura. + \item \macro{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. + \item \macro{EPIPE} \var{fd} è connesso ad una pipe il cui altro capo è + chiuso in lettura; in questo caso viene anche generato il segnale + \macro{SIGPIPE}, se questo viene gestito (o bloccato o ignorato) la + funzione ritorna questo errore. + \item \macro{EINTR} la funzione è stata interrotta da un segnale prima di + aver potuto scerivere quasiasi dato. + \item \macro{EAGAIN} la funzione non aveva nessun dato da restituire e si + era aperto il file in modalità \macro{O\_NONBLOCK}. + \end{errlist} + ed inoltre \macro{EBADF}, \macro{EIO}, \macro{EISDIR}, \macro{EBADF}, + \macro{ENOSPC}, \macro{EINVAL} e \macro{EFAULT} ed eventuali altri errori + dipendenti dalla natura dell'oggetto connesso a \var{fd}. +\end{prototype} + +Come nel caso di \func{read} la funzione tenta di scrivere \var{count} byte a +partire dalla posizione corrente nel file e sposta automaticamente la +posizione in avanti del numero di bytes scritti. Se il file è aperto in +modalità \macro{O\_APPEND} i dati vengono sempre scritti alla fine del file. +Lo standard POSIX richiede che i dati scritti siano immediatamente disponibili +ad una \func{read} chiamata dopo che la \func{write} che li ha scritti è +ritornata; ma dati i meccanismi di caching non è detto che tutti i filesystem +supportino questa capacità. + +Se \var{count} è zero la funzione restituisce zero senza fare nient'altro. Per +i file ordinari il numero di bytes scritti è sempre uguale a quello indicato +da \var{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 una analoga per scrivere +alla posizione indicata senza modificare la posizione corrente nel file, il +suo prototipo è: +\begin{prototype}{unistd.h} +{ssize\_t pwrite(int fd, void * buf, size\_t count, off\_t offset)} + +La funzione cerca di scrivere sul file \var{fd}, a partire dalla posizione +\var{offset}, \var{count} bytes dal buffer \var{buf}. + +La funzione ritorna il numero di byte letti in caso di successo e -1 in caso +di errore, nel qual caso \var{errno} viene settata secondo i valori già visti +per \func{write} e \func{lseek}. +\end{prototype} + + -\section{Funzioni avanzate} +\section{Caratteristiche avanzate} \label{sec:file_adv_func} +In questa sezione approfondireme alcune delle caratteristiche più sottili +della gestione file in un sistema unix-like, esaminando in dettaglio il +comportamento delle funzioni base, inoltre tratteremo alcune funzioni che +permettono di eseguire operazioni avanzate con i file. + \subsection{La condivisione dei files} \label{sec:file_sharing} -Si noti che i flag di stato del file, quelli settati dal parametro \var{flag} -di \func{open}, essendo tenuti nella vode sulla file table, vengono condivisi, -ai file sono però associati anche altri flag, (tenuti invece nella struttura -\var{file\_struct} interna alla process table) che sono unici per ciascun file -descriptor, e sono pertanto detti \textit{file descriptor flags} (l'unico -usato al momento è \macro{FD\_CLOEXEC}). +In \secref{sec:file_fd} abbiamo descritto brevemente l'architettura +dell'interfaccia coi file da parte di un processo, mostrando in +\figref{fig:file_proc_file} le principali strutture usate dal kernel; +esamineremo ora in dettaglio le conseguenze che questa architettura ha nei +confronti dell'accesso allo stesso file da parte di processi diversi. + +\begin{figure}[htb] + \centering + \includegraphics[width=14cm]{img/filemultacc.eps} + \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 che aprono lo stesso file +su disco; sulla base di quanto visto in \secref{sec:file_fd} avremo una +situazione come quella illustrata in \figref{fig:file_mult_acc}: ciascun +processo avrà una sua voce nella \textit{file table} referenziata da un +diverso file descriptor nella sua \var{file\_struct}. Entrambe le voci nella +\textit{file table} faranno però riferimento allo stesso inode su disco. + +Questo significa che ciascun processo avrà la sua posizione corrente sul file, +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} +\item ciascun processo può scrivere indipendentemente; dopo ciascuna + \func{write} la posizione corrente sarà cambiata solo nel processo. Se la + scrittura eccede la dimensione corrente del file questo verrà esteso + automaticamente con l'aggiornamento del campo \var{i\_size} nell'inode. +\item se un file è in modalità \macro{O\_APPEND} tutte le volte che viene + effettuata una scrittura la posizione corrente viene prima settata alla + dimensione corrente del file letta dall'inode. In questo modo il file viene + automaticamente esteso. +\item l'effetto di \func{lseek} è solo quello di cambiare il campo \var{f\_pos} + nella struttura \var{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 settata leggendo la dimensione corrente dall'inode. +\end{itemize} + +\begin{figure}[htb] + \centering + \includegraphics[width=14cm]{img/fileshar.eps} + \caption{Schema dell'accesso ai file da parte di un processo figlio} + \label{fig:file_acc_child} +\end{figure} + +È comunque possibile che due file descriptor di due processi diversi puntino +alla stessa voce nella \textit{file table}; questo è ad esempio il caso dei +file aperti che venfono ereditati dal processo figlio all'esecuzione di una +\func{fork} (si ricordi quanto detto in \secref{sec:proc_fork}). La situazione +è illustrata in \figref{fig:file_acc_child}; dato che il processo figlio +riceve una copia dello spazio di indirizzi del padre, riceverà anche una copia +di \var{file\_struct} e relativa tabella dei file aperti. + +In questo modo padre e figlio avranno gli stessi file descriptor che faranno +riferimento alla stessa voce nella \textit{file table}, condividendo così la +posizione corrente sul file. Questo ha le cosenguenze descritte a suo tempo in +\secref{sec:proc_fork}: in caso di scrittura contemporanea la posizione +corrente nel file varierà per entrambi i processi (in quanto verrà modificato +\var{f\_pos} che è la stesso per entrambi). + +Si noti inoltre che anche i flag di stato del file (quelli settati dal +parametro \var{flag} di \func{open}) essendo tenuti nella voce della +\textit{file table} (il campo \var{f\_flag} di \var{file}), vengono in questo +caso condivisi. Ai file però sono associati anche altri flag (l'unico usato al +momento è \macro{FD\_CLOEXEC}), detti \textit{file descriptor flags}, tenuti +invece in \var{file\_struct}; questi sono specifici di ciascun processo, e non +vengono toccati anche in caso di condivisione della voce della \textit{file + table}. + + \subsection{Operazioni atomiche coi file} \label{sec:file_atomic} +cvs add + + \subsection{La funzioni \func{dup} e \func{dup2}} \label{sec:file_dup} + + +\begin{figure}[htb] + \centering + \includegraphics[width=14cm]{img/filedup.eps} + \caption{Schema dell'accesso ai file duplicati} + \label{fig:file_dup} +\end{figure} + + \subsection{La funzione \func{fcntl}} \label{sec:file_fcntl}