Materiale scritto in treno
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 4 Apr 2011 10:02:30 +0000 (10:02 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 4 Apr 2011 10:02:30 +0000 (10:02 +0000)
fileadv.tex
prochand.tex
sources/FifoReporter.c
sources/test_timerfdfork.c

index b1cb34858bf049e33861bfe8b8071bb5f9c20aa5..312c36fe1162368cfe548bc08ee417c2d6919741 100644 (file)
@@ -2114,16 +2114,16 @@ timer.\footnote{in realtà per questo sarebbe già sufficiente \func{signalfd}
   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 di quelle
-introdotte da POSIX.1-2001, che abbiamo 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, che consente di creare un \textit{timer}, è \funcd{timerfd\_create},
-il cui prototipo è:
+Le funzioni di questa 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 è:
 \begin{prototype}{sys/timerfd.h} 
   {int timerfd\_create(int clockid, int flags)}
 
@@ -2180,18 +2180,71 @@ tab.~\ref{tab:timerfd_flags}.
   \label{tab:timerfd_flags}
 \end{table}
 
-In caso di successo la funzione restituisce un file descriptor che può essere
-usato per leggere le notifiche delle 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}
-(a meno che non si sia impostato il flag di \textit{close-on exex} con
-\const{TFD\_CLOEXEC}) e viene duplicato attraverso una \func{fork}, mantenendo
-il riferimento allo stesso \textit{timer}, così che anche il processo figlio
+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
+  \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
+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
+occorre \textsl{armarlo} impostandone un tempo di scadenza ed una eventuale
+periodicità di ripetizione, per farlo su usa la funzione omologa di
+\func{timer\_settime} per la nuova interfaccia; questa è
+\func{timerfd\_settime}; il suo prototipo è:
+\begin{prototype}{sys/timerfd.h} 
+  {int timerfd\_settime(int fd, int flags,
+                           const struct itimerspec *new_value,
+                           struct itimerspec *old_value)}
+
+  Crea un timer associato ad un file descriptor per la notifica. 
+
+  \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{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.
+  \end{errlist}
+  ed inoltre \errval{EMFILE} e \errval{ENFILE}.  
+}
+\end{prototype}
+
+
+
+
+.\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.}
+
+
+
+
+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 
+
+che può essere
+usato per leggere le notifiche delle scadenze dei timer. Queste possono essere
+ottenute leggendo in maniera ordinaria il file descriptor con una \func{read}, 
 
 
-per cui
-anche un processo figlio potrà ricevere informazioni sulla scadenza di un
-timer attraverso
 
 
 % TODO trattare qui eventfd, timerfd introdotte con il 2.6.22 
index 07af836fe7c3e99189156b9b7b701353db1b8de3..76b68e2d4b8595471ab95a2648f2b7ba0c5964f3 100644 (file)
@@ -659,8 +659,9 @@ Le differenze fra padre e figlio dopo la \func{fork} invece sono:\footnote{a
 \item i \textit{lock} sui file (vedi sez.~\ref{sec:file_locking}) e sulla
   memoria (vedi sez.~\ref{sec:proc_mem_lock}), che non vengono ereditati dal
   figlio;
-\item gli allarmi (vedi sez.~\ref{sec:sig_alarm_abort}) ed i segnali pendenti
-  (vedi sez.~\ref{sec:sig_gen_beha}), che per il figlio vengono cancellati.
+\item gli allarmi, i timer (vedi sez.~\ref{sec:sig_alarm_abort}) ed i segnali
+  pendenti (vedi sez.~\ref{sec:sig_gen_beha}), che per il figlio vengono
+  cancellati.
 \item le operazioni di I/O asincrono in corso (vedi
   sez.~\ref{sec:file_asyncronous_io}) che non vengono ereditate dal figlio;
 \item gli aggiustamenti fatti dal padre ai semafori con \func{semop} (vedi
index eecdb1233bfd4dfa3fccd148b8c4d028967a5a2e..4e35cba367bb4d816cabf19b67f1aef8932482b8 100644 (file)
@@ -169,7 +169,7 @@ int main(int argc, char *argv[])
         if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0) 
            die("error on epoll_wait");
        debug("Got %i events\n", n);
-       /* loop on eppol events */
+       /* loop on epoll events */
        for (i=0; i<n; i++) {    
            if (events[i].data.fd == sigfd) {             // if signalfd ready 
                printf("Signal received:\n");
index 04fad750973f0726300a3e987fc530d5fc59e7fb..34ceaedd1b317c0d29bf31397a2a7e5718ad54f0 100644 (file)
 #include <stdio.h>      /* standard I/O library */
 #include <string.h>      /* C strings library */
 #include <sys/timerfd.h> /* timerfd */
+#include <sys/epoll.h>   /* Linux epoll interface */
 // #include <time.h>
 
+#include "macros.h"
+#include "Gapil.h"
+
 /* Help printing routine */
 void usage(void);
+void die(char *);
+
+#define MAX_EPOLL_EV 10
 
 int main(int argc, char *argv[])
 {
 /* 
  * Variables definition  
  */
-    int i, fd;
+    int i, n, nread, fd, epfd;
+    pid_t pid;
+    struct epoll_event epev, events[MAX_EPOLL_EV];
     struct itimerspec expiring;
+    uint64_t expirated;
     /*
      * Input section: decode command line parameters 
      * Use getopt function
@@ -83,15 +93,53 @@ int main(int argc, char *argv[])
        printf("From %d arguments, removed %d options\n", argc, optind);
        usage();
     }
-
+    /* 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;
-    if (timerfd_settime(fd, 0, expiring, NULL)) {
-       perror("Cannot set timer");
+    if (timerfd_settime(fd, 0, &expiring, NULL)) {
+       die("Cannot set timer");
     }
+    pid = fork();
+    /* epoll setup */
+    if ((epfd=epoll_create(5)) < 0)
+       die("Failing on epoll_create");
+    epev.data.fd = fd;
+    epev.events = EPOLLIN;
+    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");
+                   }
+               }
+           }
+       }
+    // }
     return 0;
 }
 /*
@@ -105,4 +153,11 @@ void usage(void) {
     
     exit(1);
 }
+/*
+ * Print error message and exit routine
+ */
+void die(char * mess) {
+    perror(mess);
+    exit(-1);
+}