From: Simone Piccardi Date: Mon, 5 Jan 2004 19:24:52 +0000 (+0000) Subject: Altre modifiche che mi ero dimenticato di buttar giu ieri X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=bb7af0b0462a0f09ae13f617ef8f40c24e1857cf Altre modifiche che mi ero dimenticato di buttar giu ieri --- diff --git a/fileadv.tex b/fileadv.tex index a4f8229..f343a48 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -306,12 +306,12 @@ interruzione si potranno eseguire le relative operazioni. \subsection{La funzione \func{poll}} \label{sec:file_poll} -System V, invece di utilizzare l'interfaccia di \func{select}, che è una -estensione creata nello sviluppo di BSD, ha introdotto una sua interfaccia per -gestire l'\textit{I/O multiplexing}, basata sulla funzione -\funcd{poll},\footnote{la funzione è prevista dallo standard XPG4, ed è stata - introdotta in Linux come system call a partire dal kernel 2.1.23 ed inserita - nelle \acr{libc} 5.4.28.} il cui prototipo è: +Nello sviluppo di System V, invece di utilizzare l'interfaccia di +\func{select}, che è una estensione tipica di BSD, è stata introdotta un'altra +interfaccia, basata sulla funzione \funcd{poll},\footnote{la funzione è + prevista dallo standard XPG4, ed è stata introdotta in Linux come system + call a partire dal kernel 2.1.23 ed inserita nelle \acr{libc} 5.4.28.} il +cui prototipo è: \begin{prototype}{sys/poll.h} {int poll(struct pollfd *ufds, unsigned int nfds, int timeout)} @@ -331,13 +331,14 @@ gestire l'\textit{I/O multiplexing}, basata sulla funzione ed inoltre \errval{EFAULT} e \errval{ENOMEM}.} \end{prototype} -La funzione permette di tenere sotto controllo un certo numero \param{ndfs} di -file descriptor, specificati attraverso un vettore di puntatori a strutture -\struct{pollfd}. Come \func{select} anche \func{poll} permette di -interrompere l'attesa dopo un certo tempo, che va specificato attraverso +La funzione permette di tenere sotto controllo contemporaneamente \param{ndfs} +file descriptor, specificati attraverso il puntatore \param{ufds} ad un +vettore di strutture \struct{pollfd}. Come con \func{select} si può +interrompere l'attesa dopo un certo tempo, questo deve essere specificato con l'argomento \param{timeout} in numero di millisecondi: un valore negativo -indica un'attesa indefinita mentre si può usare un valore nullo per eseguire -la funzione in modalità \textsl{non-bloccante}. +indica un'attesa indefinita, mentre un valore comporta il ritorno immediato (e +può essere utilizzato per impiegare \func{poll} in modalità +\textsl{non-bloccante}). \begin{figure}[!htb] \footnotesize \centering @@ -350,15 +351,18 @@ la funzione in modalit \label{fig:file_pollfd} \end{figure} -Per ciascun file da controllare deve essere opportunamente predisposta una -struttura \struct{pollfd}, la cui definizione è riportata in -\figref{fig:file_pollfd}. La struttura prevede tre campi: il campo \var{fd} -viene utilizzato per specificare il file descriptor relativo al file da -controllare, mentre nel campo \var{events} deve essere specificata una -maschera binaria data in ingresso che indichi il tipo di evento che si vuole -controllare, il kernel restituirà il relativo risultato nel campo -\var{revents}. Usando un valore negativo per \param{fd} la corrispondente -struttura sarà ignorata da \func{poll}. +Per ciascun file da controllare deve essere inizializzata una struttura +\struct{pollfd} nel vettore indicato dall'argomento \param{ufds}. La +struttura, la cui definizione è riportata in \figref{fig:file_pollfd}, prevede +tre campi: in \var{fd} deve essere indicato il numero del file descriptor da +controllare, in \var{events} deve essere specificata una maschera binaria di +flag che indichino il tipo di evento che si vuole controllare, mentre in +\var{revents} il kernel restituirà il relativo risultato. Usando un valore +negativo per \param{fd} la corrispondente struttura sarà ignorata da +\func{poll}. Dato che i dati in ingresso sono del tutto indipendenti da quelli +in uscita (che vengono restituiti in \var{revents}) non è necessario +reinizializzare tutte le volte il valore delle strutture \struct{pollfd} a +meno di non voler cambiare qualche condizione. Le costanti che definiscono i valori relativi ai bit usati nelle maschere binarie dei campi \var{events} e \var{revents} sono riportati in @@ -397,18 +401,22 @@ nel campo \var{revents} per notificare delle condizioni di errore. \label{tab:file_pollfd_flags} \end{table} -Infine il valore \const{POLLMSG} non viene utilizzato ed è definito solo per -compatibilità con l'implementazione di SysV, dove indica segnale -\const{SIGPOLL} è arrivato alla cima dello \textit{stream}. Gli -\textit{stream} sono una interfaccia specifica di SysV non presente in Linux, -e non hanno nulla a che fare con i file \textit{stream} delle librerie -standard del C, è da questi che derivano i nomi delle costanti, in quanto per -essi sono definite tre classi di dati: \textsl{normali}, \textit{prioritari} -ed \textit{urgenti}. Nel caso di Linux la distinzione ha senso solo nel caso -per i dati \textit{out-of-band} dei socket (vedi +Il valore \const{POLLMSG} non viene utilizzato ed è definito solo per +compatibilità con l'implementazione di SysV che usa gli +\textit{stream};\footnote{essi sono una interfaccia specifica di SysV non + presente in Linux, e non hanno nulla a che fare con i file \textit{stream} + delle librerie standard del C.} è da questi che derivano i nomi di alcune +costanti, in quanto per essi sono definite tre classi di dati: +\textsl{normali}, \textit{prioritari} ed \textit{urgenti}.} In Linux la +distinzione ha senso solo per i dati \textit{out-of-band} dei socket (vedi \secref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce alle varie condizioni dei socket torneremo in \secref{sec:TCP_serv_poll}, dove -vedremo anche un esempio del suo utilizzo. +vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le +costanti relative ai diversi tipi di dati (come \macro{POLLRDNORM} e +\macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definito +\macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in testa al + file, definirla soltanto prima di includere \file{sys/poll.h} non è + sufficiente.} In caso di successo funzione ritorna restituendo il numero di file (un valore positivo) per i quali si è verificata una delle condizioni di attesa richieste @@ -423,8 +431,7 @@ tramite \var{errno}. %\label{sec:file_epoll} % placeholder ... - - +%da fare \section{Altre modalità e funzioni di I/O avanzato} \label{sec:file_advanced_io} @@ -437,16 +444,16 @@ problematiche avanzate riguardanti l'I/O su file, tratteremo tutto ci questa sezione. -\subsection{L'I/O asincrono} -\label{sec:file_asyncronous_io} +\subsection{L'apertura asincrona dei file} +\label{sec:file_asyncronous_open} -Una modalità alternativa all'uso dell'\textit{I/O multiplexing} è quella di -fare ricorso al cosiddetto \textsl{I/O asincrono}. Il concetto base -dell'\textsl{I/O asincrono} è che le funzioni di I/O non attendono il -completamento delle operazioni prima di ritornare, così che il processo non -viene bloccato. In questo modo diventa ad esempio possibile effettuare una -richiesta preventiva di dati, in modo da poter effettuare in contemporanea le -operazioni di calcolo e quelle di I/O. +Una modalità alternativa all'uso dell'\textit{I/O multiplexing} per gestione +dell'I/O simultaneo su molti file, è costituita dal cosiddetto \textsl{I/O + asincrono}. Il concetto base dell'\textsl{I/O asincrono} è che le funzioni +di I/O non attendono il completamento delle operazioni prima di ritornare, +così che il processo non viene bloccato. In questo modo diventa ad esempio +possibile effettuare una richiesta preventiva di dati, in modo da poter +effettuare in contemporanea le operazioni di calcolo e quelle di I/O. Abbiamo accennato in \secref{sec:file_open} che è possibile, attraverso l'uso del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei @@ -454,19 +461,23 @@ del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile attivare in un secondo tempo questa modalità impostando questo flag attraverso l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi -\secref{sec:file_fcntl}). - -In realtà in questo caso non si tratta di I/O asincrono vero e proprio, quanto -di un meccanismo asincrono di notifica delle variazione dello stato del file -descriptor; quello che succede è che il sistema genera un segnale (normalmente -\const{SIGIO}, ma è possibile usarne altri) tutte le volte che diventa -possibile leggere o scrivere dal file descriptor che si è posto in questa -modalità. Si può inoltre selezionare, con il comando \const{F\_SETOWN} di -\func{fcntl}, quale processo (o gruppo di processi) riceverà il segnale. +\secref{sec:file_fcntl}). + +In realtà in questo caso non si tratta di I/O asincrono vero e proprio (che +vedremo in \secref{sec:file_asyncronous_io}), quanto di un meccanismo +asincrono di notifica delle variazione dello stato del file descriptor; quello +che succede è che il sistema genera un segnale (normalmente \const{SIGIO}, ma +è possibile usarne altri) tutte le volte che diventa possibile leggere o +scrivere dal file descriptor che si è posto in questa modalità. Si può inoltre +selezionare, con il comando \const{F\_SETOWN} di \func{fcntl}, quale processo +(o gruppo di processi) riceverà il segnale. Se pertanto si effettuano le +operazioni in risposta alla ricezione del segnale non ci sarà più la necessità +di restare bloccati in attesa della disponibilità di accesso ai file. In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select} che, quando vengono usate con un numero molto grande di file descriptor, non -hanno buone prestazioni. In tal caso infatti la maggior parte del loro tempo +hanno buone prestazioni. % aggiungere cenno a epoll quando l'avrò scritta + In tal caso infatti la maggior parte del loro tempo di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor tenuti sotto controllo per determinare quali di essi (in genere una piccola percentuale) sono diventati attivi. @@ -503,6 +514,9 @@ invier in eccesso, e si dovrà determinare al solito modo quali sono i file diventati attivi. +\subsection{L'interfaccia POSIX per l'I/O asincrono} +\label{sec:file_asyncronous_io} + Benché la modalità di apertura asincrona di un file possa risultare utile in varie occasioni (in particolar modo con i socket\index{socket} e gli altri file per i quali le funzioni di I/O sono system call lente), essa è comunque @@ -580,7 +594,7 @@ che serve a specificare il modo in cui si vuole che venga effettuata la notifica del completamento delle operazioni richieste. La struttura è riportata in \secref{fig:file_sigevent}; il campo \var{sigev\_notify} è quello che indica le modalità della notifica, esso può assumere i tre valori: -\begin{basedescript}{\desclabelwidth{3.0cm}} +\begin{basedescript}{\desclabelwidth{2.6cm}} \item[\const{SIGEV\_NONE}] Non viene inviata nessuna notifica. \item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di diff --git a/sources/poll_echod.c b/sources/poll_echod.c index bf2774e..9abccf4 100644 --- a/sources/poll_echod.c +++ b/sources/poll_echod.c @@ -26,12 +26,13 @@ * * Usage: echod -h give all info * - * $Id: poll_echod.c,v 1.1 2004/01/02 21:32:08 piccardi Exp $ + * $Id: poll_echod.c,v 1.2 2004/01/05 19:24:52 piccardi Exp $ * ****************************************************************/ /* * Include needed headers */ +#define _XOPEN_SOURCE #include /* system limits */ #include /* predefined types */ #include /* include unix standard library */ @@ -44,7 +45,6 @@ #include /* error code */ #include /* error strings */ #include -#define _XOPEN_SOURCE #include /* poll function definition */ #include "macros.h" @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) poll_set[max_fd].fd = list_fd; /* main loop, wait for connection and data inside a select */ while (1) { - while ( ((n = poll(poll_set, max_fd, -1)) < 0) + while ( ((n = poll(poll_set, max_fd + 1, -1)) < 0) && (errno == EINTR)); /* wait for data or connection */ if (n < 0) { /* on real error exit */ PrintErr("poll error"); diff --git a/tcpsockadv.tex b/tcpsockadv.tex index c8e9ec4..c93dc4a 100644 --- a/tcpsockadv.tex +++ b/tcpsockadv.tex @@ -688,7 +688,7 @@ conseguente blocco del server su di una \func{write}. Le possibili soluzioni in questo caso sono quelle di ritornare ad eseguire il ciclo di risposta alle richieste all'interno di processi separati, utilizzare un timeout per le operazioni di scrittura, o eseguire queste ultime in -modalità non bloccante, cocludendo le operazioni qualora non vadano a buon +modalità non bloccante, concludendo le operazioni qualora non vadano a buon fine. @@ -700,8 +700,7 @@ Finora abbiamo trattato le problematiche risolubili con l'I/O multiplexing impiegando la funzione \func{select}; questo è quello che avviene nella maggior parte dei casi, in quanto essa è nata sotto BSD proprio per affrontare queste problematiche con i socket. Abbiamo però visto in -\secref{sec:file_multiplexing} come esistono altre funzioni che permettono di -affrontare lo stesso problema e come la funzione \func{poll} possa costituire +\secref{sec:file_multiplexing} come la funzione \func{poll} possa costituire una alternativa a \func{select}, con alcuni vantaggi.\footnote{non soffrendo delle limitazioni dovute all'uso dei \textit{file descriptor set}.} @@ -734,11 +733,25 @@ pertanto: Come esempio dell'uso di \func{poll} proviamo allora a reimplementare il server \textit{echo} secondo lo schema di \figref{fig:TCP_echo_multiplex} usando \func{poll} al posto di \func{select}. In questo caso dovremo fare -qualche modifica, - +qualche modifica, per tenere conto della diversa sintassi delle due funzioni, +ma la struttura del programma resta sostanzialmente la stessa. +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/poll_echod.c} + \end{minipage} + \normalsize + \caption{La sezione principale del codice della nuova versione di server + \textit{echo} basati sull'uso della funzione \func{poll}.} + \label{fig:TCP_PollEchod} +\end{figure} +In \figref{fig:TCP_PollEchod} è riportata la sezione principale della nuova +versione del server, la versione completa del codice è riportata nel file +\file{poll\_echod.c} dei sorgenti allegati alla guida. Al solito si sono +tralasciate \section{Le opzioni dei socket}