X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=ea2eb4b78288e0f6cf21442885dcd864f8499050;hp=6fdf67d4fc785865c8b79be60ac0da8720fa7a72;hb=e6ca5b03eaf1e9ef82eb75f722487efe97abaf88;hpb=e57a3ea92019458bdd851f97bb5021429716fcbc diff --git a/fileadv.tex b/fileadv.tex index 6fdf67d..ea2eb4b 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -164,9 +164,14 @@ La funzione richiede di specificare tre insiemi distinti di file descriptor; il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in tutti i casi in cui la successiva esecuzione di \func{read} risulti non - bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo, + bloccante, quindi anche in caso di \textit{end-of-file}; inoltre con Linux + possono verificarsi casi particolari, ad esempio quando arrivano dati su un + socket dalla rete che poi risultano corrotti e vengono scartati, può + accadere che \func{select} riporti il relativo file descriptor come + leggibile, ma una successiva \func{read} si blocchi.} il secondo, \param{writefds}, per verificare la possibilità effettuare una scrittura ed il -terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati +terzo, +\param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati urgenti \itindex{out-of-band} su un socket, vedi sez.~\ref{sec:TCP_urgent_data}). @@ -263,9 +268,13 @@ precedenti, ed inoltre aggiunge a \func{select} una nuova funzione La funzione è sostanzialmente identica a \func{select}, solo che usa una struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timeval_struct}) per indicare con maggiore precisione il timeout e non ne aggiorna il valore in -caso di interruzione. Inoltre prende un argomento aggiuntivo \param{sigmask} -che è il puntatore ad una maschera di segnali (si veda -sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa +caso di interruzione.\footnote{in realtà la system call di Linux aggiorna il + valore al tempo rimanente, ma la funzione fornita dalle \acr{glibc} modifica + questo comportamento passando alla system call una variabile locale, in modo + da mantenere l'aderenza allo standard POSIX che richiede che il valore di + \param{timeout} non sia modificato.} Inoltre prende un argomento aggiuntivo +\param{sigmask} che è il puntatore ad una maschera di segnali (si veda +sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della funzione. @@ -293,28 +302,25 @@ interrotta, e la ricezione del segnale non sar Per questo è stata introdotta \func{pselect} che attraverso l'argomento \param{sigmask} permette di riabilitare la ricezione il segnale contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al - kernel 2.6.16, non è presente la relativa system call, e la funzione è + kernel 2.6.16, non era presente la relativa system call, e la funzione era implementata nelle \acr{glibc} attraverso \func{select} (vedi \texttt{man select\_tut}) per cui la possibilità di \itindex{race~condition} - \textit{race condition} permane; esiste però una soluzione, chiamata - \itindex{self-pipe trick} \textit{self-pipe trick}, che consiste nell'aprire - una pipe (vedi sez.~\ref{sec:ipc_pipes}) ed usare \func{select} sul capo in - lettura della stessa, e indicare l'arrivo di un segnale scrivendo sul capo - in scrittura all'interno del gestore dello stesso; in questo modo anche se - il segnale va perso prima della chiamata di \func{select} questa lo - riconoscerà comunque dalla presenza di dati sulla pipe.} ribloccandolo non -appena essa ritorna, così che il precedente codice potrebbe essere riscritto -nel seguente modo: + \textit{race condition} permaneva; in tale situzione si può ricorrere ad una + soluzione alternativa, chiamata \itindex{self-pipe trick} \textit{self-pipe + trick}, che consiste nell'aprire una pipe (vedi sez.~\ref{sec:ipc_pipes}) + ed usare \func{select} sul capo in lettura della stessa; si può indicare + l'arrivo di un segnale scrivendo sul capo in scrittura all'interno del + gestore dello stesso; in questo modo anche se il segnale va perso prima + della chiamata di \func{select} questa lo riconoscerà comunque dalla + presenza di dati sulla pipe.} ribloccandolo non appena essa ritorna, così +che il precedente codice potrebbe essere riscritto nel seguente modo: \includecodesnip{listati/pselect_norace.c} in questo caso utilizzando \var{oldmask} durante l'esecuzione di \func{pselect} la ricezione del segnale sarà abilitata, ed in caso di interruzione si potranno eseguire le relative operazioni. -% TODO pselect è stata introdotta nel kernel 2.6.16 (o 15 o 17?) insieme a -% ppoll mettere e verificare, vedi articolo LWN http://lwn.net/Articles/176750/ - -\subsection{La funzione \func{poll}} +\subsection{Le funzioni \func{poll} e \func{ppoll}} \label{sec:file_poll} Nello sviluppo di System V, invece di utilizzare l'interfaccia di @@ -438,14 +444,58 @@ valore nullo indica che si indica un errore nella chiamata, il cui codice viene riportato al solito tramite \var{errno}. +Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una +variante di \func{select} che consente di gestire correttamente la ricezione +dei segnali nell'attesa su un file descriptor. Con l'introduzione di una +implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta +anche una analoga funzione che svolga lo stesso ruolo per \func{poll}. -% TODO accennare a ppoll +In questo caso si tratta di una estensione che è specifica di Linux e non è +prevista da nessuno standard; essa può essere utilizzata esclusivamente se si +definisce la macro \macro{\_GNU\_SOURCE} ed ovviamente non deve essere usata +se si ha a cuore la portabilità. La funzione è \funcd{ppoll}, ed il suo +prototipo è: +\begin{prototype}{sys/poll.h} + {int ppoll(struct pollfd *fds, nfds\_t nfds, const struct timespec *timeout, + const sigset\_t *sigmask)} + + La funzione attende un cambiamento di stato su un insieme di file + descriptor. + + \bodydesc{La funzione restituisce il numero di file descriptor con attività + in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore, + ed in quest'ultimo caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno + degli insiemi. + \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale. + \item[\errcode{EINVAL}] Il valore di \param{nfds} eccede il limite + \macro{RLIMIT\_NOFILE}. + \end{errlist} + ed inoltre \errval{EFAULT} e \errval{ENOMEM}.} +\end{prototype} + +La funzione ha lo stesso comportamento di \func{poll}, solo che si può +specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di +segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione +resterà in attesa, all'uscita viene ripristinata la maschera originale. L'uso +di questa funzione è cioè equivalente, come illustrato nella pagina di +manuale, all'esecuzione atomica del seguente codice: +\includecodesnip{listati/ppoll_means.c} + +Eccetto per \param{timeout}, che come per \func{pselect} deve essere un +puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con +\func{poll} hanno lo stesso significato, e la funzione restituisce gli stessi +risultati illustrati in precedenza. + + +% TODO accennare a ppoll vedi articolo LWN http://lwn.net/Articles/176750/ %\subsection{L'interfaccia di \textit{epoll}} %\label{sec:file_epoll} % placeholder ... -% TODO epoll +% TODO epoll \section{L'accesso \textsl{asincrono} ai file} \label{sec:file_asyncronous_access} @@ -1219,10 +1269,10 @@ cosiddetto \textit{memory-mapped I/O}, che, attraverso il meccanismo della \textsl{paginazione} \index{paginazione} usato dalla memoria virtuale (vedi sez.~\ref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un file in una sezione dello spazio di indirizzi del processo. - + che lo ha allocato \begin{figure}[htb] \centering - \includegraphics[width=12cm]{img/mmap_layout} + \includegraphics[width=10cm]{img/mmap_layout} \caption{Disposizione della memoria di un processo quando si esegue la mappatura in memoria di un file.} \label{fig:file_mmap_layout} @@ -1355,7 +1405,7 @@ tab.~\ref{tab:file_mmap_flag}. \begin{table}[htb] \centering \footnotesize - \begin{tabular}[c]{|l|p{10cm}|} + \begin{tabular}[c]{|l|p{11cm}|} \hline \textbf{Valore} & \textbf{Significato} \\ \hline @@ -1447,8 +1497,11 @@ effettive del file o della sezione che si vuole mappare. \footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di memoria.} -\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è - stato implementato in Linux a partire dai kernel della serie 2.4.x.} + +\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato + implementato in Linux a partire dai kernel della serie 2.4.x; esso consente + di creare segmenti di memoria condivisa e torneremo sul suo utilizzo in + sez.~\ref{sec:ipc_mmap_anonymous}.} \footnotetext{questo flag ed il precedente \const{MAP\_POPULATE} sono stati introdotti nel kernel 2.5.46 insieme alla mappatura non lineare di cui