From: Simone Piccardi Date: Thu, 20 Jan 2011 22:55:25 +0000 (+0000) Subject: Sistemato programma FifoReporter.c X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=c15153bee6a516df24ebb4e7bf33ffa7ce91496d Sistemato programma FifoReporter.c --- diff --git a/fileadv.tex b/fileadv.tex index fdf2946..ba81956 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1,6 +1,6 @@ %% fileadv.tex %% -%% Copyright (C) 2000-2010 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2011 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -1474,7 +1474,7 @@ vengano notificati solo i file descriptor che hanno subito una transizione da \textit{edge triggered} nel caso del precedente esempio il file descriptor diventato pronto da cui si sono letti solo 1000 byte non verrà nuovamente notificato come pronto, nonostante siano ancora disponibili in lettura 1000 -byte. Solo una volta che si saranno esauriti tutti i byte disponibili, e che +byte. Solo una volta che si saranno esauriti tutti i dati disponibili, e che il file descriptor sia tornato non essere pronto, si potrà ricevere una ulteriore notifica qualora ritornasse pronto. @@ -1649,11 +1649,14 @@ definizione Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo 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 argomento \param{fd}, che ha un significato -immediato. +tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, è una \ctyp{union} +che serve a identificare il file descriptor a cui si intende fare riferimento, +ed in astratto può contenere un valore qualsiasi (specificabile in diverse +forme) che ne permetta una indicazione univoca. Il modo più comune di usarlo +però è quello in cui si specifica il terzo argomento di \func{epoll\_ctl} +nella forma \var{event.data.fd}, assegnando come valore di questo campo lo +stesso valore dell'argomento \param{fd}, cosa che permette una immediata +identificazione del file descriptor. \begin{table}[htb] \centering @@ -2013,6 +2016,16 @@ di dimensione maggiore potranno essere letti in unica soluzione % http://lwn.net/Articles/245533/ % http://lwn.net/Articles/267331/ +\begin{figure}[!phtb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/FifoReporter.c} + \end{minipage} + \normalsize + \caption{Sezione principale del codice del programma \file{FifoReporter.c}.} + \label{fig:fiforeporter_code} +\end{figure} + \section{L'accesso \textsl{asincrono} ai file} diff --git a/listati/FifoReporter-init.c b/listati/FifoReporter-init.c new file mode 100644 index 0000000..e46342a --- /dev/null +++ b/listati/FifoReporter-init.c @@ -0,0 +1,53 @@ +... +#include /* Linux epoll interface */ +#include /* Linux signalfd interface */ + +/* Subroutines declaration */ +void usage(void); +void die(char *); + +/* default name for the input fifo */ +char *fifoname = "/tmp/reporter.fifo"; + +#define MAX_EPOLL_EV 10 + +int main(int argc, char *argv[]) +{ +/* Variables definition */ + int i, n, nread, t = 10; + char buffer[4096]; + int fifofd, epfd, sigfd; + sigset_t sigmask; + struct epoll_event epev, events[MAX_EPOLL_EV]; + struct signalfd_siginfo siginf; + ... + /* Initial setup */ + if ((epfd=epoll_create(5)) < 0) // epoll init + die("Failing on epoll_create"); + /* Signal setup for signalfd and epoll use */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGINT); + sigaddset(&sigmask, SIGQUIT); + sigaddset(&sigmask, SIGTERM); + if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) // block signals + die("Failing in sigprocmask"); + if ((sigfd=signalfd(-1, &sigmask, SFD_NONBLOCK)) == -1) // take a signalfd + die("Failing in signalfd"); + epev.data.fd = sigfd; // add fd to epoll + epev.events = EPOLLIN; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &epev)) + die("Failing in signal epoll_ctl"); + /* Fifo setup for epoll use */ + if (mkfifo(fifoname, 0622)) { // create well known fifo if does't exist + if (errno!=EEXIST) + die("Cannot create well known fifo"); + } + if ((fifofd = open(fifoname, O_RDWR|O_NONBLOCK)) < 0) // open fifo + die("Cannot open read only well known fifo"); + epev.data.fd = fifofd; // add fifofd to epoll + epev.events = EPOLLIN; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fifofd, &epev)) + die("Failing in fifo epoll_ctl"); + /* Main body: wait something to report */ + ... +} diff --git a/listati/FifoReporter-main.c b/listati/FifoReporter-main.c new file mode 100644 index 0000000..dcf3901 --- /dev/null +++ b/listati/FifoReporter-main.c @@ -0,0 +1,45 @@ + /* Main body: wait something to report */ + while (1) { + if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0) + die("error on epoll_wait"); + for (i=0; i /* signal constants, types and functions */ #include /* file control functions */ #include /* Linux epoll interface */ +#include /* Linux signalfd interface */ #include "macros.h" #include "Gapil.h" /* Subroutines declaration */ void usage(void); +void die(char *); /* default name for the input fifo */ char *fifoname = "/tmp/reporter.fifo"; +#define MAX_EPOLL_EV 10 + int main(int argc, char *argv[]) { /* Variables definition */ - int i, nread, t = 1; + int i, n, nread, t = 10; char buffer[4096]; int fifofd, epfd, sigfd; - struct epoll_event epev; sigset_t sigmask; - char buffer[1024]; + struct epoll_event epev, events[MAX_EPOLL_EV]; + struct signalfd_siginfo siginf; + char *sig_names[] = { // signal name declaration from bits/signum.h + "------- ", /*0 Filler for signal names array */ + "SIGHUP ", /*1 Hangup (POSIX). */ + "SIGINT ", /*2 Interrupt (ANSI). */ + "SIGQUIT ", /*3 Quit (POSIX). */ + "SIGILL ", /*4 Illegal instruction (ANSI). */ + "SIGTRAP ", /*5 Trace trap (POSIX). */ + "SIGABRT ", /*6 Abort (ANSI). */ + "SIGBUS ", /*7 BUS error (4.2 BSD). */ + "SIGFPE ", /*8 Floating-point exception (ANSI). */ + "SIGKILL ", /*9 Kill, unblockable (POSIX). */ + "SIGUSR1 ", /*10 User-defined signal 1 (POSIX). */ + "SIGSEGV ", /*11 Segmentation violation (ANSI). */ + "SIGUSR2 ", /*12 User-defined signal 2 (POSIX). */ + "SIGPIPE ", /*13 Broken pipe (POSIX). */ + "SIGALRM ", /*14 Alarm clock (POSIX). */ + "SIGTERM ", /*15 Termination (ANSI). */ + "SIGSTKFLT ", /*16 Stack fault. */ + "SIGCHLD ", /*17 Child status has changed (POSIX). */ + "SIGCONT ", /*18 Continue (POSIX). */ + "SIGSTOP ", /*19 Stop, unblockable (POSIX). */ + "SIGTSTP ", /*20 Keyboard stop (POSIX). */ + "SIGTTIN ", /*21 Background read from tty (POSIX). */ + "SIGTTOU ", /*22 Background write to tty (POSIX). */ + "SIGURG ", /*23 Urgent condition on socket (4.2 BSD). */ + "SIGXCPU ", /*24 CPU limit exceeded (4.2 BSD). */ + "SIGXFSZ ", /*25 File size limit exceeded (4.2 BSD). */ + "SIGVTALRM ", /*26 Virtual alarm clock (4.2 BSD). */ + "SIGPROF ", /*27 Profiling alarm clock (4.2 BSD). */ + "SIGWINCH ", /*28 Window size change (4.3 BSD, Sun). */ + "SIGIO ", /*29 I/O now possible (4.2 BSD). */ + "SIGPWR ", /*30 Power failure restart (System V). */ + "SIGSYS " /*31 Bad system call. */ + }; /* * Input section: decode parameters passed in the calling * Use getopt function @@ -98,68 +136,82 @@ int main(int argc, char *argv[]) /* * 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); - } - } - epfd = epoll_create(5); // initialize epoll - if (epfd < 0) { - perror("Failing on epoll_create"); - exit(1); - } - if ((fifofd = open(fifoname, O_RDONLY|O_NONBLOCK)) < 0) { // open fifo - perror("Cannot open read only well known fifo"); - exit(1); - } - epev.data.fd = fifofd; /* add fifofd to epoll */ - epev.events = EPOLLIN; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, fifofd, &epev)) { - perror("Failing in epoll_ctl"); - exit(-1); - } + if ((epfd=epoll_create(5)) < 0) // epoll init + die("Failing on epoll_create"); + /* Signal setup for signalfd and epoll use */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGTERM); - // blocking signal treated by signalfd to avoid default action - if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) { - perror("Failing in sigprocmask"); - exit(1); - } - if ((sigfd=signalfd(-1, &sigmask, SFD_NONBLOCK)) == -1) { - perror("Failing in signalfd"); - exit(-1); - } - epev.data.fd = sigfd; /* add sigfd to epoll */ + if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) // block signals + die("Failing in signalfd"); + if ((sigfd=signalfd(-1, &sigmask, SFD_NONBLOCK)) == -1) // take a signalfd + die("Failing in signalfd"); + epev.data.fd = sigfd; // add fd to epoll epev.events = EPOLLIN; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &epev)) { - perror("Failing in epoll_ctl"); - exit(-1); + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &epev)) + die("Failing in signal epoll_ctl"); + /* Fifo setup for epoll use */ + if (mkfifo(fifoname, 0622)) { // create well known fifo if does't exist + if (errno!=EEXIST) + die("Cannot create well known fifo"); } - - /* Main body: loop over requests */ + if ((fifofd = open(fifoname, O_RDWR|O_NONBLOCK)) < 0) // open fifo + die("Cannot open read only well known fifo"); + epev.data.fd = fifofd; // add fd to epoll + epev.events = EPOLLIN; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fifofd, &epev)) + die("Failing in fifo epoll_ctl"); + /* + * Main body: wait something to report + */ while (1) { - if ((i = epoll_wait(epfd, &epev, 1, -1)) < 0) { - perror("error on epoll_wait"); - exit(-1); - } - switch (epev.fd) { - /* - * Handling options - */ - case sigfd: - // signals - break; - case fifofd: - // fifo - break; - default: /* should not reached */ - printf("something wrong, epoll activity on unknown %i file descriptor\n", epev.data.fd); - exit(-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 eppol events */ + for (i=0; i