Correzioni varie e inizio timerfd
[gapil.git] / fileadv.tex
index fe6dda66ab8436d5124db5ab9a99f033d52ab99f..156de8e2b94492f49205904f7d9eae6f2e8a0aad 100644 (file)
@@ -10,7 +10,6 @@
 %%
 \chapter{La gestione avanzata dei file}
 \label{cha:file_advanced}
-
 In questo capitolo affronteremo le tematiche relative alla gestione avanzata
 dei file. Inizieremo con la trattazione delle problematiche del \textit{file
   locking} e poi prenderemo in esame le varie funzionalità avanzate che
@@ -1573,7 +1572,7 @@ controllare, per questo si deve usare la seconda funzione dell'interfaccia,
     l'operazione richiesta.
   \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}.
   \item[\errcode{ENOSPC}] si è raggiunto il limite massimo di registrazioni
-    per utente di file descriptor da osservere imposto da
+    per utente di file descriptor da osservare imposto da
     \procfile{/proc/sys/fs/epoll/max\_user\_watches}.
   \end{errlist}
 }
@@ -1866,9 +1865,10 @@ programma che utilizza questa interfaccia in sez.~\ref{sec:TCP_serv_epoll}.
 Abbiamo visto in sez.~\ref{sec:file_select} come il meccanismo classico delle
 notifiche di eventi tramite i segnali, presente da sempre nei sistemi
 unix-like, porti a notevoli problemi nell'interazione con le funzioni per
-l'I/O multiplexing, tanto che per evitare possibili \itindex{race~condition}
-\textit{race condition} sono state introdotte estensioni dello standard POSIX e
-funzioni apposite come \func{pselect}, \func{ppoll} e \funcd{epoll\_pwait}.
+l'\textit{I/O multiplexing}, tanto che per evitare possibili
+\itindex{race~condition} \textit{race condition} sono state introdotte
+estensioni dello standard POSIX e funzioni apposite come \func{pselect},
+\func{ppoll} e \funcd{epoll\_pwait}.
 
 Benché i segnali siano il meccanismo più usato per effettuare notifiche ai
 processi, la loro interfaccia di programmazione, che comporta l'esecuzione di
@@ -1898,10 +1898,10 @@ Abbiamo visto per
 sincrona dei segnali con la funzione \func{sigwait} e le sue affini. Queste
 funzioni consentono di gestire i segnali bloccando un processo fino alla
 avvenuta ricezione e disabilitando l'esecuzione asincrona rispetto al resto
-del programma del gestore del segnale. Questo consente di risolvere i
-problemi di atomicità nella gestione degli eventi associati ai segnali, avendo
-tutto il controllo nel flusso principale del programma, ottenendo così una
-gestione simile a quella dell'I/O multiplexing, ma non risolve i problemi
+del programma del gestore del segnale. Questo consente di risolvere i problemi
+di atomicità nella gestione degli eventi associati ai segnali, avendo tutto il
+controllo nel flusso principale del programma, ottenendo così una gestione
+simile a quella dell'\textit{I/O multiplexing}, ma non risolve i problemi
 delle interazioni con quest'ultimo, perché o si aspetta la ricezione di un
 segnale o si aspetta che un file descriptor sia accessibile e nessuna delle
 rispettive funzioni consente di fare contemporaneamente entrambe le cose.
@@ -1918,25 +1918,27 @@ In sostanza, come per \func{sigwait}, si pu
 gestore in occasione dell'arrivo di un segnale, e rilevarne l'avvenuta
 ricezione leggendone la notifica tramite l'uso di uno speciale file
 descriptor. Trattandosi di un file descriptor questo potrà essere tenuto sotto
-osservazione con le ordinarie funzioni dell'I/O multiplexing (vale a dire con
-le solite \func{select}, \func{poll} e \funcd{epoll\_wait}) allo stesso modo
-di quelli associati a file o socket, per cui alla fine si potrà attendere in
-contemporanea sia l'arrivo del segnale che la disponibilità di accesso ai dati
-relativi a questi ultimi.
+osservazione con le ordinarie funzioni dell'\textit{I/O multiplexing} (vale a
+dire con le solite \func{select}, \func{poll} e \funcd{epoll\_wait}) allo
+stesso modo di quelli associati a file o socket, per cui alla fine si potrà
+attendere in contemporanea sia l'arrivo del segnale che la disponibilità di
+accesso ai dati relativi a questi ultimi.
 
 La funzione che permette di abilitare la ricezione dei segnali tramite file
-descriptor è \funcd{signalfd},\footnote{in realtà quella riportata è la
-  interfacia alla funzione fornita dalle \acr{glibc}, esistono in realtà due
-  versioni diverse della \textit{system call}, la prima versione,
+descriptor è \funcd{signalfd},\footnote{in realtà quella riportata è
+  l'interfaccia alla funzione fornita dalle \acr{glibc}, esistono infatti due
+  versioni diverse della \textit{system call}; una prima versione,
   \func{signalfd}, introdotta nel kernel 2.6.22 e disponibile con le
-  \acr{glibc} 2.8 che non supporta l'argomento, ed una seconda versione,
-  \func{signalfd4}, che prende argomenti aggiuntivi, introdotta con il kernel
-  2.6.27 che è quella che viene sempre usata a partire dalle \acr{glibc} 2.9.}
-il cui prototipo è:
+  \acr{glibc} 2.8 che non supporta l'argomento \texttt{flags}, ed una seconda
+  versione, \func{signalfd4}, introdotta con il kernel 2.6.27 e che è quella
+  che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un
+  argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della
+  maschera dei segnali, il cui valore viene impostato automaticamente dalle
+  \acr{glibc}.}  il cui prototipo è:
 \begin{prototype}{sys/signalfd.h} 
   {int signalfd(int fd, const sigset\_t *mask, int flags)}
 
-  Crea o modifica un file descriptor pet la ricezione dei segnali. 
+  Crea o modifica un file descriptor per la ricezione dei segnali. 
 
   \bodydesc{La funzione restituisce un numero di file descriptor in caso di
     successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
@@ -1945,7 +1947,7 @@ il cui prototipo 
   \item[\errcode{EBADF}] il valore \param{fd} non indica un file descriptor.
   \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
     con \func{signalfd} o il valore di \param{flags} non è valido.
-  \item[\errcode{ENOMEN}] non c'è memoria sufficiente per creare un nuovo file
+  \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
     descriptor di \func{signalfd}.
   \item[\errcode{ENODEV}] il kernel non può montare internamente il
     dispositivo per la gestione anonima degli inode associati al file
@@ -1968,19 +1970,21 @@ con \param{fd}, in caso di errore invece verr
 L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere
 specificato tramite l'argomento \param{mask}. Questo deve essere passato come
 puntatore ad una maschera di segnali creata con l'uso delle apposite macro già
-illustrate in sez.~\ref{sec:sig_sigset}; la maschera deve indicare su quali
+illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali
 segnali si intende operare con \func{signalfd}; l'elenco può essere modificato
 con una successiva chiamata a \func{signalfd}. Dato che \const{SIGKILL} e
 \const{SIGSTOP} non possono essere intercettati (e non prevedono neanche la
-possibilità di un gestore) un loro inserimento nella maschera verrà ignorato,
-senza generare errori.
+possibilità di un gestore) un loro inserimento nella maschera verrà ignorato
+senza generare errori. 
 
 L'argomento \param{flags} consente di impostare direttamente in fase di
 creazione due flag per il file descriptor analoghi a quelli che si possono
 impostare con una creazione ordinaria con \func{open}, evitando una
 impostazione successiva con \func{fcntl}.\footnote{questo è un argomento
   aggiuntivo, introdotto con la versione fornita a partire dal kernel 2.6.27,
-  per kernel precedenti il valore deve essere nullo.}
+  per kernel precedenti il valore deve essere nullo.} L'argomento deve essere
+specificato come maschera binaria dei valori riportati in
+tab.~\ref{tab:signalfd_flags}.
 
 \begin{table}[htb]
   \centering
@@ -2002,18 +2006,71 @@ impostazione successiva con \func{fcntl}.\footnote{questo 
   \label{tab:signalfd_flags}
 \end{table}
 
+Si tenga presente che la chiamata a \func{signalfd} non disabilita la gestione
+ordinaria dei segnali indicati da \param{mask}; questa, se si vuole effettuare
+la ricezione tramite il file descriptor, dovrà essere disabilitata
+esplicitamente bloccando gli stessi segnali con \func{sigprocmask}, altrimenti
+verranno comunque eseguite le azioni di default (o un eventuale gestore
+installato in precedenza).\footnote{il blocco non ha invece nessun effetto sul
+  file descriptor restituito da \func{signalfd}, dal quale sarà possibile
+  pertanto ricevere qualunque segnale, anche se questo risultasse bloccato.}
+Si tenga presente inoltre che la lettura di una struttura
+\struct{signalfd\_siginfo} relativa ad un segnale pendente è equivalente alla
+esecuzione di un gestore, vale a dire che una volta letta il segnale non sarà
+più pendente e non potrà essere ricevuto, qualora si ripristino le normali
+condizioni di gestione, né da un gestore né dalla funzione \func{sigwaitinfo}.
+
+Come anticipato, essendo questo lo scopo principale della nuova interfaccia,
+il file descriptor può essere tenuto sotto osservazione tramite le funzioni
+dell'\textit{I/O multiplexing} (vale a dire con le solite \func{select},
+\func{poll} e \funcd{epoll\_wait}), e risulterà accessibile in lettura quando
+uno o più dei segnali indicati tramite \param{mask} sarà pendente.
+
+La funzione può essere chiamata più volte dallo stesso processo, consentendo
+così di tenere sotto osservazione segnali diversi tramite file descriptor
+diversi. Inoltre è anche possibile tenere sotto osservazione lo stesso segnale
+con più file descriptor, anche se la pratica è sconsigliata; in tal caso la
+ricezione del segnale potrà essere effettuata con una lettura da uno qualunque
+dei file descriptor a cui è associato, ma questa potrà essere eseguita
+soltanto una volta.\footnote{questo significa che tutti i file descriptor su
+  cui è presente lo stesso segnale risulteranno pronti in lettura per le
+  funzioni di \textit{I/O multiplexing}, ma una volta eseguita la lettura su
+  uno di essi il segnale sarà considerato ricevuto ed i relativi dati non
+  saranno più disponibili sugli altri file descriptor, che (a meno di una
+  ulteriore occorrenza del segnale nel frattempo) di non saranno più pronti.}
+
+Quando il file descriptor per la ricezione dei segnali non serve più potrà
+essere chiuso con \func{close} liberando tutte le risorse da esso allocate. In
+tal caso qualora vi fossero segnali pendenti questi resteranno tali, e
+potranno essere ricevuti normalmente una volta che si rimuova il blocco
+imposto con \func{sigprocmask}.
+
+Oltre che con le funzioni dell'\textit{I/O multiplexing} l'uso del file
+descriptor restituito da \func{signalfd} cerca di seguire la semantica di un
+sistema unix-like anche con altre \textit{system call}; in particolare esso
+resta aperto (come ogni altro file descriptor) attraverso una chiamata ad
+\func{exec}, a meno che non lo si sia creato con il flag di
+\const{SFD\_CLOEXEC} o si sia successivamente impostato il
+\textit{close-on-exec} con \func{fcntl}. Questo comportamento corrisponde
+anche alla ordinaria semantica relativa ai segnali bloccati, che restano
+pendenti attraverso una \func{exec}.
+
+Analogamente il file descriptor resta sempre disponibile attraverso una
+\func{fork} per il processo figlio, che ne riceve una copia; in tal caso però
+il figlio potrà leggere dallo stesso soltanto i dati relativi ai segnali
+ricevuti da lui stesso. Nel caso di \textit{thread} viene nuovamente seguita
+la semantica ordinaria dei segnali, che prevede che un singolo \textit{thread}
+possa ricevere dal file descriptor solo le notifiche di segnali inviati
+direttamente a lui o al processo in generale, e non quelli relativi ad altri
+\textit{thread} appartenenti allo stesso processo.
+
 L'interfaccia fornita da \func{signalfd} prevede che la ricezione dei segnali
 sia eseguita leggendo i dati relativi ai segnali pendenti dal file descriptor
-restituito dalla funzione con una normalissima \func{read}. Questi dati
-vengono scritti sul buffer indicato come secondo argomento di \func{read} in
-forma di una sequenza di una o più strutture \struct{signalfd\_siginfo} (la
-cui definizione si è riportata in fig.~\ref{fig:signalfd_siginfo}) a seconda
-sia della dimensione del buffer che del numero di segnali pendenti. Per questo
-motivo il buffer deve essere almeno di dimensione pari a quella di
-\struct{signalfd\_siginfo}, qualora sia di dimensione maggiore potranno essere
-letti in unica soluzione i dati relativi ad eventuali più segnali pendenti,
-fino al numero massimo di strutture \struct{signalfd\_siginfo} che possono
-rientrare nel buffer.
+restituito dalla funzione con una normalissima \func{read}.  Qualora non vi
+siano segnali pendenti la \func{read} si bloccherà a meno di non aver
+impostato la modalità di I/O non bloccante sul file descriptor, o direttamente
+in fase di creazione con il flag \const{SFD\_NONBLOCK}, o in un momento
+successivo con \func{fcntl}.  
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -2026,11 +2083,39 @@ rientrare nel buffer.
   \label{fig:signalfd_siginfo}
 \end{figure}
 
-Si tenga presente che lettura di una struttura \struct{signalfd\_siginfo}
-relativa ad un segnale pendente è equivalente alla esecuzione di un gestore,
-vale a dire che una volta letta il segnale non sarà più pendente e non potrà
-essere ricevuto, qualora si ripristino le normali condizioni di gestione, né
-da un gestore né dalla funzione \func{sigwaitinfo}. 
+I dati letti dal file descriptor vengono scritti sul buffer indicato come
+secondo argomento di \func{read} nella forma di una sequenza di una o più
+strutture \struct{signalfd\_siginfo} (la cui definizione si è riportata in
+fig.~\ref{fig:signalfd_siginfo}) a seconda sia della dimensione del buffer che
+del numero di segnali pendenti. Per questo motivo il buffer deve essere almeno
+di dimensione pari a quella di \struct{signalfd\_siginfo}, qualora sia di
+dimensione maggiore potranno essere letti in unica soluzione i dati relativi
+ad eventuali più segnali pendenti, fino al numero massimo di strutture
+\struct{signalfd\_siginfo} che possono rientrare nel buffer.
+
+Il contenuto di \struct{signalfd\_siginfo} ricalca da vicino quella della
+analoga struttura \struct{siginfo\_t} (illustrata in
+fig.~\ref{fig:sig_siginfo_t}) usata dall'interfaccia ordinaria dei segnali, e
+restituisce dati simili. Come per \struct{siginfo\_t} i campi che vengono
+avvalorati dipendono dal tipo di segnale e ricalcano i valori che abbiamo già
+illustrato in sez.~\ref{sec:sig_sigaction}.\footnote{si tenga presente però
+  che per un bug i kernel fino al 2.6.25 non avvalorano correttamente i campi
+  \var{ssi\_ptr} e \var{ssi_int} per segnali inviati con \func{sigqueue}.}
+
+Lo stesso paradigma di notifica tramite file descriptor usato per i segnali è
+stato adottato anche per i timer; in questo caso, rispetto a quanto visto in
+sez.~\ref{sec:sig_timer_adv}, la scadenza di un timer potrà essere letta da un
+file descriptor, senza dover ricorrere ad altri meccanismi come un segnale o
+un \textit{thread} di notifica. Di nuovo questo ha il vantaggio di poter
+utilizzare le funzioni dell'\textit{I/O multiplexing} per attendere allo
+stesso tempo la disponibilità di dati o la ricezione di un segnale
+qualunque.\footnote{in realtà per questo sarebbe già sufficiente
+  \func{signalfd} per ricevere i segnali associati ai timer, ma la nuova
+  interfaccia semplifica notevolmente la gestione.}
+
+Le funzioni di questa interfaccia riprendono da vicino 
+
+
 
 % TODO trattare qui eventfd, timerfd introdotte con il 2.6.22 
 % timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25
@@ -5053,7 +5138,7 @@ livello di kernel.
 % LocalWords:  only ETXTBSY DENYWRITE ENODEV filesystem EPERM EXEC noexec table
 % LocalWords:  ENFILE lenght segment violation SIGSEGV FIXED msync munmap copy
 % LocalWords:  DoS Denial Service EXECUTABLE NORESERVE LOCKED swapping stack fs
-% LocalWords:  GROWSDOWN ANON POPULATE prefaulting SIGBUS fifo VME fork old
+% LocalWords:  GROWSDOWN ANON POPULATE prefaulting SIGBUS fifo VME fork old SFD
 % LocalWords:  exec atime ctime mtime mprotect addr EACCESS mremap address new
 % LocalWords:  long MAYMOVE realloc VMA virtual Ingo Molnar remap pages pgoff
 % LocalWords:  dall' fault cache linker prelink advisory discrectionary lock fl
@@ -5076,8 +5161,9 @@ livello di kernel.
 % LocalWords:  SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG
 % LocalWords:  POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs
 % LocalWords:  DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS
-% LocalWords:  MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat
-% LocalWords:  conditions sigwait
+% LocalWords:  MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat union
+% LocalWords:  conditions sigwait CLOEXEC signalfd sizemask SIGKILL SIGSTOP ssi
+% LocalWords:  sigwaitinfo FifoReporter Windows ptr sigqueue
 
 
 %%% Local Variables: