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 è
-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
@@ -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
-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à
@@ -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}.}
 
+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 è
-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
-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
-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}.}
 
-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
-  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)}
 
@@ -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
-  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
@@ -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}.}
 
-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
-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{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,
@@ -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}
-  \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}
-  ed inoltre \errval{EMFILE} e \errval{ENFILE}.  
 }
 \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
@@ -2254,31 +2452,6 @@ ottenute leggendo in maniera ordinaria il file descriptor con una \func{read},
 %       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}
 
@@ -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:  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:  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: 
index dcf3901ad5d29d3b134b718d549f9787d4955bb3..7a0cb2ea5fc70a08957fa28a9845640b64fc484d 100644 (file)
@@ -17,6 +17,7 @@
                        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);
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, 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
index 81ce5914f6911491e1b65549c9f7ab0e8bf1e13f..8692ff7605835954eef66cc46557d68adfa04a43 100644 (file)
@@ -104,6 +104,10 @@ lettura restituirà i dati urgenti.
 \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}
 
index 4e35cba367bb4d816cabf19b67f1aef8932482b8..0ce8c37df0313cb39d07267077e424558c7adee1 100644 (file)
@@ -165,6 +165,7 @@ int main(int argc, char *argv[])
     /* 
      * 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");
@@ -185,7 +186,9 @@ int main(int argc, char *argv[])
                        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
+                       printf("SIGINT means exit\n");
                        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 */
-    while ( (i = getopt(argc, argv, "h")) != -1) {
+    while ( (i = getopt(argc, argv, "hs:")) != -1) {
         switch (i) {
         /* 
          * Handling options 
@@ -72,7 +72,7 @@ int main(int argc, char *argv[])
             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 */
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");
-    printf("  testfopen [-h] file mode \n");
+    printf("  testsignalfd [-h] file mode \n");
     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 <time.h>
+#include <time.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;
+    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;
-    uint64_t expirated;
+    uint64_t expired;
     /*
      * 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 
@@ -74,6 +75,18 @@ int main(int argc, char *argv[])
            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();
@@ -95,13 +108,14 @@ int main(int argc, char *argv[])
     }
     /* 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");
     }
+    printf("Timer interval %i sec, timer time %i sec\n", wait, interval);
     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 */
-    //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;
 }
 /*
@@ -149,6 +166,8 @@ void usage(void) {
     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);