Revisione di epoll in vista dell'esempio di FifoReporter.c
authorSimone Piccardi <piccardi@gnulinux.it>
Tue, 4 Jan 2011 00:56:15 +0000 (00:56 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Tue, 4 Jan 2011 00:56:15 +0000 (00:56 +0000)
fileadv.tex
fileunix.tex
ipc.tex
sources/FifoReporter.c [new file with mode: 0644]

index 9bd8e161bb3e2a0735f92d5dc13305d03fb4f154..fdf294698312d9d9f307039e954d642d88b27569 100644 (file)
@@ -1494,36 +1494,59 @@ La prima versione \textit{epoll} prevedeva l'apertura di uno speciale file di
 dispositivo, \texttt{/dev/epoll}, per ottenere un file descriptor da
 utilizzare con le funzioni dell'interfaccia,\footnote{il backporting
   dell'interfaccia per il kernel 2.4, non ufficiale, utilizza sempre questo
-  file.} ma poi si è passati all'uso una apposita \textit{system call}.  Il
-primo passo per usare l'interfaccia di \textit{epoll} è pertanto quello di
-chiamare la funzione \funcd{epoll\_create}, il cui prototipo è:
-\begin{prototype}{sys/epoll.h}
-  {int epoll\_create(int size)}
+  file.} ma poi si è passati all'uso di apposite \textit{system call}.  Il
+primo passo per usare l'interfaccia di \textit{epoll} è pertanto quello
+ottenere detto file descriptor chiamando una delle funzioni
+\funcd{epoll\_create} e \funcd{epoll\_create1},\footnote{l'interfaccia di
+  \textit{epoll} è stata inserita nel kernel a partire dalla versione 2.5.44,
+  ed il supporto è stato aggiunto alle \acr{glibc} 2.3.2.} i cui prototipi
+sono:
+\begin{functions}
+  \headdecl{sys/epoll.h}
+
+  \funcdecl{int epoll\_create(int size)}
+  \funcdecl{int epoll\_create1(int flags)}
   
   Apre un file descriptor per \textit{epoll}.
   
-  \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
-    $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \bodydesc{Le funzioni restituiscono un file descriptor per \textit{epoll} in
+    caso di successo, o $-1$ in caso di errore, nel qual caso \var{errno}
+    assumerà uno dei valori:
   \begin{errlist}
   \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
-    positivo.
+    positivo o non valido per \param{flags}.
   \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
     nel sistema.
+  \item[\errcode{EMFILE}] si è raggiunto il limite sul numero massimo di
+    istanze di \textit{epoll} per utente stabilito da
+    \procfile{/proc/sys/fs/epoll/max\_user\_instances}.
   \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
     l'istanza.
   \end{errlist}
 }
-\end{prototype}
+\end{functions}
 
-La funzione restituisce un file descriptor speciale,\footnote{esso non è
-  associato a nessun file su disco, inoltre a differenza dei normali file
-  descriptor non può essere inviato ad un altro processo attraverso un socket
-  locale (vedi sez.~\ref{sec:sock_fd_passing}).} detto anche \textit{epoll
-  descriptor}, che viene associato alla infrastruttura utilizzata dal kernel
-per gestire la notifica degli eventi; l'argomento \param{size} serve a dare
-l'indicazione del numero di file descriptor che si vorranno tenere sotto
-controllo, ma costituisce solo un suggerimento per semplificare l'allocazione
-di risorse sufficienti, non un valore massimo.
+Entrambe le funzioni restituiscono un file descriptor speciale,\footnote{esso
+  non è associato a nessun file su disco, inoltre a differenza dei normali
+  file descriptor non può essere inviato ad un altro processo attraverso un
+  socket locale (vedi sez.~\ref{sec:sock_fd_passing}).} detto anche
+\textit{epoll descriptor}, che viene associato alla infrastruttura utilizzata
+dal kernel per gestire la notifica degli eventi. Nel caso di
+\func{epoll\_create} l'argomento \param{size} serviva a dare l'indicazione del
+numero di file descriptor che si vorranno tenere sotto controllo, e costituiva
+solo un suggerimento per semplificare l'allocazione di risorse sufficienti,
+non un valore massimo.\footnote{ma a partire dal kernel 2.6.8 esso viene
+  totalmente ignorato e l'allocazione è sempre dinamica.}
+
+La seconda versione della funzione, \func{epoll\_create1} è stata
+introdotta\footnote{è disponibile solo a partire dal kernel 2.6.27.} come
+estensione della precedente, per poter passare dei flag di controllo come
+maschera binaria in fase di creazione del file descriptor. Al momento l'unico
+valore legale per \param{flags} (a parte lo zero) è \const{EPOLL\_CLOEXEC},
+che consente di impostare in maniera atomica sul file descriptor il flag di
+\itindex{close-on-exec} \textit{close-on-exec} (si veda il significato di
+\const{O\_CLOEXEC} in tab.~\ref{tab:file_open_flags}), senza che sia
+necessaria una successiva chiamata a \func{fcntl}.
 
 Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
 indicare quali file descriptor mettere sotto osservazione e quali operazioni
@@ -1549,6 +1572,9 @@ controllare, per questo si deve usare la seconda funzione dell'interfaccia,
   \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel gestire
     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
+    \procfile{/proc/sys/fs/epoll/max\_user\_watches}.
   \end{errlist}
 }
 \end{prototype}
@@ -1597,8 +1623,10 @@ di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
 indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
 sotto controllo.  L'argomento viene ignorato con l'operazione
 \const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
-  che questo fosse un puntatore valido, anche se poi veniva ignorato, a
-  partire dal 2.6.9 si può specificare anche un valore \texttt{NULL}.}
+  che questo fosse un puntatore valido, anche se poi veniva ignorato; a
+  partire dal 2.6.9 si può specificare anche un valore \texttt{NULL} ma se si
+  vuole mantenere la compatibilità con le versioni precedenti occorre usare un
+  puntatore valido.}
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1624,7 +1652,8 @@ deve essere specificato come OR aritmetico delle costanti riportate in
 tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, serve ad indicare a
 quale file descriptor si intende fare riferimento, ed in astratto può
 contenere un valore qualsiasi che permetta di identificarlo, di norma comunque
-si usa come valore lo stesso \param{fd}.
+si usa come valore lo stesso argomento \param{fd}, che ha un significato
+immediato.
 
 \begin{table}[htb]
   \centering
@@ -1641,7 +1670,8 @@ si usa come valore lo stesso \param{fd}.
     \const{EPOLLRDHUP}  & L'altro capo di un socket di tipo
                           \const{SOCK\_STREAM} (vedi sez.~\ref{sec:sock_type})
                           ha chiuso la connessione o il capo in scrittura
-                          della stessa (vedi sez.~\ref{sec:TCP_shutdown}).\\
+                          della stessa (vedi
+                          sez.~\ref{sec:TCP_shutdown}).\footnotemark\\
     \const{EPOLLPRI}    & Ci sono \itindex{out-of-band} dati urgenti
                           disponibili in lettura (analogo di
                           \const{POLLPRI}); questa condizione viene comunque
@@ -1651,7 +1681,9 @@ si usa come valore lo stesso \param{fd}.
                           (analogo di \const{POLLERR}); questa condizione
                           viene comunque riportata in uscita, e non è
                           necessaria impostarla in ingresso.\\
-    \const{EPOLLHUP}    & Si è verificata una condizione di hung-up.\\
+    \const{EPOLLHUP}    & Si è verificata una condizione di hung-up; questa
+                          condizione viene comunque riportata in uscita, e non
+                          è necessaria impostarla in ingresso.\\
     \const{EPOLLET}     & Imposta la notifica in modalità \textit{edge
                             triggered} per il file descriptor associato.\\ 
     \const{EPOLLONESHOT}& Imposta la modalità \textit{one-shot} per il file
@@ -1663,7 +1695,12 @@ si usa come valore lo stesso \param{fd}.
   \label{tab:epoll_events}
 \end{table}
 
-\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.2.}
+\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.17,
+  ed è utile per riconoscere la chiusura di una connessione dall'altro capo
+  quando si lavora in modalità \textit{edge triggered}.}
+
+\footnotetext[48]{questa modalità è disponibile solo a partire dal kernel
+  2.6.2.}
 
 Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è
 l'insieme dei file descriptor da tenere sotto controllo tramite un certo
@@ -1781,9 +1818,10 @@ restituiti meno dati di quelli richiesti.
 
 Come già per \func{select} e \func{poll} anche per l'interfaccia di
 \textit{epoll} si pone il problema di gestire l'attesa di segnali e di dati
-contemporaneamente, per far questo di nuovo è necessaria una variante della
-funzione di attesa che consenta di reimpostare all'uscita una maschera di
-segnali, analoga alle precedenti estensioni \func{pselect} e \func{ppoll} di
+contemporaneamente per le osservazioni fatte in sez.~\ref{sec:file_select},
+per fare questo di nuovo è necessaria una variante della funzione di attesa
+che consenta di reimpostare all'uscita una maschera di segnali, analoga alle
+estensioni \func{pselect} e \func{ppoll} che abbiamo visto in precedenza per
 \func{select} e \func{poll}; in questo caso la funzione si chiama
 \funcd{epoll\_pwait}\footnote{la funziona è stata introdotta a partire dal
   kernel 2.6.19, ed è come tutta l'interfaccia di \textit{epoll}, specifica di
index fe6f46dbb922eabacac01848e961c4aa3ccae32e..0bcc5fec26c7ed736bc39e6734e09c6ab2204d95 100644 (file)
@@ -350,7 +350,8 @@ ritorno il file descriptor con il valore pi
                          alle dimensioni dei blocchi del filesystem; per il
                          kernel 2.6 basta che siano allineati a multipli di 512
                          byte.\\
-    \const{O\_CLOEXEC} & Attiva la modalità di \textit{close-on-exec} (vedi
+    \const{O\_CLOEXEC} & Attiva la modalità di \itindex{close-on-exec}
+                         \textit{close-on-exec} (vedi 
                          sez.~\ref{sec:file_sharing} e
                          \ref{sec:file_fcntl}).\footnotemark\\  
     \hline
@@ -1067,7 +1068,7 @@ sull'altro (dato che quello che viene modificato 
 della \textit{file table} a cui entrambi fanno riferimento). L'unica
 differenza fra due file descriptor duplicati è che ciascuno avrà il suo
 \textit{file descriptor flag}; a questo proposito va specificato che nel caso
-di \func{dup} il flag di \textit{close-on-exec}\itindex{close-on-exec} (vedi
+di \func{dup} il flag di \textit{close-on-exec} \itindex{close-on-exec} (vedi
 sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}) viene sempre cancellato
 nella copia.
 
diff --git a/ipc.tex b/ipc.tex
index d22c3ba381bcab3aadcce723e927fef2a43c28f0..91c6ff352dd5c67943014b4b149ac8e0a21dba32 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -4449,10 +4449,10 @@ corrente.
   \label{fig:ipc_posix_sem_shm_message_server_handler}
 \end{figure}
 
-Prima della stampa del messaggio invece si deve aquisire il semaforo
+Prima della stampa del messaggio invece si deve acquisire il semaforo
 (\texttt{\small 31--34}) per evitare accessi concorrenti alla stringa da parte
 del programma di modifica. Una volta eseguita la stampa (\texttt{\small 41})
-il semforo dovrà essere rilasciato (\texttt{\small 42--45}). Il passo finale
+il semaforo dovrà essere rilasciato (\texttt{\small 42--45}). Il passo finale
 (\texttt{\small 46}) è attendere per un secondo prima di eseguire da capo il
 ciclo. 
 
@@ -4461,7 +4461,7 @@ il break da tastiera (\texttt{C-c}), che corrisponde all'invio del segnale
 \const{SIGINT}, per il quale si è installato (\texttt{\small 10}) una
 opportuna funzione di gestione, riportata in
 fig.~\ref{fig:ipc_posix_sem_shm_message_server_handler}. La funzione è molto
-semplice e richiame le funzioni di rimozione sia per il segmento di memoria
+semplice e richiama le funzioni di rimozione sia per il segmento di memoria
 condivisa che per il semaforo, garantendo così che possa essere riaperto
 ex-novo senza errori in un futuro riutilizzo del comando.
 
@@ -4510,9 +4510,9 @@ eseguite da \file{message\_getter}). Terminato il tempo di attesa si rilascer
 (\texttt{\small 29--32}) il semaforo per poi uscire.
 
 Per verificare il funzionamento dei programmi occorrerà lanciare per primo
-\file{message\_getter}\footnote{lanciando per primo \file{message\_setter}
-  darà luogo ad un errore, non essendo stati creati il semaforo ed il segmento
-  di memoria condivisa.} che inizierà a stampare una volta al secondo il
+\file{message\_getter}\footnote{lanciare per primo \file{message\_setter} darà
+  luogo ad un errore, non essendo stati creati il semaforo ed il segmento di
+  memoria condivisa.} che inizierà a stampare una volta al secondo il
 contenuto del messaggio ed i suoi dati, con qualcosa del tipo:
 \begin{Verbatim}
 piccardi@hain:~/gapil/sources$  ./message_getter messaggio
@@ -4610,17 +4610,20 @@ testo alla terminazione di quest'ultimo.
 % LocalWords:  SHARED ANONYMOUS thread patch names strace system call userid Di
 % LocalWords:  groupid Michal Wronski Krzysztof Benedyczak wrona posix mqueue
 % LocalWords:  lmqueue gcc mount mqd name oflag attr maxmsg msgsize receive ptr
-% LocalWords:  send WRONLY NONBLOCK close mqdes EBADF getattr setattr mqstat
+% LocalWords:  send WRONLY NONBLOCK close mqdes EBADF getattr setattr mqstat to
 % LocalWords:  omqstat curmsgs flags timedsend len prio timespec abs EMSGSIZE
 % LocalWords:  ETIMEDOUT timedreceive getaddr notify sigevent notification l'I
 % LocalWords:  EBUSY sigev SIGNAL signo value sigval siginfo all'userid MESGQ
 % LocalWords:  Konstantin Knizhnik futex tmpfs ramfs cache shared swap CONFIG
 % LocalWords:  lrt blocks PAGECACHE TRUNC CLOEXEC mmap ftruncate munmap FindShm
-% LocalWords:  CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS
+% LocalWords:  CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS has
 % LocalWords:  ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait
-% LocalWords:  process getvalue sval execve pshared ENOSYS heap PAGE destroy
+% LocalWords:  process getvalue sval execve pshared ENOSYS heap PAGE destroy it
 % LocalWords:  xffffffff Arrays owner perms Queues used bytes messages device
-% LocalWords:  Cannot find such Segments getter Signal MSGMAXSIZE
+% LocalWords:  Cannot find such Segments getter Signal MSGMAXSIZE been stable
+% LocalWords:  for now it's break Berlin sources Let's an accidental feature
+% LocalWords:  Larry Wall Escape the Hell William ipctestid Identifier segment
+% LocalWords:  violation dell'I SIGINT setter Fri Dec Sleeping seconds
 
 
 %%% Local Variables: 
diff --git a/sources/FifoReporter.c b/sources/FifoReporter.c
new file mode 100644 (file)
index 0000000..631c56e
--- /dev/null
@@ -0,0 +1,140 @@
+/* FifoReporter.c
+ * 
+ * Copyright (C) 2011 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Program reporterd
+ * FIFO, signal, event and alarm reporter
+ * an example program for I/O multiplexing with signalfd and Co.
+ *
+ * Author: Simone Piccardi
+ * Jan. 2011
+ *
+ * Usage: reporterd -h give all info
+ *
+ ****************************************************************/
+/* 
+ * Include needed headers
+ */
+#include <sys/types.h>   /* primitive system data types */
+#include <sys/stat.h>    /* file characteristics constants and functions */
+#include <unistd.h>      /* unix standard library */
+#include <stdio.h>       /* standard I/O library */
+#include <stdlib.h>     /* C standard library */
+#include <string.h>     /* C strings library */
+#include <errno.h>      /* error definitions and routines */
+#include <signal.h>     /* signal constants, types and functions */
+#include <fcntl.h>      /* file control functions */
+#include <sys/epoll.h>   /* Linux epoll interface */
+
+#include "macros.h"
+#include "Gapil.h"
+
+/* Subroutines declaration */
+void usage(void);
+
+/* default name for the input fifo */
+char *fifoname = "/tmp/reporter.fifo";
+
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int i, t = 1;
+    char buffer[4096];
+    int fifofd, epfd;
+    struct epoll_event epev;
+    int nread;
+    /*
+     * Input section: decode parameters passed in the calling 
+     * Use getopt function
+     */
+    opterr = 0;                                     /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "ht:f:")) != -1) {
+       switch (i) {
+       /* 
+        * Handling options 
+        */ 
+       case 'h':  
+           printf("Wrong -h option use\n");
+           usage();
+           return(0);
+           break;
+       case 'f':
+           fifoname = optarg;
+           break;
+       case 't':
+           t = strtol(optarg, NULL, 10);
+           break;
+       case '?':                                    /* unrecognized options */
+           printf("Unrecognized options -%c\n",optopt);
+           usage();
+       default:                                       /* should not reached */
+           usage();
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          Options processing completed
+     *
+     *               Main code beginning
+     * 
+     * ***********************************************************/
+    /* 
+     * Initial setup 
+     */
+    if (mkfifo(fifoname, 0622)) {  // create well known fifo if does't exist 
+       if (errno!=EEXIST) {
+           perror("Cannot create well known fifo");
+           exit(1);
+       }
+    }
+    if ((fifo = open(fifoname, O_RDONLY)) < 0) {    // open fifo
+       perror("Cannot open read only well known fifo");
+       exit(1);
+    }
+    epfd = epoll_create(5);       // initialize epoll
+    if (epfd < 0) {
+        perror("Failing on epoll_create");
+        exit(1);
+    }
+    /* Main body: loop over requests */
+    while (1) {
+       
+    }
+    debug("Exiting for unknown reasons\n");
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+    printf("Elementary fortune server\n");
+    printf("Usage:\n");
+    printf("  fortuned [-h] [-f] -n XXX \n");
+    printf("  -h   print this help\n");
+    printf("  -t filename   set fifo file\n");
+    printf("  -n XXX        set pool depth\n");
+    exit(1);
+}
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+    debug("Terminated by %s\n", strsignal(signo));
+    unlink(fifoname);
+    exit(0);
+}