X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=fileadv.tex;h=9f0a22558eb536c668485ed82808c91b020a6e5c;hb=8e235dc9eb48a0fdc6dab240ebede646f1391bb3;hp=b4c7d0012595d51cd65f87f041d978b6a19b3875;hpb=ff76d56c6a2c280cbe4f153173488871d7b12336;p=gapil.git diff --git a/fileadv.tex b/fileadv.tex index b4c7d00..9f0a225 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -142,7 +142,7 @@ possono usare delle opportune macro di preprocessore: Inserisce il file descriptor \param{fd} nell'insieme. \funcdecl{void \macro{FD\_CLR}(int fd, fd\_set *set)} - Rimuove il file descriptor \param{fd} nell'insieme. + Rimuove il file descriptor \param{fd} dall'insieme. \funcdecl{int \macro{FD\_ISSET}(int fd, fd\_set *set)} Controlla se il file descriptor \param{fd} è nell'insieme. @@ -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} @@ -493,7 +543,7 @@ accesso ai file; per questo motivo Stevens chiama questa modalit 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. % aggiungere cenno a epoll quando l'avrò scritta +hanno buone prestazioni. % TODO 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 @@ -576,11 +626,11 @@ soluzione disponibile con l'interfaccia tradizionale, che Queste nuove funzionalità sono delle estensioni specifiche, non standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel -supportano meccanismi simili). Esse sono realizzate, e solo a partire dalla -versione 2.4 del kernel, attraverso l'uso di alcuni \textsl{comandi} -aggiuntivi per la funzione \func{fcntl} (vedi sez.~\ref{sec:file_fcntl}), che -divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE} -prima di includere \file{fcntl.h}. +supportano meccanismi simili). Alcune di esse sono realizzate, e solo a +partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni +\textsl{comandi} aggiuntivi per la funzione \func{fcntl} (vedi +sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è +definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}. \index{file!lease|(} @@ -649,7 +699,8 @@ su un file, e che un \textit{lease} pu può ottenere un \textit{lease} soltanto per un file appartenente ad un \acr{uid} corrispondente a quello del processo. Soltanto un processo con privilegi di amministratore (cioè con la \itindex{capabilities} capability -\const{CAP\_LEASE}) può acquisire \textit{lease} su qualunque file. +\const{CAP\_LEASE}, vedi sez.~\ref{sec:proc_capabilities}) può acquisire +\textit{lease} su qualunque file. Se su un file è presente un \textit{lease} quando il \textit{lease breaker} esegue una \func{truncate} o una \func{open} che confligge con @@ -693,28 +744,20 @@ kernel 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 viene -modificato, che è quanto necessario ad esempio ai programma di gestione dei -file dei vari desktop grafici. +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. Per risolvere questo problema è stata allora creata un'altra interfaccia, chiamata \textit{dnotify}, che consente di richiedere una notifica quando una directory, o di uno qualunque dei file in essa contenuti, viene modificato. Come per i \textit{file lease} la notifica avviene di default attraverso il -segnale \const{SIGIO}, ma questo può essere modificato e si può ottenere nel -gestore il file descriptor che è stato modificato dal contenuto della -struttura \struct{siginfo\_t}. +segnale \const{SIGIO}, ma se ne può utilizzare un altro. inoltre si potrà +ottenere nel gestore del segnale il file descriptor che è stato modificato +tramite il contenuto della struttura \struct{siginfo\_t}. \index{file!lease|)} -Ci si può registrare per le notifiche dei cambiamenti al contenuto di una -certa directory eseguendo \func{fcntl} su un file descriptor \param{fd} -associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso -l'argomento \param{arg} serve ad indicare per quali classi eventi si vuole -ricevere la notifica, e prende come valore una maschera binaria composta -dall'OR aritmetico di una o più delle costanti riportate in -tab.~\ref{tab:file_notify}. - \begin{table}[htb] \centering \footnotesize @@ -750,23 +793,110 @@ tab.~\ref{tab:file_notify}. \label{tab:file_notify} \end{table} -A meno di non impostare in maniera esplicita una notifica permanente usando -\const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una sola -volta quando si verifica uno qualunque fra gli eventi per i quali la si è -richiesta. Questo significa che un programma deve registrarsi un'altra volta se -desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse + +Ci si può registrare per le notifiche dei cambiamenti al contenuto di una +certa directory eseguendo la funzione \func{fcntl} su un file descriptor +associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso +l'argomento \param{arg} di \func{fcntl} serve ad indicare per quali classi +eventi si vuole ricevere la notifica, e prende come valore una maschera +binaria composta dall'OR aritmetico di una o più delle costanti riportate in +tab.~\ref{tab:file_notify}. + +A meno di non impostare in maniera esplicita una notifica permanente usando il +valore \const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una +sola volta quando si verifica uno qualunque fra gli eventi per i quali la si è +richiesta. Questo significa che un programma deve registrarsi un'altra volta +se desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi specificate in chiamate successive vengono aggiunte a quelle già impostate nelle precedenti. Se si vuole rimuovere la notifica si deve invece specificare un valore nullo. + +\index{file!inotify|(} + +Il maggiore problema di \textit{dnotify} è quello della scalabilità, e della +complessità di gestione dovuta all'uso dei segnali. Per questo motivo a +partire dal kernel 2.6.13 è stata introdotta una nuova interfaccia per +l'osservazione delle modifiche a file o directory, chiamata +\textit{inotify}.\footnote{le corrispondenti funzioni di interfaccia sono + state introdotte nelle glibc 2.4.} + \index{file!dnotify|)} +L'interfaccia di \textit{inotify} è una caratteristica specifica di Linux +(pertanto non deve essere usata se si devono scrivere programmi portabili), ed +è basata sull'uso di una coda di notifica degli eventi associata ad un file +descriptor. La coda viene creata attraverso la funzione \funcd{inotify\_init}, +il cui prototipo è: +\begin{prototype}{sys/inotify.h} + {int inotify\_init(void)} + + Inizializza una istanza di \textit{inotify}. + + \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: + \begin{errlist} + \item[\errcode{EMFILE}] si è raggiunto il numero massimo di istanze di + \textit{inotify} consentite all'utente. + \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti + nel sistema. + \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare + l'istanza. + \end{errlist} +} +\end{prototype} + +La funzione non prende alcun argomento, e restituisce un file descriptor +associato alla coda, attraverso il quale verranno effettuate le operazioni di +notifica. Si tratta di un file descriptor speciale, che non è associato a +nessun file, ma che viene utilizzato per notificare gli eventi che si sono +posti in osservazione all'applicazione che usa l'interfaccia di +\textit{inotify}. + +Trattandosi di file descriptor a tutti gli effetti, esso potrà essere +utilizzato con le funzioni \func{select} e \func{poll}. Dato che gli eventi +vengono notificati come dati disponibili in lettura sul file descriptor +stesso, dette funzioni ritorneranno tutte le volte che si avrà un evento di +notifica. Si potrà cioè gestirlo secondo le modalità illustrate in +sez.~\ref{sec:file_multiplexing}. Inoltre, come per i file descriptor +associati ai socket (vedi sez.~\ref{sec:sock_ioctl_IP}) si potrà ottenere il +numero di byte disponibili in lettura eseguendo su di esso l'operazione +\const{FIONREAD} con \func{ioctl}. + +Una volta creata la coda di notifica, ed ottenuto il relativo file descriptor, +l'interfaccia prevede che si definiscano gli eventi da tenere sotto +osservazione associando ad esso una \textsl{lista di osservazione} (o +\textit{watch list}) che indica quali file e directory tenere d'occhio. Per +gestire la lista di osservazione l'interfaccia fornisce due funzioni, la prima +è \funcd{inotify\_add\_watch}, il cui prototipo è: +\begin{prototype}{sys/inotify.h} + {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)} + + Aggiunge una voce alla lista di osservazione di \param{fd}. + + \bodydesc{La funzione restituisce un valore positivo in caso di successo, o + $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato. + \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd} + non è un filesystem di \textit{inotify}. + \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di + osservazione o il kernel non ha potuto allocare una risorsa necessaria. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.} +\end{prototype} + + -\index{file!inotify|)} % TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478 -\index{file!inotify|(} +% TODO e man inotify + +\index{file!inotify|)} + + + @@ -1026,10 +1156,9 @@ valore di \param{aiocbp}. Quando una operazione viene cancellata una successiva chiamata ad \func{aio\_error} riporterà \errcode{ECANCELED} come codice di errore, ed il suo codice di ritorno sarà -1, inoltre il meccanismo di notifica non verrà invocato. Se si specifica una operazione relativa ad un -altro file descriptor il risultato è indeterminato. - -In caso di successo, i possibili valori di ritorno per \func{aio\_cancel} sono -tre (anch'essi definiti in \file{aio.h}): +altro file descriptor il risultato è indeterminato. In caso di successo, i +possibili valori di ritorno per \func{aio\_cancel} (anch'essi definiti in +\file{aio.h}) sono tre: \begin{basedescript}{\desclabelwidth{3.0cm}} \item[\const{AIO\_ALLDONE}] indica che le operazioni di cui si è richiesta la cancellazione sono state già completate, @@ -1104,29 +1233,28 @@ lettura o scrittura; il suo prototipo } \end{prototype} -La funzione esegue la richiesta delle \param{nent} operazioni indicate dalla -lista \param{list}; questa deve contenere gli indirizzi di altrettanti -\textit{control block}, opportunamente inizializzati; in particolare nel caso -dovrà essere specificato il tipo di operazione tramite il campo -\var{aio\_lio\_opcode}, che può prendere i tre valori: +La funzione esegue la richiesta delle \param{nent} operazioni indicate nella +lista \param{list} che deve contenere gli indirizzi di altrettanti +\textit{control block} opportunamente inizializzati; in particolare dovrà +essere specificato il tipo di operazione con il campo \var{aio\_lio\_opcode}, +che può prendere i valori: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{LIO\_READ}] si richiede una operazione di lettura. \item[\const{LIO\_WRITE}] si richiede una operazione di scrittura. \item[\const{LIO\_NOP}] non si effettua nessuna operazione. \end{basedescript} -l'ultimo valore viene usato quando si ha a che fare con un vettore di -dimensione fissa, per poter specificare solo alcune operazioni, o quando si è -dovuto cancellare delle operazioni e si deve ripetere la richiesta per quelle -non completate. +dove \const{LIO\_NOP} viene usato quando si ha a che fare con un vettore di +dimensione fissa, per poter specificare solo alcune operazioni, o quando si +sono dovute cancellare delle operazioni e si deve ripetere la richiesta per +quelle non completate. -L'argomento \param{mode} permette di stabilire il comportamento della -funzione, se viene specificato il valore \const{LIO\_WAIT} la funzione si -blocca fino al completamento di tutte le operazioni richieste; se invece si -specifica \const{LIO\_NOWAIT} la funzione ritorna immediatamente dopo aver -messo in coda tutte le richieste. In questo caso il chiamante può richiedere -la notifica del completamento di tutte le richieste, impostando l'argomento -\param{sig} in maniera analoga a come si fa per il campo \var{aio\_sigevent} -di \struct{aiocb}. +L'argomento \param{mode} controlla il comportamento della funzione, se viene +usato il valore \const{LIO\_WAIT} la funzione si blocca fino al completamento +di tutte le operazioni richieste; se si usa \const{LIO\_NOWAIT} la funzione +ritorna immediatamente dopo aver messo in coda tutte le richieste. In tal caso +il chiamante può richiedere la notifica del completamento di tutte le +richieste, impostando l'argomento \param{sig} in maniera analoga a come si fa +per il campo \var{aio\_sigevent} di \struct{aiocb}. \section{Altre modalità di I/O avanzato} @@ -1163,37 +1291,34 @@ prototipi sono: \begin{functions} \headdecl{sys/uio.h} - \funcdecl{int readv(int fd, const struct iovec *vector, int count)} Esegue - una lettura vettorizzata da \param{fd} nei \param{count} buffer specificati - da \param{vector}. - - \funcdecl{int writev(int fd, const struct iovec *vector, int count)} Esegue - una scrittura vettorizzata da \param{fd} nei \param{count} buffer - specificati da \param{vector}. + \funcdecl{int readv(int fd, const struct iovec *vector, int count)} + \funcdecl{int writev(int fd, const struct iovec *vector, int count)} + + Eseguono rispettivamente una lettura o una scrittura vettorizzata. \bodydesc{Le funzioni restituiscono il numero di byte letti o scritti in caso di successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato. \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli argomenti (ad esempio \param{count} è maggiore di \const{MAX\_IOVEC}). \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di di avere eseguito una qualunque lettura o scrittura. \item[\errcode{EAGAIN}] \param{fd} è stato aperto in modalità non bloccante e non ci sono dati in lettura. - \item[\errcode{EOPNOTSUPP}] La coda delle richieste è momentaneamente piena. + \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena. \end{errlist} - ed inoltre \errval{EISDIR}, \errval{ENOMEM}, \errval{EFAULT} (se non sono - stato allocati correttamente i buffer specificati nei campi - \var{iov\_base}), più tutti gli ulteriori errori che potrebbero avere le - usuali funzioni di lettura e scrittura eseguite su \param{fd}.} + ed anche \errval{EISDIR}, \errval{EBADF}, \errval{ENOMEM}, \errval{EFAULT} + (se non sono stati allocati correttamente i buffer specificati nei campi + \var{iov\_base}), più gli eventuali errori delle funzioni di lettura e + scrittura eseguite su \param{fd}.} \end{functions} -Entrambe le funzioni usano una struttura \struct{iovec}, definita in -fig.~\ref{fig:file_iovec}, che definisce dove i dati devono essere letti o -scritti. Il primo campo, \var{iov\_base}, contiene l'indirizzo del buffer ed -il secondo, \var{iov\_len}, la dimensione dello stesso. +Entrambe le funzioni usano una struttura \struct{iovec}, la cui definizione è +riportata in fig.~\ref{fig:file_iovec}, che definisce dove i dati devono +essere letti o scritti ed in che quantità. Il primo campo della struttura, +\var{iov\_base}, contiene l'indirizzo del buffer ed il secondo, +\var{iov\_len}, la dimensione dello stesso. \begin{figure}[!htb] \footnotesize \centering @@ -1206,12 +1331,12 @@ il secondo, \var{iov\_len}, la dimensione dello stesso. \label{fig:file_iovec} \end{figure} -I buffer da utilizzare sono indicati attraverso l'argomento \param{vector} che -è un vettore di strutture \struct{iovec}, la cui lunghezza è specificata da -\param{count}. Ciascuna struttura dovrà essere inizializzata per -opportunamente per indicare i vari buffer da/verso i quali verrà eseguito il -trasferimento dei dati. Essi verranno letti (o scritti) nell'ordine in cui li -si sono specificati nel vettore \param{vector}. +La lista dei buffer da utilizzare viene indicata attraverso l'argomento +\param{vector} che è un vettore di strutture \struct{iovec}, la cui lunghezza +è specificata dall'argomento \param{count}. Ciascuna struttura dovrà essere +inizializzata opportunamente per indicare i vari buffer da e verso i quali +verrà eseguito il trasferimento dei dati. Essi verranno letti (o scritti) +nell'ordine in cui li si sono specificati nel vettore \param{vector}. \subsection{File mappati in memoria} @@ -1224,6 +1349,14 @@ 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=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} +\end{figure} Il meccanismo è illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del file viene \textsl{mappata} direttamente nello spazio degli indirizzi del @@ -1236,14 +1369,6 @@ segmento di memoria con quello del file mappato su di esso. Per questo motivo si può parlare tanto di \textsl{file mappato in memoria}, quanto di \textsl{memoria mappata su file}. -\begin{figure}[htb] - \centering - \includegraphics[width=14cm]{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} -\end{figure} - L'uso del \textit{memory-mapping} comporta una notevole semplificazione delle operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer intermedi su cui appoggiare i dati da traferire, poiché questi potranno essere @@ -1360,7 +1485,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 @@ -1452,8 +1577,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 @@ -2748,7 +2876,7 @@ possibilit % LocalWords: flock shared exclusive operation dup inode linked NFS cmd ENOLCK % LocalWords: EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP % LocalWords: switch bsd lockf mandatory SVr sgid group root mount mand TRUNC -% LocalWords: SVID UX Documentation sendfile +% LocalWords: SVID UX Documentation sendfile dnotify inotify NdA %%% Local Variables: