From: Simone Piccardi Date: Wed, 9 Apr 2014 17:12:12 +0000 (+0000) Subject: Correzioni varie e revisione epoll completata X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=67794e5214c13e46667b290dfd9f3014261a41d7;p=gapil.git Correzioni varie e revisione epoll completata --- diff --git a/fileadv.tex b/fileadv.tex index 00fad4a..f3b6b66 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1665,6 +1665,14 @@ dell'interfaccia, \funcd{epoll\_ctl}, il cui prototipo è: } \end{funcproto} +La funzione prende sempre come primo argomento un file descriptor di +\textit{epoll}, \param{epfd}, che indica quale istanza di \textit{epoll} usare +e deve pertanto essere stato ottenuto in precedenza con una chiamata a +\func{epoll\_create} o \func{epoll\_create1}. L'argomento \param{fd} indica +invece il file descriptor che si vuole tenere sotto controllo, quest'ultimo +può essere un qualunque file descriptor utilizzabile con \func{poll}, ed anche +un altro file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}. + Il comportamento della funzione viene controllato dal valore dall'argomento \param{op} che consente di specificare quale operazione deve essere eseguita. Le costanti che definiscono i valori utilizzabili per \param{op} @@ -1689,7 +1697,6 @@ delle operazioni cui fanno riferimento. \param{event}.\\ \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista dei file controllati tramite \param{epfd}.\\ - \const{EPOLL\_CTL\_DISABLE}& da fare.\\ \hline \end{tabular} \caption{Valori dell'argomento \param{op} che consentono di scegliere quale @@ -1697,35 +1704,44 @@ delle operazioni cui fanno riferimento. \label{tab:epoll_ctl_operation} \end{table} -% aggiunta EPOLL_CTL_DISABLE con il kernel 3.7, vedi +% era stata aggiunta EPOLL_CTL_DISABLE in previsione del kernel 3.7, vedi % http://lwn.net/Articles/520012/ e http://lwn.net/Articles/520198/ +% ma non è mai stata inserita. -La funzione prende sempre come primo argomento un file descriptor di -\textit{epoll}, \param{epfd}, che indica quale istanza di \textit{epoll} usare -e deve pertanto essere stato ottenuto in precedenza con una chiamata a -\func{epoll\_create}. L'argomento \param{fd} indica invece il file descriptor -che si vuole tenere sotto controllo, quest'ultimo può essere un qualunque file -descriptor utilizzabile con \func{poll}, ed anche un altro file descriptor di -\textit{epoll}, ma non lo stesso \param{epfd}. +Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è +l'insieme dei file descriptor da tenere sotto controllo utilizzando una serie +di chiamate a \const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è + che queste chiamate devono essere ripetute per ciascun file descriptor, + incorrendo in una perdita di prestazioni qualora il numero di file + descriptor sia molto grande; per questo è stato proposto di introdurre come + estensione una funzione \code{epoll\_ctlv} che consenta di effettuare con + una sola chiamata le impostazioni per un blocco di file descriptor.} L'uso +di \const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di +osservazione di un file descriptor che sia già stato aggiunto alla lista di +osservazione. Qualora non si abbia più interesse nell'osservazione di un file +descriptor lo si può rimuovere dalla lista associata a \param{epfd} con +\const{EPOLL\_CTL\_DEL}. Anche se è possibile tenere sotto controllo lo stesso file descriptor in due istanze distinte di \textit{epoll} in genere questo è sconsigliato in quanto -entrambe riceveranno le notifiche, ma gestire correttamente le notifiche +entrambe riceveranno le notifiche, e gestire correttamente le notifiche multiple richiede molta attenzione. Se invece si cerca di inserire due volte -lo stesso file descriptor nella stessa istanza di \textit{epoll} (con lo -stesso \param{epfd}) la funzione fallirà con un errore di \errval{EEXIST}. -Tuttavia è possibile inserire nella stessa istanza file descriptor duplicati -(si ricordi quanto visto in sez.~\ref{sec:file_dup}), una tecnica che può -essere usata per registrarli con un valore diverso per \param{events} e -classificare così diversi tipi di eventi. +lo stesso file descriptor nella stessa istanza di \textit{epoll} la funzione +fallirà con un errore di \errval{EEXIST}. Tuttavia è possibile inserire nella +stessa istanza file descriptor duplicati (si ricordi quanto visto in +sez.~\ref{sec:file_dup}), una tecnica che può essere usata per registrarli con +un valore diverso per \param{events} e classificare così diversi tipi di +eventi. Si tenga presente che quando si chiude un file descriptor questo, se era stato posto sotto osservazione da una istanza di \textit{epoll}, viene rimosso -automaticamente solo nel caso esso sia l'unico riferimento al file sottostante -(alla struttura \kstruct{file}, si ricordi fig.~\ref{fig:file_dup}), quindi -qualora esso sia stato duplicato si potranno ricevere eventi relativi ad esso -anche dopo che lo si è chiuso, per evitare questo è necessario rimuoverlo -esplicitamente dalla lista dei file descriptor mantenuti sotto controllo con +automaticamente solo nel caso esso sia l'unico riferimento al file aperto +sottostante (più precisamente alla struttura \kstruct{file}, si ricordi +fig.~\ref{fig:file_dup}) e non è necessario usare +\const{EPOLL\_CTL\_DEL}. Questo non avviene qualora esso sia stato duplicato +(perché la suddetta struttura non viene disallocata) e si potranno ricevere +eventi ad esso relativi anche dopo che lo si è chiuso; per evitare +l'inconveniente è necessario rimuoverlo esplicitamente con \const{EPOLL\_CTL\_DEL}. L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura @@ -1760,14 +1776,15 @@ definizione è riportata in fig.~\ref{fig:epoll_event}. 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}, è una \direct{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. +tab.~\ref{tab:epoll_events}. Nella prima parte della tabella si sono indicate +le costanti che permettono di indicare il tipo di evento, che sono le +equivalenti delle analoghe di tab.~\ref{tab:file_pollfd_flags} per +\func{poll}. Queste sono anche quelle riportate nella struttura +\struct{epoll\_event} restituita da \func{epoll\_wait} per indicare il tipo di +evento presentatosi, insieme a quelle della seconda parte della tabella, che +vengono comunque riportate anche se non le si sono impostate con +\func{epoll\_ctl}. La terza parte della tabella contiene le costanti che +modificano le modalità di notifica. \begin{table}[htb] \centering @@ -1791,6 +1808,7 @@ identificazione del file descriptor. \const{POLLPRI}); questa condizione viene comunque riportata in uscita, e non è necessaria impostarla in ingresso.\\ + \hline \const{EPOLLERR} & Si è verificata una condizione di errore (analogo di \const{POLLERR}); questa condizione viene comunque riportata in uscita, e non è @@ -1798,12 +1816,19 @@ identificazione del file descriptor. \const{EPOLLHUP} & Si è verificata una condizione di hung-up; questa condizione viene comunque riportata in uscita, e non è necessaria impostarla in ingresso.\\ + \hline \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 descriptor associato (questa modalità è disponibile solo a partire dal kernel 2.6.2).\\ - \hline + \const{EPOLLWAKEUP} & Attiva la prevenzione della sospensione del sistema + se il file descriptor che si è marcato con esso + diventa pronto (aggiunto a partire dal kernel 3.5), + può essere impostato solo dall'amministratore (o da + un processo con la capacità + \const{CAP\_BLOCK\_SUSPEND}).\\ + \hline \end{tabular} \caption{Costanti che identificano i bit del campo \param{events} di \struct{epoll\_event}.} @@ -1811,40 +1836,24 @@ identificazione del file descriptor. \end{table} \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}.} - -% TODO aggiunto EPOLLWAKEUP con il 3.5 - - -Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è -l'insieme dei file descriptor da tenere sotto controllo tramite un certo -\textit{epoll descriptor} \param{epfd} attraverso una serie di chiamate a -\const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è che queste - chiamate devono essere ripetute per ciascun file descriptor, incorrendo in - una perdita di prestazioni qualora il numero di file descriptor sia molto - grande; per questo è stato proposto di introdurre come estensione una - funzione \code{epoll\_ctlv} che consenta di effettuare con una sola chiamata - le impostazioni per un blocco di file descriptor.} L'uso di -\const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di -osservazione di un file descriptor che sia già stato aggiunto alla lista di -osservazione. + ed è utile per riconoscere la chiusura di una connessione dall'altro capo di + un socket quando si lavora in modalità \textit{edge triggered}.} + +Il secondo campo, \var{data}, è una \direct{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. % TODO verificare se prima o poi epoll_ctlv verrà introdotta Le impostazioni di default prevedono che la notifica degli eventi richiesti sia effettuata in modalità \textit{level triggered}, a meno che sul file descriptor non si sia impostata la modalità \textit{edge triggered}, -registrandolo con \const{EPOLLET} attivo nel campo \var{events}. Si tenga -presente che è possibile tenere sotto osservazione uno stesso file descriptor -su due \textit{epoll descriptor} diversi, ed entrambi riceveranno le -notifiche, anche se questa pratica è sconsigliata. - -Qualora non si abbia più interesse nell'osservazione di un file descriptor lo -si può rimuovere dalla lista associata a \param{epfd} con -\const{EPOLL\_CTL\_DEL}; si tenga conto inoltre che i file descriptor sotto -osservazione che vengono chiusi sono eliminati dalla lista automaticamente e -non è necessario usare \const{EPOLL\_CTL\_DEL}. +registrandolo con \const{EPOLLET} attivo nel campo \var{events}. Infine una particolare modalità di notifica è quella impostata con \const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti @@ -1865,8 +1874,8 @@ dovrà essere riabilitato esplicitamente con una successiva chiamata con \const{EPOLL\_CTL\_MOD}. Una volta impostato l'insieme di file descriptor che si vogliono osservare con -i relativi eventi, la funzione che consente di attendere l'occorrenza di uno -di tali eventi è \funcd{epoll\_wait}, il cui prototipo è: +i relativi eventi, la funzione di sistema che consente di attendere +l'occorrenza di uno di tali eventi è \funcd{epoll\_wait}, il cui prototipo è: \begin{funcproto}{ \fhead{sys/epoll.h} @@ -1925,26 +1934,40 @@ dell'osservazione con \const{EPOLL\_CTL\_MOD}, questi verrebbero riletti alla luce delle modifiche. Si tenga presente infine che con l'uso della modalità \textit{edge triggered} -il ritorno di \func{epoll\_wait} indica che un file descriptor è pronto e -resterà tale fintanto che non si sono completamente esaurite le operazioni su -di esso. Questa condizione viene generalmente rilevata dall'occorrere di un -errore di \errcode{EAGAIN} al ritorno di una \func{read} o una -\func{write},\footnote{è opportuno ricordare ancora una volta che l'uso - dell'\textit{I/O multiplexing} richiede di operare sui file in modalità non - bloccante.} ma questa non è la sola modalità possibile, ad esempio la -condizione può essere riconosciuta anche per il fatto che sono stati -restituiti meno dati di quelli richiesti. +il ritorno di \func{epoll\_wait} avviene solo quando il file descriptor ha +cambiato stato diventando pronto. Esso non sarà riportato nuovamente fino ad +un altro cambiamento di stato, per cui occorre assicurarsi di aver +completamente esaurito le operazioni su di esso. Questa condizione viene +generalmente rilevata dall'occorrere di un errore di \errcode{EAGAIN} al +ritorno di una \func{read} o una \func{write}, (è opportuno ricordare ancora +una volta che l'uso dell'\textit{I/O multiplexing} richiede di operare sui +file in modalità non bloccante) ma questa non è la sola modalità possibile, ad +esempio la condizione può essere riconosciuta anche per il fatto che sono +stati restituiti meno dati di quelli richiesti. + +Si tenga presente che in modalità \textit{edge triggered}, dovendo esaurire le +attività di I/O dei file descriptor risultati pronti per poter essere +rinotificati, la gestione elementare per cui li si trattano uno per uno in +sequenza può portare ad un effetto denominato \textit{starvation} +(``\textsl{carestia}''). Si rischia cioè di concentrare le operazioni sul +primo file descriptor che dispone di molti dati, prolungandole per tempi molto +lunghi con un ritardo che può risultare eccessivo nei confronti di quelle da +eseguire sugli altri che verrebbero dopo. Per evitare questo tipo di +problematiche viene consigliato di usare \func{epoll\_wait} per registrare un +elenco dei file descriptor da gestire, e di trattarli a turno in maniera più +equa. 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 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 \index{maschera~dei~segnali} -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 funzione è stata - introdotta a partire dal kernel 2.6.19, ed è come tutta l'interfaccia di - \textit{epoll}, specifica di Linux.} ed il suo prototipo è: +contemporaneamente. Valgono le osservazioni fatte in +sez.~\ref{sec:file_select}, e per poterlo fare di nuovo è necessaria una +variante della funzione di attesa che consenta di reimpostare all'uscita una +\index{maschera~dei~segnali} 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 di sistema si chiama +\funcd{epoll\_pwait}\footnote{la funzione è stata introdotta a partire dal + kernel 2.6.19, ed è come tutta l'interfaccia di \textit{epoll}, specifica di + Linux.} ed il suo prototipo è: \begin{funcproto}{ \fhead{sys/epoll.h} @@ -1999,10 +2022,11 @@ fare all'interno della funzione del gestore di segnali (quelli illustrati in sez.~\ref{sec:sig_signal_handler}), c'è il problema più generale consistente nel fatto che questa modalità di funzionamento cozza con altre interfacce di programmazione previste dal sistema in cui si opera in maniera -\textsl{sincrona}, come quelle dell'I/O multiplexing appena illustrate. +\textsl{sincrona}, come quelle dell'\textit{I/O multiplexing} appena +illustrate. In questo tipo di interfacce infatti ci si aspetta che il processo gestisca -gli eventi a cui vuole rispondere in maniera sincrona generando le opportune +gli eventi a cui deve reagire in maniera sincrona generando le opportune risposte, mentre con l'arrivo di un segnale si possono avere interruzioni asincrone in qualunque momento. Questo comporta la necessità di dover gestire, quando si deve tener conto di entrambi i tipi di eventi, le @@ -2103,11 +2127,11 @@ loro inserimento nella maschera verrà ignorato senza generare errori. L'argomento \param{flags} consente di impostare direttamente in fase di creazione due flag per il file descriptor analoghi a quelli che si possono impostare con una creazione ordinaria con \func{open}, evitando una -impostazione successiva con \func{fcntl}.\footnote{si ricordi che questo è un - argomento aggiuntivo, introdotto con la versione fornita a partire dal - kernel 2.6.27, per kernel precedenti il valore deve essere nullo.} -L'argomento deve essere specificato come maschera binaria dei valori riportati -in tab.~\ref{tab:signalfd_flags}. +impostazione successiva con \func{fcntl} (si ricordi che questo è un argomento +aggiuntivo, introdotto con la versione fornita a partire dal kernel 2.6.27, +per kernel precedenti il valore deve essere nullo). L'argomento deve essere +specificato come maschera binaria dei valori riportati in +tab.~\ref{tab:signalfd_flags}. \begin{table}[htb] \centering diff --git a/filedir.tex b/filedir.tex index c294d7d..dc97d8b 100644 --- a/filedir.tex +++ b/filedir.tex @@ -6830,6 +6830,8 @@ opportuno dettagliare maggiormente. \const{CAP\_AUDIT\_WRITE}&Scrivere dati nel giornale di auditing del kernel (dal kernel 2.6.11).\\ % TODO verificare questa roba dell'auditing + \const{CAP\_BLOCK\_SUSPEND}&Utilizzare funzionalità che possono bloccare + la sospensione del sistema (dal kernel 3.5).\\ \const{CAP\_CHOWN} & Cambiare proprietario e gruppo proprietario di un file (vedi sez.~\ref{sec:file_ownership_management}).\\ diff --git a/listati/signalfd_siginfo.h b/listati/signalfd_siginfo.h index 33c1d08..930d49e 100644 --- a/listati/signalfd_siginfo.h +++ b/listati/signalfd_siginfo.h @@ -17,5 +17,5 @@ struct signalfd_siginfo { uint64_t ssi_addr; /* Address that generated signal (for hardware-generated signals) */ uint8_t pad[X]; /* Pad size to 128 bytes (allow for - additional fields in the future) */ + additional fields in the future) */ };