Ritocchi vari ai sorgenti, commento di FifoReporter e trattazione di
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 19 Jun 2011 19:35:32 +0000 (19:35 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 19 Jun 2011 19:35:32 +0000 (19:35 +0000)
timerfd_settime

AUTHORS
fileadv.tex
listati/FifoReporter-main.c
signal.tex
sockadv.tex
sources/FifoReporter.c
sources/tee.c
sources/test_signalfd.c
sources/test_timerfdfork.c

diff --git a/AUTHORS b/AUTHORS
index 4deb647c43c3de67b26bea1cacaed6d198a54e47..f063764632504edef4b90cd28eac751bc1ce273a 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1 @@
-Simone Piccardi <piccardi@softwarelibero.it>
+Simone Piccardi <piccardi@gnulinux.it> http://piccardi.gnulinux.it
index c38a396892f79c152fa679bf374c1e40b458cc35..38f01fcf3d77be4a850bf90f374e33c2d29a1a67 100644 (file)
@@ -547,7 +547,7 @@ Per fare qualche esempio sul \textit{file locking} si è scritto un programma ch
 permette di bloccare una sezione di un file usando la semantica POSIX, o un
 intero file usando la semantica BSD; in fig.~\ref{fig:file_flock_code} è
 riportata il corpo principale del codice del programma, (il testo completo è
 permette di bloccare una sezione di un file usando la semantica POSIX, o un
 intero file usando la semantica BSD; in fig.~\ref{fig:file_flock_code} è
 riportata il corpo principale del codice del programma, (il testo completo è
-allegato nella directory dei sorgenti).
+allegato nella directory dei sorgenti, nel file \texttt{Flock.c}).
 
 La sezione relativa alla gestione delle opzioni al solito si è omessa, come la
 funzione che stampa le istruzioni per l'uso del programma, essa si cura di
 
 La sezione relativa alla gestione delle opzioni al solito si è omessa, come la
 funzione che stampa le istruzioni per l'uso del programma, essa si cura di
@@ -1907,7 +1907,7 @@ segnale o si aspetta che un file descriptor sia accessibile e nessuna delle
 rispettive funzioni consente di fare contemporaneamente entrambe le cose.
 
 Per risolvere questo problema nello sviluppo del kernel si è pensato di
 rispettive funzioni consente di fare contemporaneamente entrambe le cose.
 
 Per risolvere questo problema nello sviluppo del kernel si è pensato di
-introdurre un meccanismo alternativo alla notifica dei segnali (esteso anche
+introdurre un meccanismo alternativo per la notifica dei segnali (esteso anche
 ad altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per
 cui tutto è un file, consentisse di eseguire la notifica con l'uso di
 opportuni file descriptor.\footnote{ovviamente si tratta di una funzionalità
 ad altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per
 cui tutto è un file, consentisse di eseguire la notifica con l'uso di
 opportuni file descriptor.\footnote{ovviamente si tratta di una funzionalità
@@ -2102,28 +2102,198 @@ 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}.}
 
   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}.}
 
+Come esempio di questa nuova interfaccia ed anche come esempio di applicazione
+della interfaccia di \itindex{epoll} \textit{epoll}, si è scritto un programma
+elementare che stampi sullo standard output sia quanto viene scritto da terzi
+su una \textit{named fifo}, che l'avvenuta ricezione di alcuni segnali.  Il
+codice completo si trova al solito nei sorgenti allegati alla guida (nel file
+\texttt{FifoReporter.c}).
+
+In fig.~\ref{fig:fiforeporter_code_init} si è riportata la parte iniziale del
+programma in cui vengono effettuate le varie inizializzazioni necessarie per
+l'uso di \itindex{epoll} \textit{epoll} e \func{signalfd}, a partire
+(\texttt{\small 12--16}) dalla definizione delle varie variabili e strutture
+necessarie. Al solito si è tralasciata la parte dedicata alla decodifica delle
+opzioni che consentono ad esempio di cambiare il nome del file associato alla
+fifo.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/FifoReporter-init.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione di inizializzazione del codice del programma
+    \file{FifoReporter.c}.}
+  \label{fig:fiforeporter_code_init}
+\end{figure}
+
+Il primo passo (\texttt{\small 19--20}) è la crezione di un file descriptor
+\texttt{epfd} di \itindex{epoll} \textit{epoll} con \func{epoll\_create} che è
+quello che useremo per il controllo degli altri.  É poi necessario
+disabilitare la ricezione dei segnali (nel caso \const{SIGINT},
+\const{SIGQUIT} e \const{SIGTERM}) per i quali si vuole la notifica tramite
+file descriptor. Per questo prima li si inseriscono (\texttt{\small 22--25}) in
+una maschera di segnali \texttt{sigmask} che useremo con (\texttt{\small 26})
+\func{sigprocmask} per disabilitarli.  Con la stessa maschera si potrà per
+passare all'uso (\texttt{\small 28--29}) di \func{signalfd} per abilitare la
+notifica sul file descriptor \var{sigfd}. Questo poi (\texttt{\small 30--33})
+dovrà essere aggiunto con \func{epoll\_ctl} all'elenco di file descriptor
+controllati con \texttt{epfd}.
+
+Occorrerà infine (\texttt{\small 35--38}) creare la \textit{named fifo} se
+questa non esiste ed aprirla per la lettura (\texttt{\small 39--40}); una
+volta fatto questo sarà necessario aggiungere il relativo file descriptor
+(\var{fifofd}) a quelli osservati da \itindex{epoll} \textit{epoll} in maniera
+del tutto analoga a quanto fatto con quello relativo alla notifica dei
+segnali.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/FifoReporter-main.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Ciclo principale del codice del programma \file{FifoReporter.c}.}
+  \label{fig:fiforeporter_code_body}
+\end{figure}
+
+Una volta completata l'inizializzazione verrà eseguito indefinitamente il
+ciclo principale del programma (\texttt{\small 2--45}) che si è riportato in
+fig.~\ref{fig:fiforeporter_code_body}, fintanto che questo non riceva un
+segnale di \texttt{SIGINT} (ad esempio con la pressione di \texttt{C-c}). Il
+ciclo prevede che si attenda (\texttt{\small 2--3}) la presenza di un file
+descriptor pronto in lettura con \func{epoll\_wait},\footnote{si ricordi che
+  entrambi i file descriptor \var{fifofd} e \var{sigfd} sono stati posti in
+  osservazioni per eventi di tipo \const{EPOLLIN}.} che si bloccherà fintanto
+che non siano stati scritti dati sulla fifo o che non sia arrivato un
+segnale.\footnote{per semplificare il codice non si è trattato il caso in cui
+  \func{epoll\_wait} viene interrotta da un segnale, assumendo che tutti
+  quelli che possano interessare siano stati predisposti per la notifica
+  tramite file descriptor, per gli altri si otterrà semplicemente l'uscita dal
+  programma.}
+
+Anche se in questo caso i file descriptor pronti possono essere al più due, si
+è comunque adottato un approccio generico in cui questi verranno letti
+all'interno di un opportuno ciclo (\texttt{\small 5--44}) sul numero
+restituito da \func{epoll\_wait}, esaminando i risultati presenti nel vettore
+\var{events} all'interno di una catena di condizionali alternativi sul valore
+del file descriptor riconosciuto come pronto.\footnote{controllando cioè a
+  quale dei due file descriptor possibili corrisponde il campo relativo,
+  \var{events[i].data.fd}.}
+
+Il primo condizionale (\texttt{\small 6--24}) è relativo al caso che si sia
+ricevuto un segnale e che il file descriptor pronto corrisponda
+(\texttt{\small 6}) a \var{sigfd}. Dato che in generale si possono ricevere
+anche notifiche relativi a più di un singolo segnale, si è scelto di leggere
+una struttura \const{signalfd\_siginfo} alla volta, eseguendo la lettura
+all'interno di un ciclo (\texttt{\small 8--24}) che prosegue fintanto che vi
+siano dati da leggere.
+
+Per questo ad ogni lettura si esamina (\texttt{\small 9--14}) se il valore di
+ritorno della funzione \func{read} è negativo, uscendo dal programma
+(\texttt{\small 11}) in caso di errore reale, o terminando il ciclo
+(\texttt{\small 13}) con un \texttt{break} qualora si ottenga un errore di
+\errcode{EAGAIN} per via dell'esaurimento dei dati.\footnote{si ricordi come
+  sia la fifo che il file descriptor per i segnali siano stati aperti in
+  modalità non-bloccante, come previsto per l’\textit{I/O multiplexing},
+  pertanto ci si aspetta di ricevere un errore di \errcode{EAGAIN} quando non
+  vi saranno più dati da leggere.}
+
+In presenza di dati invece il programma proseguirà l'esecuzione stampando
+(\texttt{\small 19--20}) il nome del segnale ottenuto all'interno della
+struttura \const{signalfd\_siginfo} letta in \var{siginf}\footnote{per la
+  stampa si è usato il vettore \var{sig\_names} a ciascun elemento del quale
+  corrisponde il nome del segnale avente il numero corrispondente, la cui
+  definizione si è omessa dal codice di fig.~\ref{fig:fiforeporter_code_init}
+  per brevità.} ed il \textit{pid} del processo da cui lo ha ricevuto; inoltre
+(\texttt{\small 21--24}) si controllerà anche se il segnale ricevuto è
+\var{SIGINT}, che si è preso come segnale da utilizzare per la terminazione
+del programma, che verrà eseguita dopo aver rimosso il file della \textit{name
+  fifo}.
+Il secondo condizionale (\texttt{\small 26--39}) è invece relativo al caso in
+cui ci siano dati pronti in lettura sulla fifo e che il file descriptor pronto
+corrisponda (\texttt{\small 26}) a \var{fifofd}. Di nuovo si effettueranno le
+letture in un ciclo (\texttt{\small 28--39}) ripetendole fin tanto che la
+funzione \func{read} non resituisce un errore di \errcode{EAGAIN}
+(\texttt{\small 29--35}).\footnote{il procedimento è lo stesso adottato per il
+  file descriptor associato al segnale, in cui si esce dal programma in caso
+  di errore reale, in questo caso però alla fine dei dati prima di uscire si
+  stampa anche (\texttt{\small 32}) un messaggio di chiusura.} Se invece vi
+sono dati validi letti dalla fifo si inserirà (\texttt{\small 36}) una
+terminazione di stringa sul buffer e si stamperà il tutto (\texttt{\small
+  37--38}) sullo \textit{standard output}. L'ultimo condizionale
+(\texttt{\small 40--44}) è semplicemente una condizione di cattura per una
+eventualità che comunque non dovrebbe mai verificarsi, e che porta alla uscita
+dal programma con una opportuna segnalazione di errore.
+
+A questo punto si potrà eseguire il comando lanciandolo su un terminale, ed
+osservarne le reazioni agli eventi generati da un altro terminale; lanciando
+il programma otterremo qualcosa del tipo:
+\begin{Verbatim}
+piccardi@hain:~/gapil/sources$ ./a.out 
+FifoReporter starting, pid 4568
+\end{Verbatim}
+%$
+e scrivendo qualcosa sull'altro terminale con:
+\begin{Verbatim}
+root@hain:~# echo prova > /tmp/reporter.fifo  
+\end{Verbatim}
+si otterrà:
+\begin{Verbatim}
+Message from fifo:
+prova
+end message
+\end{Verbatim}
+mentre inviando un segnale:
+\begin{Verbatim}
+root@hain:~# kill 4568
+\end{Verbatim}
+si avrà:
+\begin{Verbatim}
+Signal received:
+Got SIGTERM       
+From pid 3361
+\end{Verbatim}
+ed infine premendo \texttt{C-\bslash} sul terminale in cui è in esecuzione si
+vedrà:
+\begin{Verbatim}
+^\Signal received:
+Got SIGQUIT       
+From pid 0
+\end{Verbatim}
+e si potrà far uscire il programma con \texttt{C-c} ottenendo:
+\begin{Verbatim}
+^CSignal received:
+Got SIGINT        
+From pid 0
+SIGINT means exit
+\end{Verbatim}
+
+
 Lo stesso paradigma di notifica tramite file descriptor usato per i segnali è
 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
+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
 sez.~\ref{sec:sig_timer_adv}, la scadenza di un timer potrà essere letta da un
-file descriptor, senza dover ricorrere ad altri meccanismi di notifica come un
+file descriptor senza dover ricorrere ad altri meccanismi di notifica come un
 segnale o un \textit{thread}. Di nuovo questo ha il vantaggio di poter
 utilizzare le funzioni dell'\textit{I/O multiplexing} per attendere allo
 segnale o un \textit{thread}. 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 scadenza di un
+stesso tempo la disponibilità di dati o la ricezione della scadenza di un
 timer.\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 e consente di fare tutto con una sola
   \textit{system call}.}
 
 timer.\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 e consente di fare tutto con una sola
   \textit{system call}.}
 
-Le funzioni di questa interfaccia ricalcano da vicino la struttura delle
+Le funzioni di questa nuova interfaccia ricalcano da vicino la struttura delle
 analoghe versioni ordinarie introdotte con lo standard POSIX.1-2001, che
 abbiamo già illustrato in sez.~\ref{sec:sig_timer_adv}.\footnote{questa
   interfaccia è stata introdotta in forma considerata difettosa con il kernel
   2.6.22, per cui è stata immediatamente tolta nel successivo 2.6.23 e
   reintrodotta in una forma considerata adeguata nel kernel 2.6.25, il
   supporto nelle \acr{glibc} è stato introdotto a partire dalla versione
 analoghe versioni ordinarie introdotte con lo standard POSIX.1-2001, che
 abbiamo già illustrato in sez.~\ref{sec:sig_timer_adv}.\footnote{questa
   interfaccia è stata introdotta in forma considerata difettosa con il kernel
   2.6.22, per cui è stata immediatamente tolta nel successivo 2.6.23 e
   reintrodotta in una forma considerata adeguata nel kernel 2.6.25, il
   supporto nelle \acr{glibc} è stato introdotto a partire dalla versione
-  2.8.6, la versione del kernel 2.6.22 non è supportata e non deve essere
-  usata.} La prima funzione prevista, quella che consente di creare un
-\textit{timer}, è \funcd{timerfd\_create}, il cui prototipo è:
+  2.8.6, la versione del kernel 2.6.22, presente solo su questo kernel, non è
+  supportata e non deve essere usata.} La prima funzione prevista, quella che
+consente di creare un timer, è \funcd{timerfd\_create}, il cui prototipo è:
 \begin{prototype}{sys/timerfd.h} 
   {int timerfd\_create(int clockid, int flags)}
 
 \begin{prototype}{sys/timerfd.h} 
   {int timerfd\_create(int clockid, int flags)}
 
@@ -2184,7 +2354,7 @@ In caso di successo la funzione restituisce un file descriptor sul quale
 verranno notificate le scadenze dei timer. Come per quelli restituiti da
 \func{signalfd} anche questo file descriptor segue la semantica dei sistemi
 unix-like, in particolare resta aperto attraverso una \func{exec},\footnote{a
 verranno notificate le scadenze dei timer. Come per quelli restituiti da
 \func{signalfd} anche questo file descriptor segue la semantica dei sistemi
 unix-like, in particolare resta aperto attraverso una \func{exec},\footnote{a
-  meno che non si sia impostato il flag di \textit{close-on exex} con
+  meno che non si sia impostato il flag di \textit{close-on exec} con
   \const{TFD\_CLOEXEC}.} e viene duplicato attraverso una \func{fork}; questa
 ultima caratteristica comporta però che anche il figlio può utilizzare i dati
 di un timer creato nel padre, a differenza di quanto avviene invece con i
   \const{TFD\_CLOEXEC}.} e viene duplicato attraverso una \func{fork}; questa
 ultima caratteristica comporta però che anche il figlio può utilizzare i dati
 di un timer creato nel padre, a differenza di quanto avviene invece con i
@@ -2192,11 +2362,11 @@ timer impostati con le funzioni ordinarie.\footnote{si ricordi infatti che,
   come illustrato in sez.~\ref{sec:proc_fork}, allarmi, timer e segnali
   pendenti nel padre vengono cancellati per il figlio dopo una \func{fork}.}
 
   come illustrato in sez.~\ref{sec:proc_fork}, allarmi, timer e segnali
   pendenti nel padre vengono cancellati per il figlio dopo una \func{fork}.}
 
-Una volta creato il timer con \funcd{timerfd\_create} per poterlo utilizzare
+Una volta creato il timer con \func{timerfd\_create} per poterlo utilizzare
 occorre \textsl{armarlo} impostandone un tempo di scadenza ed una eventuale
 occorre \textsl{armarlo} impostandone un tempo di scadenza ed una eventuale
-periodicità di ripetizione, per farlo su usa la funzione omologa di
+periodicità di ripetizione, per farlo si usa la funzione omologa di
 \func{timer\_settime} per la nuova interfaccia; questa è
 \func{timer\_settime} per la nuova interfaccia; questa è
-\func{timerfd\_settime}; il suo prototipo è:
+\funcd{timerfd\_settime} ed il suo prototipo è:
 \begin{prototype}{sys/timerfd.h} 
   {int timerfd\_settime(int fd, int flags,
                            const struct itimerspec *new\_value,
 \begin{prototype}{sys/timerfd.h} 
   {int timerfd\_settime(int fd, int flags,
                            const struct itimerspec *new\_value,
@@ -2208,37 +2378,65 @@ periodicità di ripetizione, per farlo su usa la funzione omologa di
     successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
     dei valori:
   \begin{errlist}
     successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
     dei valori:
   \begin{errlist}
-  \item[\errcode{EINVAL}] l'argomento \param{clockid} non è
-    \const{CLOCK\_MONOTONIC} o \const{CLOCK\_REALTIME}, o
-    l'argomento \param{flag} non è valido, o è diverso da zero per kernel
-    precedenti il 2.6.27.
-  \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
-    descriptor.
+  \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+    descriptor. 
+  \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+    con \func{timerfd\_create}, o i valori di \param{flag} o dei campi
+    \var{tv\_nsec} in \param{new\_value} non sono validi.
+  \item[\errcode{EFAULT}] o \param{new\_value} o \param{old\_value} non sono
+    puntatori validi.
   \end{errlist}
   \end{errlist}
-  ed inoltre \errval{EMFILE} e \errval{ENFILE}.  
 }
 \end{prototype}
 
 }
 \end{prototype}
 
+In questo caso occorre indicare su quale timer si intende operare specificando
+come primo argomento il file descriptor ad esso associato, che deve essere
+stato ottenuto da una precedente chiamata a \func{timerfd\_create}. I restanti
+argomenti sono del tutto analoghi a quelli della omologa funzione
+\func{timer\_settime}, e prevedono l'uso di strutture \struct{itimerspec}
+(vedi fig.~\ref{fig:struct_itimerspec}) per le indicazioni di temporizzazione.
+
+I valori ed il significato di questi argomenti sono gli stessi che sono già
+stati illustrati in dettaglio in sez.~\ref{sec:sig_timer_adv} e non staremo a
+ripetere quanto detto in quell'occasione;\footnote{per brevità si ricordi che
+  con \param{new\_value.it\_value} si indica la prima scadenza del timer e
+  con \param{new\_value.it\_interval} la sua periodicità.}  l'unica differenza
+riguarda l'argomento \param{flags} che serve sempre ad indicare se il tempo di
+scadenza del timer è da considerarsi relativo o assoluto rispetto al valore
+corrente dell'orologio associato al timer, ma che in questo caso ha come
+valori possibili rispettivamente soltanto $0$ e
+\const{TFD\_TIMER\_ABSTIME}.\footnote{anche questo valore, che è l'analogo di
+  \const{TIMER\_ABSTIME} è l'unico attualmente possibile per \param{flags}.}
+
+L'ultima funzione prevista dalla nuova interfaccia è \funcd{timerfd\_gettime},
+che è l'analoga di \func{timer\_gettime}, il suo prototipo è:
+\begin{prototype}{sys/timerfd.h} 
+  {int timerfd\_gettime(int fd, struct itimerspec *curr\_value)}
 
 
+  Crea un timer associato ad un file descriptor per la notifica. 
 
 
-
-.\footnote{si otterranno in entrambi i casi gli stessi
-  risultati, il file descriptor risulterà pronto in lettura e in entrambi i
-  processi si potranno leggere il numero di scadenze.}
+  \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
+    dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+    descriptor. 
+  \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+    con \func{timerfd\_create}.
+  \item[\errcode{EFAULT}] o \param{curr\_value} non è un puntatore valido.
+  \end{errlist}
+}
+\end{prototype}
 
 
 
 
 
 
 
 
-Questo infatti diverrà pronto in
-lettura per tutte le varie funzioni dell'I/O multiplexing in presenza di una o
-più scadenze del timer ad esso associato. 
 
 
+Questo infatti diverrà pronto in lettura per tutte le varie funzioni dell'I/O
+multiplexing in presenza di una o più scadenze del timer ad esso associato.
 
 
-Inoltre sarà possibile ottenere il
-numero di volte che il timer è scaduto dalla ultima impostazione 
+Inoltre sarà possibile ottenere il numero di volte che il timer è scaduto
+dalla ultima impostazione
 
 che può essere
 usato per leggere le notifiche delle scadenze dei timer. Queste possono essere
 
 che può essere
 usato per leggere le notifiche delle scadenze dei timer. Queste possono essere
@@ -2254,31 +2452,6 @@ ottenute leggendo in maniera ordinaria il file descriptor con una \func{read},
 %       http://lwn.net/Articles/267331/
 
 
 %       http://lwn.net/Articles/267331/
 
 
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/FifoReporter-init.c}
-  \end{minipage} 
-  \normalsize 
-  \caption{Sezione di inizializzazione del codice del programma
-    \file{FifoReporter.c}.}
-  \label{fig:fiforeporter_code}
-\end{figure}
-
-
-
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/FifoReporter-main.c}
-  \end{minipage} 
-  \normalsize 
-  \caption{Ciclo principale del codice del programma \file{FifoReporter.c}.}
-  \label{fig:fiforeporter_code}
-\end{figure}
-
-
-
 \section{L'accesso \textsl{asincrono} ai file}
 \label{sec:file_asyncronous_access}
 
 \section{L'accesso \textsl{asincrono} ai file}
 \label{sec:file_asyncronous_access}
 
@@ -5289,11 +5462,13 @@ livello di kernel.
 % LocalWords:  Jens Anxboe vmsplice seek ESPIPE GIFT TCP CORK MSG splicecp nr
 % LocalWords:  nwrite segs patch readahead posix fadvise TC advice FADV NORMAL
 % LocalWords:  SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG
 % LocalWords:  Jens Anxboe vmsplice seek ESPIPE GIFT TCP CORK MSG splicecp nr
 % LocalWords:  nwrite segs patch readahead posix fadvise TC advice FADV NORMAL
 % LocalWords:  SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG
-% LocalWords:  POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs
+% LocalWords:  POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs it
 % LocalWords:  DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS
 % LocalWords:  MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat union
 % LocalWords:  conditions sigwait CLOEXEC signalfd sizemask SIGKILL SIGSTOP ssi
 % LocalWords:  DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS
 % 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
+% LocalWords:  sigwaitinfo FifoReporter Windows ptr sigqueue named timerfd TFD
+% LocalWords:  clockid CLOCK MONOTONIC REALTIME itimerspec interval
+% LocalWords:  ABSTIME gettime
 
 
 %%% Local Variables: 
 
 
 %%% Local Variables: 
index dcf3901ad5d29d3b134b718d549f9787d4955bb3..7a0cb2ea5fc70a08957fa28a9845640b64fc484d 100644 (file)
@@ -17,6 +17,7 @@
                        continue;
                    }
                    printf("Got %s\n", sig_names[siginf.ssi_signo]);
                        continue;
                    }
                    printf("Got %s\n", sig_names[siginf.ssi_signo]);
+                   printf("From pid %i\n", siginf.ssi_pid);
                    if(siginf.ssi_signo == SIGINT) { // SIGINT stop program
                        unlink(fifoname);
                        exit(0);
                    if(siginf.ssi_signo == SIGINT) { // SIGINT stop program
                        unlink(fifoname);
                        exit(0);
index 400f689bded9ec25c821e43ed85522f779161e76..65e5b6e4281abb0be6c5cedcae8919a446076369 100644 (file)
@@ -2696,7 +2696,9 @@ tab.~\ref{tab:sig_timer_clockid_types}.
 
 % TODO: aggiungere le estensioni introdotte con il 2.6.38, verificandone il
 % funzionamento, vedi http://lwn.net/Articles/429595/
 
 % TODO: aggiungere le estensioni introdotte con il 2.6.38, verificandone il
 % funzionamento, vedi http://lwn.net/Articles/429595/
-% TODO, dal 2.6.39 anche CLOCK_BOOTTIME, vedi http://lwn.net/Articles/432757/
+% TODO, dal 2.6.39 anche CLOCK_BOOTTIME_ALARM e CLOCK_BOOTTIME_ALARM, vedi
+% http://lwn.net/Articles/429925/
+
 
 Per poter utilizzare queste funzionalità le \acr{glibc} richiedono che la
 macro \macro{\_POSIX\_C\_SOURCE} sia definita ad un valore maggiore o uguale
 
 Per poter utilizzare queste funzionalità le \acr{glibc} richiedono che la
 macro \macro{\_POSIX\_C\_SOURCE} sia definita ad un valore maggiore o uguale
index 81ce5914f6911491e1b65549c9f7ab0e8bf1e13f..8692ff7605835954eef66cc46557d68adfa04a43 100644 (file)
@@ -104,6 +104,10 @@ lettura restituirà i dati urgenti.
 \itindend{out-of-band} 
 
 
 \itindend{out-of-band} 
 
 
+% TODO trattare sendmmsg aggiunta con il kernel 3.0.
+% e gli ICMP socket, vedi  http://lwn.net/Articles/420799/
+
+
 \section{L'uso dell'I/O non bloccante}
 \label{sec:sock_noblok_IO}
 
 \section{L'uso dell'I/O non bloccante}
 \label{sec:sock_noblok_IO}
 
index 4e35cba367bb4d816cabf19b67f1aef8932482b8..0ce8c37df0313cb39d07267077e424558c7adee1 100644 (file)
@@ -165,6 +165,7 @@ int main(int argc, char *argv[])
     /* 
      * Main body: wait something to report 
      */
     /* 
      * Main body: wait something to report 
      */
+    printf("FifoReporter starting, pid %i\n", getpid());
     while (1) {
         if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0) 
            die("error on epoll_wait");
     while (1) {
         if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0) 
            die("error on epoll_wait");
@@ -185,7 +186,9 @@ int main(int argc, char *argv[])
                        continue;
                    }
                    printf("Got %s\n", sig_names[siginf.ssi_signo]);
                        continue;
                    }
                    printf("Got %s\n", sig_names[siginf.ssi_signo]);
+                   printf("From pid %i\n", siginf.ssi_pid);
                    if(siginf.ssi_signo == SIGINT) {      // SIGINT is exit
                    if(siginf.ssi_signo == SIGINT) {      // SIGINT is exit
+                       printf("SIGINT means exit\n");
                        unlink(fifoname);
                        exit(0);
                    }
                        unlink(fifoname);
                        exit(0);
                    }
index d876ad998c31cd7a9f7381de8ef976f38497f959..8c09ae35bae08e4ee7118a6be8a9f25ca7621e26 100644 (file)
@@ -62,7 +62,7 @@ int main(int argc, char *argv[])
      * Use getopt function
      */
     opterr = 0;  /* don't want writing to stderr */
      * Use getopt function
      */
     opterr = 0;  /* don't want writing to stderr */
-    while ( (i = getopt(argc, argv, "h")) != -1) {
+    while ( (i = getopt(argc, argv, "hs:")) != -1) {
         switch (i) {
         /* 
          * Handling options 
         switch (i) {
         /* 
          * Handling options 
@@ -72,7 +72,7 @@ int main(int argc, char *argv[])
             usage();
             return -1;
             break;
             usage();
             return -1;
             break;
-        case 's':      /* take wait time for childen */
+        case 's':      /* buffer size */
             size = strtol(optarg, NULL, 10);    /* convert input */
             break;
        case '?':      /* unrecognized options */
             size = strtol(optarg, NULL, 10);    /* convert input */
             break;
        case '?':      /* unrecognized options */
index 48a0935dc9e4730c5f63bbee2307a2f8618f2450..a31cf0b27a847f7b9f324461736ebbaaccac5797 100644 (file)
@@ -128,7 +128,7 @@ int main(int argc, char *argv[])
 void usage(void) {
     printf("Program testsignalfd : test signalfd on close \n");
     printf("Usage:\n");
 void usage(void) {
     printf("Program testsignalfd : test signalfd on close \n");
     printf("Usage:\n");
-    printf("  testfopen [-h] file mode \n");
+    printf("  testsignalfd [-h] file mode \n");
     printf("  -h          print this help\n");
     
     exit(1);
     printf("  -h          print this help\n");
     
     exit(1);
index 34ceaedd1b317c0d29bf31397a2a7e5718ad54f0..19d37b680ae7494b7b89749c0271bc4b8151e222 100644 (file)
@@ -38,7 +38,7 @@
 #include <string.h>      /* C strings library */
 #include <sys/timerfd.h> /* timerfd */
 #include <sys/epoll.h>   /* Linux epoll interface */
 #include <string.h>      /* C strings library */
 #include <sys/timerfd.h> /* timerfd */
 #include <sys/epoll.h>   /* Linux epoll interface */
-// #include <time.h>
+#include <time.h>
 
 #include "macros.h"
 #include "Gapil.h"
 
 #include "macros.h"
 #include "Gapil.h"
@@ -55,16 +55,17 @@ int main(int argc, char *argv[])
  * Variables definition  
  */
     int i, n, nread, fd, epfd;
  * Variables definition  
  */
     int i, n, nread, fd, epfd;
+    int wait=5, interval=1, nswait=0, nsinter=0;   // timer default
     pid_t pid;
     struct epoll_event epev, events[MAX_EPOLL_EV];
     struct itimerspec expiring;
     pid_t pid;
     struct epoll_event epev, events[MAX_EPOLL_EV];
     struct itimerspec expiring;
-    uint64_t expirated;
+    uint64_t expired;
     /*
      * Input section: decode command line parameters 
      * Use getopt function
      */
     opterr = 0;         /* don't want writing to stderr */
     /*
      * Input section: decode command line parameters 
      * Use getopt function
      */
     opterr = 0;         /* don't want writing to stderr */
-    while ( (i = getopt(argc, argv, "h")) != -1) {
+    while ( (i = getopt(argc, argv, "ht:i:w:n:")) != -1) {
        switch (i) {
        /* 
         * Handling options 
        switch (i) {
        /* 
         * Handling options 
@@ -74,6 +75,18 @@ int main(int argc, char *argv[])
            usage();
            return -1;
            break;
            usage();
            return -1;
            break;
+        case 'i':      /* timer interval */
+            interval = strtol(optarg, NULL, 10);    /* convert input */
+            break;
+        case 't':      /* timer expiring */
+            wait = strtol(optarg, NULL, 10);    /* convert input */
+            break;
+        case 'n':      /* timer interval in ns */
+            nsinter = strtol(optarg, NULL, 10);    /* convert input */
+            break;
+        case 'w':      /* timer expiring in ns */
+            nswait = strtol(optarg, NULL, 10);    /* convert input */
+            break;
        case '?':   /* unrecognized options */
            printf("Unrecognized options -%c\n",optopt);
            usage();
        case '?':   /* unrecognized options */
            printf("Unrecognized options -%c\n",optopt);
            usage();
@@ -95,13 +108,14 @@ int main(int argc, char *argv[])
     }
     /* timerfd setup */
     fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
     }
     /* timerfd setup */
     fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
-    expiring.it_interval.tv_sec=1;
-    expiring.it_interval.tv_nsec=0;
-    expiring.it_value.tv_sec=5;
-    expiring.it_value.tv_nsec=0;
+    expiring.it_interval.tv_sec=interval;
+    expiring.it_interval.tv_nsec=nsinter;
+    expiring.it_value.tv_sec=wait;
+    expiring.it_value.tv_nsec=nswait;
     if (timerfd_settime(fd, 0, &expiring, NULL)) {
        die("Cannot set timer");
     }
     if (timerfd_settime(fd, 0, &expiring, NULL)) {
        die("Cannot set timer");
     }
+    printf("Timer interval %i sec, timer time %i sec\n", wait, interval);
     pid = fork();
     /* epoll setup */
     if ((epfd=epoll_create(5)) < 0)
     pid = fork();
     /* epoll setup */
     if ((epfd=epoll_create(5)) < 0)
@@ -111,35 +125,38 @@ int main(int argc, char *argv[])
     if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &epev))
        die("Failing in epoll_ctl"); 
     /* main loop */
     if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &epev))
        die("Failing in epoll_ctl"); 
     /* main loop */
-    //while (1) {
-        if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0) 
-           die("error on epoll_wait");
-       debug("Got %i events\n", n);
-       /* loop on epoll events */
-       for (i=0; i<n; i++) {
-           if (events[i].data.fd == fd) {             // if timer expired
-               printf("Timer expired:\n");
-               while(nread=read(fd, &expirated, sizeof(expirated))) {
-                   if (nread < 0) {
-                       if (errno != EAGAIN) 
-                           die("signalfd read error");
-                       else 
-                           break;
-                   }
-                   if (nread != sizeof(expirated)) {
-                       printf("Error on timer data read, '\n");
-                       continue;
-                   }
-                   printf("Expired %llu times\n", expirated);
-                   if (pid == 0) {
-                       printf("in child\n");
-                   } else {
-                       printf("in father\n");
+    while (1) {
+        while (n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) { 
+           if (n < 0) {
+               if (errno != EAGAIN) 
+                   die("error on epoll_wait");
+               else 
+                   continue;
+           } else {
+               printf("Got %i events, pid %i, time %i\n", n, pid, time(NULL));
+               /* loop on epoll events */
+               for (i=0; i<n; i++) {
+                   if (events[i].data.fd == fd) {   // if timer expired
+                       printf("Timer expired in pid %i:\n", pid);
+                       while(nread=read(fd, &expired, sizeof(expired))) {
+                           if (nread < 0) {
+                               if (errno != EAGAIN) 
+                                   die("signalfd read error");
+                               else 
+                                   break;
+                           }
+                           if (nread != sizeof(expired)) {
+                               printf("Error on timer data read, '\n");
+                               continue;
+                           }
+                           printf("Expired %llu times in pid %i\n", 
+                                  expired, pid);
+                       }
                    }
                }
            }
        }
                    }
                }
            }
        }
-    // }
+    }
     return 0;
 }
 /*
     return 0;
 }
 /*
@@ -149,6 +166,8 @@ void usage(void) {
     printf("Program testtimerfdfork : test timerfd across fork  \n");
     printf("Usage:\n");
     printf("  testtimerfdfork [-h]  \n");
     printf("Program testtimerfdfork : test timerfd across fork  \n");
     printf("Usage:\n");
     printf("  testtimerfdfork [-h]  \n");
+    printf("  -i sec      interval for repetition\n");
+    printf("  -t sec      time to wait to expire\n");
     printf("  -h          print this help\n");
     
     exit(1);
     printf("  -h          print this help\n");
     
     exit(1);