X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=fileadv.tex;h=fdf294698312d9d9f307039e954d642d88b27569;hb=7d224ad655c0a530877f39411d43a91e3d7318e1;hp=77e058e920ae77b2a6e90f00277af8ab6219cb30;hpb=c23786b2033224de5b188ddcf1180e35ed9eb5af;p=gapil.git diff --git a/fileadv.tex b/fileadv.tex index 77e058e..fdf2946 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -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 @@ -1871,7 +1909,7 @@ ad altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per cui tutto è un file, consentisse di eseguire la notifica con l'uso di opportuni file descriptor.\footnote{ovviamente si tratta di una funzionalità specifica di Linux, non presente in altri sistemi unix-like, e non prevista - da nessuno standard.} + da nessuno standard, per cui va evitata se si ha a cuore la portabilità.} In sostanza, come per \func{sigwait}, si può disabilitare l'esecuzione di un gestore in occasione dell'arrivo di un segnale, e rilevarne l'avvenuta @@ -1884,9 +1922,14 @@ contemporanea sia l'arrivo del segnale che la disponibilit relativi a questi ultimi. La funzione che permette di abilitare la ricezione dei segnali tramite file -descriptor è \funcd{signalfd},\footnote{in realtà questa è il nome della - funzione fornita dalle \acr{glibc}, esistono in realtà due - versioni, anche se } il cui prototipo è: +descriptor è \funcd{signalfd},\footnote{in realtà quella riportata è la + interfacia alla funzione fornita dalle \acr{glibc}, esistono in realtà due + versioni diverse della \textit{system call}, la prima versione, + \func{signalfd}, introdotta nel kernel 2.6.22 e disponibile con le + \acr{glibc} 2.8 che non supporta l'argomento, ed una seconda versione, + \func{signalfd4}, che prende argomenti aggiuntivi, introdotta con il kernel + 2.6.27 che è quella che viene sempre usata a partire dalle \acr{glibc} 2.9.} +il cui prototipo è: \begin{prototype}{sys/signalfd.h} {int signalfd(int fd, const sigset\_t *mask, int flags)} @@ -1911,29 +1954,30 @@ descriptor La funzione consente di creare o modificare le caratteristiche di un file descriptor speciale su cui ricevere le notifiche della ricezione di -segnali. Per creare un nuovo file descriptor è necessario passare $-1$ come -valore per l'argomento \param{fd}, ogni altro valore positivo verrà invece -interpretato come il numero del file descriptor (che deve esser stato +segnali. Per creare ex-novo uno di questi file descriptor è necessario passare +$-1$ come valore per l'argomento \param{fd}, ogni altro valore positivo verrà +invece interpretato come il numero del file descriptor (che deve esser stato precedentemente creato sempre con \func{signalfd}) di cui si vogliono -modificare le caratteristiche. Nel primo caso la funzione ritornerà il nuovo -file descriptor e nel secondo caso \param{fd}, in caso di errore verrà invece -restituito $-1$. +modificare le caratteristiche. Nel primo caso la funzione ritornerà il valore +del nuovo file descriptor e nel secondo caso il valore indicato +con \param{fd}, in caso di errore invece verrà restituito $-1$. L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere specificato tramite l'argomento \param{mask}. Questo deve essere passato come -puntatore ad una maschera di segnali creata con l'uso delle apposite macro -illustrate in sez.~\ref{sec:sig_sigset} che indichi su quali segnali si -intende operare con \func{signalfd}, l'elenco può essere modificato da una -chiamata successiva. Dato che \const{SIGKILL} e \const{SIGSTOP} non possono -essere intercettati (e non prevedono neanche la possibilità di un gestore) un -loro inserimento nella maschera verrà semplicemente ignorato, senza generare -errori. - -Infine l'argomento \param{flags} consente di impostare direttamente in fase di -creazione due flag per il file descriptor analoghe a quelle che si possono -impostare con \func{open}, evitando una impostazione successiva con -\func{fcntl}.\footnote{questo è un argomento aggiuntivo introdotto con il - kernel 2.6.27, in precedenza il valore era nullo } +puntatore ad una maschera di segnali creata con l'uso delle apposite macro già +illustrate in sez.~\ref{sec:sig_sigset}; la maschera deve indicare su quali +segnali si intende operare con \func{signalfd}; l'elenco può essere modificato +con una successiva chiamata a \func{signalfd}. Dato che \const{SIGKILL} e +\const{SIGSTOP} non possono essere intercettati (e non prevedono neanche la +possibilità di un gestore) un 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{questo è un argomento + aggiuntivo, introdotto con la versione fornita a partire dal kernel 2.6.27, + per kernel precedenti il valore deve essere nullo.} \begin{table}[htb] \centering @@ -1951,11 +1995,19 @@ impostare con \func{open}, evitando una impostazione successiva con \hline \end{tabular} \caption{Valori dell'argomento \param{flags} per la funzione \func{signalfd} - che consentono di impostare fl.} + che consentono di impostare i flag del file descriptor.} \label{tab:signalfd_flags} \end{table} -% TODO trattare qui eventfd signalfd e timerfd introdotte con il 2.6.22 +L'interfaccia fornita da \func{signalfd} prevede che la ricezione dei segnali +sia eseguita leggendo dal file descriptor restituito dalla funzione. La +lettura fornisce nel buffer indicato come secondo argomento alla funzione +\func{read} una o più strutture \struct{signalfd\_siginfo} a seconda della +dimensione dello stesso e del numero di segnali pendenti. Pertanto il buffer +deve essere almeno di dimensione pari a \code{sizeof(signalfd\_siginfo)}; se +di dimensione maggiore potranno essere letti in unica soluzione + +% TODO trattare qui eventfd, signalfd e timerfd introdotte con il 2.6.22 % timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25 % vedi: http://lwn.net/Articles/233462/ % http://lwn.net/Articles/245533/ @@ -2227,14 +2279,17 @@ rilasciato o declassato (che questo sia fatto dal \textit{lease holder} o dal kernel è lo stesso) le chiamate a \func{open} o \func{truncate} eseguite dal \textit{lease breaker} rimaste bloccate proseguono automaticamente. - -\itindbeg{dnotify} - Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da parte di più processi, l'uso dei \textit{file lease} non consente comunque di risolvere il problema di rilevare automaticamente quando un file o una -directory vengono modificati, che è quanto necessario ad esempio ai programma -di gestione dei file dei vari desktop grafici. +directory vengono modificati,\footnote{questa funzionalità venne aggiunta + principalmente ad uso di Samba per poter facilitare l'emulazione del + comportamento di Windows sui file, ma ad oggi viene considerata una + interfaccia mal progettata ed il suo uso è fortemente sconsigliato a favore + di \textit{inotify}.} che è quanto necessario ad esempio ai programma di +gestione dei file dei vari desktop grafici. + +\itindbeg{dnotify} Per risolvere questo problema a partire dal kernel 2.4 è stata allora creata un'altra interfaccia,\footnote{si ricordi che anche questa è una interfaccia @@ -2324,7 +2379,7 @@ numero di file). Infine l'uso dei segnali come interfaccia di notifica comporta tutti i problemi di gestione visti in sez.~\ref{sec:sig_management} e sez.~\ref{sec:sig_adv_control}. Per tutta questa serie di motivi in generale quella di \textit{dnotify} viene considerata una interfaccia di usabilità -problematica. +problematica ed il suo uso oggi è fortemente sconsigliato. \itindend{dnotify}