Inserite funzioni "at", alcune modifiche per sigaction, finita
[gapil.git] / fileadv.tex
index 9a717f2e9b76b4370dd2d4ec1c24b1674f628221..ee49313125b9153e51a80e38b3da8db973d6b55b 100644 (file)
@@ -1,4 +1,4 @@
-gb%% fileadv.tex
+%% fileadv.tex
 %%
 %% Copyright (C) 2000-2007 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
@@ -694,13 +694,15 @@ file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}.
 
 L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
 di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
-\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD} per le quali serve ad
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD}, per le quali serve ad
 indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
-sotto controllo.  L'argomento viene ignorato con
+sotto controllo.  L'argomento viene ignorato con l'operazione
 \const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
   che questo fosse un puntatore valido, anche se poi veniva ignorato, a
   partire dal 2.6.9 si può specificare anche anche un valore \texttt{NULL}.}
 
+
+
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -717,10 +719,11 @@ La struttura \struct{epoll\_event} 
 quest'ultima serve sia in ingresso (quando usata con \func{epoll\_ctl}) ad
 impostare quali eventi osservare, che in uscita (nei risultati ottenuti con
 \func{epoll\_wait}) per ricevere le notifiche degli eventi avvenuti.  La sua
-definizione è riportata in fig.~\ref{fig:epoll_event}; il primo campo,
-\var{events}, è una maschera binaria in cui ciascun bit corrisponde o ad un
-tipo di evento, o una modalità di notifica. Detto campo deve essere
-specificato come OR aritmetico delle costanti riportate in
+definizione è riportata in fig.~\ref{fig:epoll_event}. 
+
+Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit
+corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo
+deve essere specificato come OR aritmetico delle costanti riportate in
 tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, serve ad indicare a
 quale file descriptor si intende fare riferimento, ed in astratto può
 contenere un valore qualsiasi che permetta di identificarlo, di norma comunque
@@ -764,35 +767,54 @@ si usa come valore lo stesso \param{fd}.
 
 \footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.2.}
 
-Le modalità di utilizzo di \textit{epoll} prevedano che si definisca un
-insieme di file descriptor da tenere sotto controllo su un \textit{epoll
-  descriptor} \param{epfd} con una serie di chiamate a
-\const{EPOLL\_CTL\_ADD}.  Il default prevede la notifica in modalità
-\textit{level triggered}, a meno che sul file descriptor non si sia impostata
-la modalità \textit{edge triggered} con \const{EPOLLET}.  Si tenga presente
-che è possibile tenere sotto osservazione uno stesso file descriptor su due
-\textit{epoll descriptor} diversi, ed entrambi riceveranno le notifiche, ma la
-pratica è sconsigliata.
-
-Una particolare modalità di notifica è quella impostata con
-\const{EPOLLONESHOT}: quando si è in modalità \textit{edge triggered} l'arrivo
-in rapida successione di dati in blocchi separati causa la generazione di una
-serie di eventi multipli; in questo caso si può utilizzare la modalità
-\textit{one-shot} in cui la notifica viene effettuata solo la prima volta,
-dopo di che il file descriptor osservato, pur restando nella lista di
-\param{epfd}, viene disattivato, e per essere riutilizzato dovrà essere
-riabilitato con una successiva chiamata con \const{EPOLL\_CTL\_MOD}.
-
-
-Infine qualora un file descriptor posto sotto osservazione dovesse essere
-chiuso, esso sarà automaticamente eliminato dall'insieme dei file descriptor
-osservati.
-
-
-
-
-La funzione che consente di attendere è \funcd{epoll\_wait}, il cui prototipo
-è:
+Le modalità di utilizzo di \textit{epoll} prevedano che si definisca qual'è
+l'insieme dei file descriptor da tenere sotto controllo tramite un certo
+\textit{epoll descriptor} \param{epfd} attraverso una serie di chiamate a
+\const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è che queste
+  chiamate devono essere ripetute per ciascun file descriptor, incorrendo in
+  una perdita di prestazioni qualora il numero di file descriptor sia molto
+  grande; per questo è stato proposto di introdurre come estensione una
+  funzione \func{epoll\_ctlv} che consenta di effettuare con una sola chiamata
+  le impostazioni per un blocco di file descriptor.} L'uso di
+\const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di
+osservazione di un file descriptor che sia già stato aggiunto alla lista di
+osservazione.
+
+Le impostazioni di default prevedono che la notifica degli eventi richiesti
+sia effettuata in modalità \textit{level triggered}, a meno che sul file
+descriptor non si sia impostata la modalità \textit{edge triggered},
+registrandolo con \const{EPOLLET} attivo nel campo \var{events}.  Si tenga
+presente che è possibile tenere sotto osservazione uno stesso file descriptor
+su due \textit{epoll descriptor} diversi, ed entrambi riceveranno le
+notifiche, anche se questa pratica è sconsigliata.
+
+Qualora non si abbia più interesse nell'osservazione di un file descriptor lo
+si può rimuovere dalla lista associata a \param{epfd} con
+\const{EPOLL\_CTL\_DEL}; si tenga conto inoltre che i file descriptor sotto
+osservazione che vengono chiusi sono eliminati dalla lista automaticamente e
+non è necessario usare \const{EPOLL\_CTL\_DEL}.
+
+Infine una particolare modalità di notifica è quella impostata con
+\const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti
+quando si è in modalità \textit{edge triggered} l'arrivo in rapida successione
+di dati in blocchi separati\footnote{questo è tipico con i socket di rete, in
+  quanto i dati arrivano a pacchetti.} può causare una generazione di eventi
+(ad esempio segnalazioni di dati in lettura disponibili) anche se la
+condizione è già stata rilevata.\footnote{si avrebbe cioè una rottura della
+  logica \textit{edge triggered}.} 
+
+Anche se la situazione è facile da gestire, la si può evitare utilizzando
+\const{EPOLLONESHOT} per impostare la modalità \textit{one-shot}, in cui la
+notifica di un evento viene effettuata una sola volta, dopo di che il file
+descriptor osservato, pur restando nella lista di osservazione, viene
+automaticamente disattivato,\footnote{la cosa avviene contestualmente al
+  ritorno di \func{epoll\_wait} a causa dell'evento in questione.} e per
+essere riutilizzato dovrà essere riabilitato esplicitamente con una successiva
+chiamata con \const{EPOLL\_CTL\_MOD}.
+
+Una volta impostato l'insieme di file descriptor che si vogliono osservare con
+i relativi eventi, la funzione che consente di attendere l'occorrenza di uno
+di tali eventi è \funcd{epoll\_wait}, il cui prototipo è:
 \begin{prototype}{sys/epoll.h}
   {int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents, int
     timeout)}
@@ -808,16 +830,61 @@ La funzione che consente di attendere 
   \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
     della scadenza di \param{timeout}.
   \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
-    con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
-    l'operazione richiesta con \param{op} non è supportata.
+    con \func{epoll\_create}, o \param{maxevents} non è maggiore di zero.
   \end{errlist}
 }
 \end{prototype}
 
+La funzione si blocca in attesa di un evento per i file descriptor registrati
+nella lista di osservazione di \param{epfd} fino ad un tempo massimo
+specificato in millisecondi tramite l'argomento \param{timeout}. Gli eventi
+registrati vengono riportati in un vettore di strutture \struct{epoll\_event}
+(che deve essere stato allocato in precedenza) all'indirizzo indicato
+dall'argomento \param{events}, fino ad un numero massimo di eventi impostato
+con l'argomento \param{maxevents}.
+
+La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora
+sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
+oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
+indica di non attendere e ritornare immediatamente,\footnote{anche in questo
+  caso il valore di ritorno sarà nullo.} o $-1$, che indica un'attesa
+indefinita. L'argomento \param{maxevents} dovrà invece essere sempre un intero
+positivo.
+
+Come accennato la funzione restituisce i suoi risultati nel vettore di
+strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
+campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
+eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
+stato impostato (per il file descriptor per cui si è verificato l'evento)
+quando questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}.
+
+Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
+come si è impostata la modalità di osservazione (se \textit{level triggered} o
+\textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
+che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
+questi vengano combinati. Inoltre qualora su di esso fossero presenti eventi
+non ancora notificati, e si effettuasse una modifica dell'osservazione con
+\const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla luce delle modifiche.
+
+Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
+il ritorno di \func{epoll\_wait} indica un file descriptor è pronto e resterà
+tale fintanto che non si sono completamente esaurite le operazioni su di esso,
+questo può essere rilevato con un errore di \errcode{EAGAIN} in una
+\func{read} o una \func{write},\footnote{è opportuno ricordare ancora una
+  volta che l'uso dell'I/O multiplexing richiede di operare sui file in
+  modalità non bloccante.} ma anche con il fatto che sono stati restituiti
+meno dati di quelli richiesti.
+
+Come per le precedenti \func{select} e \func{poll}, essendo queste funzioni
+utiilizzate prevalentemente con i server di rete, tratteremo degli esempi del
+loro più avanti, nella trattazione dei socket, ed in particolare in
+sez.~\ref{sec:TCP_sock_multiplexing}.
+
 
 \itindend{epoll}
-% TODO epoll 
-%
+
+
 
 \section{L'accesso \textsl{asincrono} ai file}
 \label{sec:file_asyncronous_access}
@@ -830,44 +897,52 @@ contesto le modalit
 \textsl{asincrona}, quelle cioè in cui un processo non deve bloccarsi in
 attesa della disponibilità dell'accesso al file, ma può proseguire
 nell'esecuzione utilizzando invece un meccanismo di notifica asincrono (di
-norma un segnale), per essere avvisato della possibilità di eseguire le
+norma un segnale, ma esistono anche altre interfacce, come \itindex{inotify}
+\textit{inotify}), per essere avvisato della possibilità di eseguire le
 operazioni di I/O volute.
 
 
-\subsection{Operazioni asincrone sui file}
+\subsection{Il \textit{Signal driven I/O}}
 \label{sec:file_asyncronous_operation}
 
-Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso l'uso
-del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
-  comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è specifico
-  di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile
-attivare in un secondo tempo questa modalità impostando questo flag attraverso
-l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
-sez.~\ref{sec:file_fcntl}). 
-
-In realtà in questo caso non si tratta di eseguire delle operazioni di lettura
-o scrittura del file in modo asincrono (tratteremo questo, che più
-propriamente è detto \textsl{I/O asincrono} in
-sez.~\ref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di
-notifica delle variazione dello stato del file descriptor aperto in questo
-modo.
-
-Quello che succede in questo caso è che il sistema genera un segnale
-(normalmente \const{SIGIO}, ma è possibile usarne altri con il comando
-\const{F\_SETSIG} di \func{fcntl}) tutte le volte che diventa possibile
-leggere o scrivere dal file descriptor che si è posto in questa modalità. Si
-può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
+Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso
+l'uso del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e
+  dei comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è
+  specifico di Linux e BSD.} aprire un file in modalità asincrona, così come è
+possibile attivare in un secondo tempo questa modalità impostando questo flag
+attraverso l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
+sez.~\ref{sec:file_fcntl}).
+
+In realtà parlare di apertura in modalità asincrona non significa che le
+operazioni di lettura o scrittura del file vengono eseguite in modo asincrono
+(tratteremo questo, che è ciò che più propriamente viene chiamato \textsl{I/O
+  asincrono}, in sez.~\ref{sec:file_asyncronous_io}), quanto dell'attivazione
+un meccanismo di notifica asincrona delle variazione dello stato del file
+descriptor aperto in questo modo.  Quello che succede in questo caso è che il
+sistema genera un segnale (normalmente \const{SIGIO}, ma è possibile usarne
+altri con il comando \const{F\_SETSIG} di \func{fcntl}) tutte le volte che
+diventa possibile leggere o scrivere dal file descriptor che si è posto in
+questa modalità.\footnote{questa modalità non è utilizzabile con i file
+  ordinari ma solo con socket, file di terminale o pseudo terminale, e, a
+  partire dal kernel 2.6, anche per fifo e pipe.}
+
+Si può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
 quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
 effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
 sarà più la necessità di restare bloccati in attesa della disponibilità di
-accesso ai file; per questo motivo Stevens chiama questa modalità
-\textit{signal driven I/O}.
-
-Questa è un'altra modalità di gestione I/O, alternativa all'uso di
-\itindex{epoll} \textit{epoll}, che consente di evitare l'uso delle funzioni
-\func{poll} o \func{select} che, come illustrato in sez.~\ref{sec:file_epoll},
-quando vengono usate con un numero molto grande di file descriptor, non hanno
-buone prestazioni.
+accesso ai file. 
+
+Per questo motivo Stevens, ed anche le pagine di manuale di
+Linux, chiamano questa modalità ``\textit{Signal driven I/O}''.  Questa è
+ancora un'altra modalità di gestione dell'I/O, alternativa all'uso di
+\itindex{epoll} \textit{epoll},\footnote{anche se le prestazioni ottenute con
+  questa tecnica sono inferiori, il vantaggio è che questa modalità è
+  utilizzabile anche con kernel che non supportano \textit{epoll}, come quelli
+  della serie 2.4, ottenendo comunque prestazioni superiori a quelle che si
+  hanno con \func{poll} e \func{select}.} che consente di evitare l'uso delle
+funzioni \func{poll} o \func{select} che, come illustrato in
+sez.~\ref{sec:file_epoll}, quando vengono usate con un numero molto grande di
+file descriptor, non hanno buone prestazioni.
 
 Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
 presenta notevoli problemi, dato che non è possibile determinare, quando i
@@ -905,11 +980,16 @@ un file su cui l'accesso 
 funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
 la coda.  
 
-Se infatti si  eccedono le dimensioni di quest'ultima,  il kernel, non potendo
-più assicurare il comportamento corretto  per un segnale real-time, invierà al
-suo posto un solo \const{SIGIO}, su  cui si saranno accumulati tutti i segnali
-in  eccesso, e si  dovrà allora  determinare con  un ciclo  quali sono  i file
-diventati attivi.
+Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
+più assicurare il comportamento corretto per un segnale real-time, invierà al
+suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti i segnali
+in eccesso, e si dovrà allora determinare con un ciclo quali sono i file
+diventati attivi. L'unico modo per essere sicuri che questo non avvenga è di
+impostare la lunghezza della coda dei segnali real-time ad una dimensione
+identica al valore massimo del numero di file descriptor
+utilizzabili.\footnote{vale a dire impostare il contenuto di
+  \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore di quello di
+  \texttt{/proc/sys/fs/file-max}.}
 
 % TODO fare esempio che usa O_ASYNC
 
@@ -1575,7 +1655,7 @@ operazioni di sincronizzazione dei dati saranno completate.
 
 In alcuni casi può essere necessario interrompere le operazioni (in genere
 quando viene richiesta un'uscita immediata dal programma), per questo lo
-standard POSIX.1b prevede una funzioni apposita, \funcd{aio\_cancel}, che
+standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
 permette di cancellare una operazione richiesta in precedenza; il suo
 prototipo è:
 \begin{prototype}{aio.h}
@@ -3318,7 +3398,8 @@ possibilit
 % LocalWords:  dell'inode CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl
 % LocalWords:  attribute Universe epoll Solaris kqueue level triggered Jonathan
 % LocalWords:  Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
-% LocalWords:  MOD
+% LocalWords:  MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one
+% LocalWords:  EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents
 
 
 %%% Local Variables: