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.
\itindend{memory~mapping}
+\subsection{L'I/O diretto fra file descriptor con \func{sendfile}}
+\label{sec:file_sendfile}
+
+Uno dei problemi
+
+NdA è da finire, sul perché non è abilitata fra file vedi:
+
+\href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}
+{\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}
+% TODO documentare la funzione sendfile
+
+
+
% i raw device
%\subsection{I \textit{raw} device}
%\label{sec:file_raw_device}
% consultare le manpage di ioperm, iopl e outb
+
+
\section{Il file locking}
\label{sec:file_locking}
\subsection{Il \textit{mandatory locking}}
\label{sec:file_mand_locking}
+\itindbeg{mandatory~locking|(}
+
Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4,
per introdurre un file locking che, come dice il nome, fosse effettivo
indipendentemente dai controlli eseguiti da un processo. Con il
qual caso la funzione fallisce con il solito \errcode{EAGAIN}) che comporta la
possibilità di modificare il file.
\index{file!locking|)}
+\itindend{mandatory~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