Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra
\textit{fast} e \textit{slow} system call,\index{system~call~lente} che in
certi casi le funzioni di I/O possono bloccarsi indefinitamente.\footnote{si
- ricordi però che questo può accadere solo per le pipe, i
- socket\index{socket} ed alcuni file di
- dispositivo\index{file!di~dispositivo}; sui file normali le funzioni di
- lettura e scrittura ritornano sempre subito.} Ad esempio le operazioni di
-lettura possono bloccarsi quando non ci sono dati disponibili sul descrittore
-su cui si sta operando.
+ ricordi però che questo può accadere solo per le pipe, i socket ed alcuni
+ file di dispositivo\index{file!di~dispositivo}; sui file normali le funzioni
+ di lettura e scrittura ritornano sempre subito.} Ad esempio le operazioni
+di lettura possono bloccarsi quando non ci sono dati disponibili sul
+descrittore su cui si sta operando.
Questo comportamento causa uno dei problemi più comuni che ci si trova ad
affrontare nelle operazioni di I/O, che si verifica quando si deve operare con
Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
multiplexing} è stato BSD,\footnote{la funzione \func{select} è apparsa in
BSD4.2 e standardizzata in BSD4.4, ma è stata portata su tutti i sistemi che
- supportano i \textit{socket}\index{socket}, compreso le varianti di System
- V.} con la funzione \funcd{select}, il cui prototipo è:
+ supportano i socket, compreso le varianti di System V.} con la funzione
+\funcd{select}, il cui prototipo è:
\begin{functions}
\headdecl{sys/time.h}
\headdecl{sys/types.h}
Per specificare quali file descriptor si intende \textsl{selezionare}, la
funzione usa un particolare oggetto, il \textit{file descriptor set},
identificato dal tipo \type{fd\_set}, che serve ad identificare un insieme di
-file descriptor, in maniera analoga a come un
-\itindex{signal~set}\textit{signal set} (vedi sez.~\ref{sec:sig_sigset})
-identifica un insieme di segnali. Per la manipolazione di questi \textit{file
- descriptor set} si possono usare delle opportune macro di preprocessore:
+file descriptor, in maniera analoga a come un \itindex{signal~set}
+\textit{signal set} (vedi sez.~\ref{sec:sig_sigset}) identifica un insieme di
+segnali. Per la manipolazione di questi \textit{file descriptor set} si
+possono usare delle opportune macro di preprocessore:
\begin{functions}
\headdecl{sys/time.h}
\headdecl{sys/types.h}
tutti i casi in cui la successiva esecuzione di \func{read} risulti non
bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
\param{writefds}, per verificare la possibilità effettuare una scrittura ed il
-terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i
-messaggi urgenti su un \textit{socket}\index{socket}, vedi
+terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
+urgenti \itindex{out-of-band} su un socket, vedi
sez.~\ref{sec:TCP_urgent_data}).
Dato che in genere non si tengono mai sotto controllo fino a
specificare anche un tempo nullo (cioè una struttura \struct{timeval} con i
campi impostati a zero), qualora si voglia semplicemente controllare lo stato
corrente dei file descriptor.
-\itindend{file~descriptor~set}
La funzione restituisce il numero di file descriptor pronti,\footnote{questo è
il comportamento previsto dallo standard, ma la standardizzazione della
insiemi sono indefiniti e non si può fare nessun affidamento sul loro
contenuto.
+\itindend{file~descriptor~set}
+
In Linux \func{select} modifica anche il valore di \param{timeout},
impostandolo al tempo restante in caso di interruzione prematura; questo è
utile quando la funzione viene interrotta da un segnale, in tal caso infatti
Per questo è stata introdotta \func{pselect} che attraverso l'argomento
\param{sigmask} permette di riabilitare la ricezione il segnale
-contestualmente all'esecuzione della funzione,\footnote{in Linux però non è
- presente la relativa system call, e la funzione è implementata nelle
- \acr{glibc} attraverso \func{select} (vedi \texttt{man select\_tut}) per cui
- la possibilità di \itindex{race~condition}\textit{race condition} permane;
- esiste però una soluzione, chiamata \itindex{self-pipe trick}
- \textit{self-pipe trick}, che consiste nell'aprire una pipe (vedi
- sez.~\ref{sec:ipc_pipes}) ed usare \func{select} sul capo in lettura della
- stessa, e indicare l'arrivo di un segnale scrivendo sul capo in scrittura
- all'interno del manipolatore; in questo modo anche se il segnale va perso
- prima della chiamata di \func{select} questa lo riconoscerà comunque dalla
- presenza di dati sulla pipe.} ribloccandolo non appena essa ritorna, così
-che il precedente codice potrebbe essere riscritto nel seguente modo:
+contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al
+ kernel 2.6.26, non è presente la relativa system call, e la funzione è
+ implementata nelle \acr{glibc} attraverso \func{select} (vedi \texttt{man
+ select\_tut}) per cui la possibilità di \itindex{race~condition}
+ \textit{race condition} permane; esiste però una soluzione, chiamata
+ \itindex{self-pipe trick} \textit{self-pipe trick}, che consiste nell'aprire
+ una pipe (vedi sez.~\ref{sec:ipc_pipes}) ed usare \func{select} sul capo in
+ lettura della stessa, e indicare l'arrivo di un segnale scrivendo sul capo
+ in scrittura all'interno del manipolatore; in questo modo anche se il
+ segnale va perso prima della chiamata di \func{select} questa lo riconoscerà
+ comunque dalla presenza di dati sulla pipe.} ribloccandolo non appena essa
+ritorna, così che il precedente codice potrebbe essere riscritto nel seguente
+modo:
\includecodesnip{listati/pselect_norace.c}
in questo caso utilizzando \var{oldmask} durante l'esecuzione di
\func{pselect} la ricezione del segnale sarà abilitata, ed in caso di
interruzione si potranno eseguire le relative operazioni.
% TODO pselect è stata introdotta nel kernel 2.6.16 (o 15 o 17?) insieme a
-% ppoll mettere e verificare
+% ppoll mettere e verificare, vedi articolo LWN http://lwn.net/Articles/176750/
\subsection{La funzione \func{poll}}
\const{POLLIN} & È possibile la lettura.\\
\const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\
\const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\
- \const{POLLPRI} & È possibile la lettura di dati urgenti.\\
+ \const{POLLPRI} & È possibile la lettura di \itindex{out-of-band} dati
+ urgenti.\\
\hline
\const{POLLOUT} & È possibile la scrittura immediata.\\
\const{POLLWRNORM}& È possibile la scrittura di dati normali. \\
delle librerie standard del C.} è da questi che derivano i nomi di alcune
costanti, in quanto per essi sono definite tre classi di dati:
\textsl{normali}, \textit{prioritari} ed \textit{urgenti}. In Linux la
-distinzione ha senso solo per i dati \textit{out-of-band} dei socket (vedi
-sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce
-alle varie condizioni dei socket torneremo in sez.~\ref{sec:TCP_serv_poll},
-dove vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le
-costanti relative ai diversi tipi di dati (come \const{POLLRDNORM} e
-\const{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la
-macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in
- testa al file, definirla soltanto prima di includere \file{sys/poll.h} non è
- sufficiente.}
+distinzione ha senso solo per i dati urgenti \itindex{out-of-band} dei socket
+(vedi sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll}
+reagisce alle varie condizioni dei socket torneremo in
+sez.~\ref{sec:TCP_serv_poll}, dove vedremo anche un esempio del suo utilizzo.
+Si tenga conto comunque che le costanti relative ai diversi tipi di dati (come
+\const{POLLRDNORM} e \const{POLLRDBAND}) sono utilizzabili soltanto qualora si
+sia definita la macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di
+ farlo sempre in testa al file, definirla soltanto prima di includere
+ \file{sys/poll.h} non è sufficiente.}
In caso di successo funzione ritorna restituendo il numero di file (un valore
positivo) per i quali si è verificata una delle condizioni di attesa richieste
\textit{lease breaker} rimaste bloccate proseguono automaticamente.
-\index{file!notify|(}
+\index{file!dnotify|(}
Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da
parte di più processi, l'uso dei \textit{file lease} non consente comunque di
modificato, che è quanto necessario ad esempio ai programma di gestione dei
file dei vari desktop grafici.
-Per risolvere questo problema è stata allora creata un'altra interfaccia che
-consente di richiedere una notifica quando una directory, o di uno qualunque
-dei file in essa contenuti, viene modificato. Come per i \textit{file lease}
-la notifica avviene di default attraverso il segnale \const{SIGIO}, ma questo
-può essere modificato e si può ottenere nel manipolatore il file descriptor
-che è stato modificato dal contenuto della struttura \struct{siginfo\_t}.
+Per risolvere questo problema è stata allora creata un'altra interfaccia,
+chiamata \textit{dnotify}, che consente di richiedere una notifica quando una
+directory, o di uno qualunque dei file in essa contenuti, viene modificato.
+Come per i \textit{file lease} la notifica avviene di default attraverso il
+segnale \const{SIGIO}, ma questo può essere modificato e si può ottenere nel
+manipolatore il file descriptor che è stato modificato dal contenuto della
+struttura \struct{siginfo\_t}.
\index{file!lease|)}
specificate in chiamate successive vengono aggiunte a quelle già impostate
nelle precedenti. Se si vuole rimuovere la notifica si deve invece
specificare un valore nullo.
-
-\index{file!notify|)}
-
-
-
+\index{file!dnotify|)}
-
-
-
-% TODO inserire anche inotify
+\index{file!inotify|)}
+% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
+\index{file!inotify|(}
effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
Benché la modalità di apertura asincrona di un file possa risultare utile in
-varie occasioni (in particolar modo con i socket\index{socket} e gli altri
-file per i quali le funzioni di I/O sono \index{system~call~lente}system call
-lente), essa è comunque limitata alla notifica della disponibilità del file
-descriptor per le operazioni di I/O, e non ad uno svolgimento asincrono delle
-medesime. Lo standard POSIX.1b definisce una interfaccia apposita per l'I/O
-asincrono vero e proprio, che prevede un insieme di funzioni dedicate per la
-lettura e la scrittura dei file, completamente separate rispetto a quelle
-usate normalmente.
+varie occasioni (in particolar modo con i socket e gli altri file per i quali
+le funzioni di I/O sono \index{system~call~lente}system call lente), essa è
+comunque limitata alla notifica della disponibilità del file descriptor per le
+operazioni di I/O, e non ad uno svolgimento asincrono delle medesime. Lo
+standard POSIX.1b definisce una interfaccia apposita per l'I/O asincrono vero
+e proprio, che prevede un insieme di funzioni dedicate per la lettura e la
+scrittura dei file, completamente separate rispetto a quelle usate
+normalmente.
In generale questa interfaccia è completamente astratta e può essere
implementata sia direttamente nel kernel, che in user space attraverso l'uso
accesso ai file più evolute rispetto alle normali funzioni di lettura e
scrittura che abbiamo esaminato in sez.~\ref{sec:file_base_func}. In questa
sezione allora prenderemo in esame le interfacce per l'\textsl{I/O
- vettorizzato} e per l'\textsl{I/O mappato in memoria}.
+ vettorizzato} e per l'\textsl{I/O mappato in memoria} e la funzione
+\func{sendfile}.
\subsection{I/O vettorizzato}
protezione verrà applicata a tutte le pagine contenute, anche parzialmente,
dall'intervallo fra \param{addr} e \param{addr}+\param{size}-1.
-
Infine Linux supporta alcune operazioni specifiche non disponibili su altri
kernel unix-like. La prima di queste è la possibilità di modificare un
precedente \textit{memory mapping}, ad esempio per espanderlo o restringerlo.
% TODO l'I/O sulle porte di I/O
% consultare le manpage di ioperm, iopl e outb
+%\subsection{L'I/O diretto fra file descriptor con \func{sendfile}}
+%\label{sec:file_sendfile}
+%
+% TODO documentare la funzione sendfile
+% consultare la manpage di sendfile
+
+
\section{Il file locking}
\label{sec:file_locking}
% LocalWords: flock shared exclusive operation dup inode linked NFS cmd ENOLCK
% LocalWords: EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP
% LocalWords: switch bsd lockf mandatory SVr sgid group root mount mand TRUNC
-% LocalWords: SVID UX Documentation
+% LocalWords: SVID UX Documentation sendfile