From: Simone Piccardi Date: Mon, 12 Nov 2001 23:18:26 +0000 (+0000) Subject: Completate: condivisione, operazioni atomiche sui file, dup ed iniziata X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=4f6d6cb9e5228bfa2341e052acbf23c3d78b2780;ds=sidebyside Completate: condivisione, operazioni atomiche sui file, dup ed iniziata fcntl --- diff --git a/fileunix.tex b/fileunix.tex index 3001194..06efeda 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -758,18 +758,44 @@ creare un file di lock, bloccandosi se il file esiste. In questo caso la sequenza logica porterebbe a verificare prima l'esistenza del file con una \func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la possibilità di una race condition da parte di un altro processo che crea lo -stesso file fra il controllo e la creazione. - -Per questo motivo sono stati introdotti i flag \macro{O\_CREAT} -\macro{O\_EXCL} +stesso file fra il controllo e la creazione. +Per questo motivo sono stati introdotti i due flag \macro{O\_CREAT} e +\macro{O\_EXCL}, in questo modo l'operazione di controllo dell'esistenza del +file (con relativa uscita dalla funzione con un errore) e creazione in caso di +assenza, diventa atomica essendo svolta tutta all'interno di una singola +\func{open}. \subsection{La funzioni \func{dup} e \func{dup2}} \label{sec:file_dup} +Abbiamo già visto in \secref{sec:file_sharing} 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 \func{dup} il cui +prototipo è: +\begin{prototype}{unistd.h}{int dup(int oldfd)} + + La funzione crea una copia del file descriptor \param{oldfd}. + + La funzione ritorna il nuovo file descriptor 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{EBADF} \param{oldfd} non è un file aperto. + \item \macro{EMFILE} si è raggiunto il numero massimo consentito di file + descriptor aperti. + \end{errlist} +\end{prototype} +La funzione ritorna, come \func{open}, il primo file descriptor libero. Il +file descriptor è una copia esatta del precedente ed entrambi possono essere +interscambiati nell'uso. Per capire meglio il funzionamento della funzione si +può fare riferimento a \figref{fig:file_dup}: l'effetto della funzione è +semplicamente quello di copiare il valore nella struttura \var{file\_struct}, +cosicché anche il nuovo file descriptor fa riferirimento alla stessa voce +nella \textit{file table}. \begin{figure}[htb] \centering \includegraphics[width=14cm]{img/filedup.eps} @@ -777,10 +803,91 @@ Per questo motivo sono stati introdotti i flag \macro{O\_CREAT} \label{fig:file_dup} \end{figure} +In questo modo entrambi i file condivideranno eventuali lock, \textit{file + status flag}, e posizione corrente: se ad esempio \func{lseek} modifica la +posizione su uno dei due file descriptor essa sarà modificata anche sull'altro +(al solito viene modificato lo stesso campo nella voce della \textit{file + table} a cui entrambi fanno riferimento). + +L'unica differenza fra i due file descriptor è che ciascuno avrà il suo +\textit{file descriptor flag}; nel caso di \func{dup} il flag di \textit{close + on exec} viene sempre cancellato nella copia. + +Una diversa versione della funzione, \func{dup2} viene utilizzata per +specificare esplicitamente il nuovo file descriptor; il suo prototipo è: +\begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)} + + La funzione rende \param{newfd} una copia del file descriptor \param{oldfd}. + + La funzione ritorna il nuovo file descriptor 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{EBADF} \param{oldfd} non è un file aperto o \param{newfd} ha un + valore fuori dall'intervallo consentito per i file descriptor. + \item \macro{EMFILE} si è raggiunto il numero massimo consentito di file + descriptor aperti. + \end{errlist} +\end{prototype} +\noindent la funzione chiude il file descriptor \param{newfd} se è aperto. + +La duplicazione dei file descriptor può essere effettuata anche usando la +funzione di controllo dei file \func{fnctl} (che esamineremo in +\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}. + +L'operazione ha la sintassi \func{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0 +come valore per \param{newfd} diventa equivalente a \func{dup}. La sola +differenza, a parte i codici di errore, è che \func{dup2} chiude il nuovo file +se è già aperto mentre \func{fcntl} apre il primo disponibile con un valore +superiore, per cui per poterla usare come \func{dup2} occorrerebbe prima +effettare una \func{close}, perdendo l'atomicità dell'operazione. + +L'uso principale di queste funzioni è per la redirezione dell'input e +dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec}; +diventa così possibile associare un file (o una pipe) allo standard input o +allo standard output, torneremo su questo uso più avanti quando tratteremo le +pipe. + \subsection{La funzione \func{fcntl}} \label{sec:file_fcntl} +Oltre alle operazioni base esaminate in \secref{sec:file_base_func} esistono +tutta una serie di operazioni ausiliarie che è possibile eseguire su un file +descriptor. Per queste operazioni di manipolazione delle varie proprietà di un +file descriptor viene usata la funzione \func{fcntl} il cui prototipo è: +\begin{functions} + \headdecl{unistd.h} + \headdecl{fcntl.h} + \funcdecl{int fcntl(int fd, int cmd)} + \funcdecl{int fcntl(int fd, int cmd, long arg)} + \funcdecl{int fcntl(int fd, int cmd, struct flock *lock)} + La funzione esegue una delle possibili operazioni specificate da \param{cmd} + sul file \param{fd}. + + La funzione ha valori di ritorno diversi a seconda dell'operazione. In caso + di errore il valore di ritorno è -1 e la variabile \var{errno} viene settata + ad un opportuno codice, quelli validi in generale sono: + \begin{errlist} + \item \macro{EBADF} \param{oldfd} non è un file aperto. + \end{errlist} +\end{functions} + +Il comportamento di questa funzione è determinato dal valore del comando +\param{cmd} che le viene fornito; in \secref{sec:file_dup} abbiamo incontrato +un esempio, una lista dei possibili valori è riportata di seguito: +\begin{basedescript}{\desclabelwidth{2.0cm}} +\item[\macro{F\_DUPFD}] trova il primo file descriptor disponibile di valore + maggiore o uguale ad \param{arg} e ne fa una copia di \var{fd}. In caso di + successo ritorna il nuovo file descriptor. Gli errori possibili sono + \macro{EINVAL} se \param{arg} è negativo o maggiore del massimo consentito o + \macro{EMFILE} se il processo ha già raggiunto il massimo numero di + descrittori consentito. +\item[\macro{F\_GETFD}] ritorna il valore dei \textit{file descriptor flag} di + \var{fd}, al momento è definito solo \macro{FD\_CLOEXEC}. Prova prov proep +\item[\macro{F\_SETFD}] setta il valore dei \textit{file descriptor flag} + specificato da \param{arg}. +\end{basedescript} + \subsection{La funzione \func{ioctl}} \label{sec:file_ioctl} diff --git a/gapil.tex b/gapil.tex index ee3e1a0..3b8ed0b 100644 --- a/gapil.tex +++ b/gapil.tex @@ -1,7 +1,7 @@ -%% +%% %% GaPiL : Guida alla Programmazione in Linux -%% -%% S. Piccardi Oct. 2000 +%% +%% S. Piccardi Oct. 2000 %% %% main.tex: file principale, gli altri vanno inclusi da questo. %% diff --git a/img/filedup.dia b/img/filedup.dia index 972233c..9519a40 100644 Binary files a/img/filedup.dia and b/img/filedup.dia differ