X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=67887c80e9eebed448e62ec16837a22ba1e8c491;hp=6c2bfccc4cb177bc1309572285b2c380b871e32b;hb=492c6b5ca2c851077e63d3a53c9f735e854e8765;hpb=05e740c9a3031a4359e9a895b0fb3d582b497d2f diff --git a/fileadv.tex b/fileadv.tex index 6c2bfcc..67887c8 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1461,7 +1461,7 @@ sottodirectory; se si vogliono osservare anche questi sar ulteriori \textit{watch} per ciascuna sottodirectory. Infine usando il flag \const{IN\_ONESHOT} è possibile richiedere una notifica -singola;\footnote{questa funzionalità però è disponibile soltato a partire dal +singola;\footnote{questa funzionalità però è disponibile soltanto a partire dal kernel 2.6.16.} una volta verificatosi uno qualunque fra gli eventi richiesti con \func{inotify\_add\_watch} l'\textsl{osservatore} verrà automaticamente rimosso dalla lista di osservazione e nessun ulteriore evento @@ -1504,7 +1504,6 @@ viene cancellato o un filesystem viene smontato i relativi osservatori vengono rimossi automaticamente e non è necessario utilizzare \func{inotify\_rm\_watch}. - Come accennato l'interfaccia di \textit{inotify} prevede che gli eventi siano notificati come dati presenti in lettura sul file descriptor associato alla coda di notifica. Una applicazione pertanto dovrà leggere i dati da detto file @@ -1544,7 +1543,7 @@ osservatore maschera di bit che identifica il tipo di evento verificatosi; in essa compariranno sia i bit elencati nella prima parte di tab.~\ref{tab:inotify_event_watch}, che gli eventuali valori -aggiuntivi\footnote{questi compaiono solo nel campo \var{maks} di +aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di \struct{inotify\_event}, e non utilizzabili in fase di registrazione dell'osservatore.} di tab.~\ref{tab:inotify_read_event_flag}. @@ -1598,15 +1597,137 @@ osservazione, in tal caso essi contengono rispettivamente il nome del file byte. Il campo \var{name} viene sempre restituito come stringa terminata da NUL, con uno o più zeri di terminazione, a seconda di eventuali necessità di allineamento del risultato, ed il valore di \var{len} corrisponde al totale -della dimensione di \var{name}, zeri aggiuntivi compresi. Questo significa che -le dimensioni di ciascun evento di \textit{inotify} saranno pari al valore -\code{sizeof(\struct{inotify\_event}) + len}. +della dimensione di \var{name}, zeri aggiuntivi compresi. La stringa con il +nome del file viene restituita nella lettura subito dopo la struttura +\struct{inotify\_event}; questo significa che le dimensioni di ciascun evento +di \textit{inotify} saranno pari a \code{sizeof(\struct{inotify\_event}) + + len}. Vediamo allora un esempio dell'uso dell'interfaccia di \textit{inotify} con un -semplice programma che permette di mettere sotto osservazione un file o una -directory. +semplice programma che permette di mettere sotto osservazione uno o più file e +directory. Il programma si chiama \texttt{inotify\_monitor.c} ed il codice +completo è disponibile coi sorgenti allegati alla guida, il corpo principale +del programma, che non contiene la sezione di gestione delle opzioni e le +funzioni di ausilio è riportato in fig.~\ref{fig:inotify_monitor_example}. +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/inotify_monitor.c} + \end{minipage} + \normalsize + \caption{Esempio di codice che usa l'interfaccia di \textit{inotify}.} + \label{fig:inotify_monitor_example} +\end{figure} + +Una volta completata la scansione delle opzioni il corpo principale del +programma inizia controllando (\texttt{\small 11--15}) che sia rimasto almeno +un argomento che indichi quale file o directory mettere sotto osservazione (e +qualora questo non avvenga esce stampando la pagina di aiuto); dopo di che +passa (\texttt{\small 16--20}) all'inizializzazione di \textit{inotify} +ottenendo con \func{inotify\_init} il relativo file descriptor (oppure usce in +caso di errore). + +Il passo successivo è aggiungere (\texttt{\small 21--30}) alla coda di +notifica gli opportuni osservatori per ciascuno dei file o directory indicati +all'invocazione del comando; questo viene fatto eseguendo un ciclo +(\texttt{\small 22--29}) fintanto che la variabile \var{i}, inizializzata a +zero (\texttt{\small 21}) all'inizio del ciclo, è minore del numero totale di +argomenti rimasti. All'interno del ciclo si invoca (\texttt{\small 23}) +\func{inotify\_add\_watch} per ciascuno degli argomenti, usando la maschera +degli eventi data dalla variabile \var{mask} (il cui valore viene impostato +nella scansione delle opzioni), in caso di errore si esce dal programma +altrimenti si incrementa l'indice (\texttt{\small 29}). + +Completa l'inizializzazione di \textit{inotify} inizia il ciclo principale +(\texttt{\small 32--56}) del programma, nel quale si resta in attesa degli +eventi che si intendono osservare. Questo viene fatto eseguendo all'inizio del +ciclo (\texttt{\small 33}) una \func{read} che si bloccherà fintanto che non +si saranno verificati eventi. + +Dato che l'interfaccia di \textit{inotify} può riportare anche più eventi in +una sola lettura, si è avuto cura di passare alla \func{read} un buffer di +dimensioni adeguate, inizializzato in (\texttt{\small 7}) ad un valore di +approssimativamente 512 eventi.\footnote{si ricordi che la quantità di dati + restituita da \textit{inotify} è variabile a causa della diversa lunghezza + del nome del file restituito insieme a \struct{inotify\_event}.} In caso di +errore di lettura (\texttt{\small 35--40}) il programma esce con un messaggio +di errore (\texttt{\small 37--39}), a meno che non si tratti di una +interruzione della system call, nel qual caso (\texttt{\small 36}) si ripete la +lettura. + +Se la lettura è andata a buon fine invece si esegue un ciclo (\texttt{\small + 43--52}) per leggere tutti gli eventi restituiti, al solito si inizializza +l'indice \var{i} a zero (\texttt{\small 42}) e si ripetono le operazioni +(\texttt{\small 43}) fintanto che esso non supera il numero di byte restituiti +in lettura. Per ciascun evento all'interno del ciclo si assegna\footnote{si + noti come si sia eseguito un opportuno \textit{casting} del puntatore.} alla +variabile \var{event} l'indirizzo nel buffer della corrispondente struttura +\struct{inotify\_event} (\texttt{\small 44}), e poi si stampano il numero di +\textit{watch descriptor} (\texttt{\small 45}) ed il file a cui questo fa +riferimento (\texttt{\small 46}), ricavato dagli argomenti passati a riga di +comando sfruttando il fatto che i \textit{watch descriptor} vengono assegnati +in ordine progressivo crescente a partire da 1. + +Qualora sia presente il riferimento ad un nome di file associato all'evento lo +si stampa (\texttt{\small 47--49}); si noti come in questo caso si sia +utilizzato il valore del campo \var{event->len} e non al fatto che +\var{event->name} riporti o meno un puntatore nullo.\footnote{l'interfaccia + infatti, qualora il nome non sia presente, non avvalora il campo + \var{event->name}, che si troverà a contenere quello che era precedentemente + presente nella rispettiva locazione di memoria, nel caso più comune il + puntatore al nome di un file osservato in precedenza.} Si utilizza poi +(\texttt{\small 50}) la funzione \code{printevent}, che interpreta il valore +del campo \var{event->mask} per stampare il tipo di eventi +accaduti.\footnote{per il relativo codice, che non riportiamo in quanto non + essenziale alla comprensione dell'esempio, si possono utilizzare direttamente + i sorgenti allegati alla guida.} Infine (\texttt{\small 51}) si provvede ad +aggiornare l'indice \var{i} per farlo puntare all'evento successivo. + +Se adesso usiamo il programma per mettere sotto osservazione una directory, e +da un altro terminale eseguiamo il comando \texttt{ls} otterremo qualcosa del +tipo di: +\begin{verbatim} +piccardi@gethen:~/gapil/sources$ ./inotify_monitor -a /home/piccardi/gapil/ +Watch descriptor 1 +Observed event on /home/piccardi/gapil/ +IN_OPEN, +Watch descriptor 1 +Observed event on /home/piccardi/gapil/ +IN_CLOSE_NOWRITE, +\end{verbatim} +I lettori più accorti si saranno resi conto che nel ciclo di lettura degli +eventi appena illustrato non viene trattato il caso particolare in cui la +funzione \func{read} restituisce in \var{nread} un valore nullo. Lo si è fatto +perché con \textit{inotify} il ritorno di una \func{read} con un valore nullo +avviene soltanto, come forma di avviso, quando si sia eseguita la funzione +specificando un buffer di dimensione insufficiente a contenere anche un solo +evento. Nel nostro caso le dimensioni erano senz'altro sufficienti, per cui +tale evenienza non si verificherà mai. + +Ci si potrà però chiedere cosa succede se il buffer è sufficiente per un +evento, ma non per tutti gli eventi verificatisi. Come si potrà notare nel +codice illustrato in precedenza non si è presa nessuna precauzione per +verificare che non ci fossero stati troncamenti dei dati. Anche in questo caso +il comportamento scelto è corretto, perché l'interfaccia di \textit{inotify} +garantisce automaticamente, anche quando ne sono presenti in numero maggiore, +di restituire soltanto il numero di eventi che possono rientrare completamente +nelle dimensioni del buffer specificato.\footnote{si avrà cioè, facendo + riferimento sempre al codice di fig.~\ref{fig:inotify_monitor_example}, che + \var{read} sarà in genere minore delle dimensioni di \var{buffer} ed uguale + soltanto qualora gli eventi corrispondano esattamente alle dimensioni di + quest'ultimo.} Se gli eventi sono di più ne saranno restituiti solo quelli +che entrano interamente nel buffer e gli altri saranno restituiti alla +successiva chiamata di \func{read}. + +Infine un'ultima caratteristica dell'interfaccia di \textit{inotify} è che gli +eventi restituiti nella lettura formano una sequenza ordinata, è cioè +garantito che se si esegue uno spostamento di un file gli eventi vengano +generati nella sequenza corretta. L'interfaccia garantisce anche che se si +verificano più eventi consecutivi identici (vale a dire con gli stessi valori +dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono +raggruppati in un solo evento. % TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478 % TODO e man inotify @@ -1999,14 +2120,12 @@ l'operazione sia facilmente eseguibile attraverso una serie multipla di chiamate, ci sono casi in cui si vuole poter contare sulla atomicità delle operazioni. -Per questo motivo BSD 4.2\footnote{Le due funzioni sono riprese da BSD4.4 ed - integrate anche dallo standard Unix 98. Fino alle libc5, Linux usava - \type{size\_t} come tipo dell'argomento \param{count}, una scelta logica, - che però è stata dismessa per restare aderenti allo standard.} ha introdotto -due nuove system call, \funcd{readv} e \funcd{writev}, che permettono di -effettuare con una sola chiamata una lettura o una scrittura su una serie di -buffer (quello che viene chiamato \textsl{I/O vettorizzato}. I relativi -prototipi sono: +Per questo motivo su BSD 4.2 sono state introdotte due nuove system call, +\funcd{readv} e \funcd{writev},\footnote{in Linux le due funzioni sono riprese + da BSD4.4, esse sono previste anche dallo standard POSIX.1-2001.} che +permettono di effettuare con una sola chiamata una lettura o una scrittura su +una serie di buffer (quello che viene chiamato \textsl{I/O vettorizzato}. I +relativi prototipi sono: \begin{functions} \headdecl{sys/uio.h} @@ -2020,11 +2139,11 @@ prototipi sono: assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli - argomenti (ad esempio \param{count} è maggiore di \const{MAX\_IOVEC}). + argomenti (ad esempio \param{count} è maggiore di \const{IOV\_MAX}). \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. + non ci sono dati in lettura. \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena. \end{errlist} ed anche \errval{EISDIR}, \errval{EBADF}, \errval{ENOMEM}, \errval{EFAULT} @@ -2052,10 +2171,132 @@ essere letti o scritti ed in che quantit 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}. +è specificata dall'argomento \param{count}.\footnote{fino alle libc5, Linux + usava \type{size\_t} come tipo dell'argomento \param{count}, una scelta + logica, che però è stata dismessa per restare aderenti allo standard + POSIX.1-2001.} 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}. + +La standardizzazione delle due funzioni all'interno della revisione +POSIX.1-2001 prevede anche che sia possibile avere un limite al numero di +elementi del vettore \param{vector}. Qualora questo sussista, esso deve essere +indicato dal valore dalla costante \const{IOV\_MAX}, definita come le altre +costanti analoghe (vedi sez.~\ref{sec:sys_limits}) in \file{limits.h}; lo +stesso valore deve essere ottenibile in esecuzione tramite la funzione +\func{sysconf} richiedendo l'argomento \const{\_SC\_IOV\_MAX} (vedi +sez.~\ref{sec:sys_sysconf}). + +Nel caso di Linux il limite di sistema è di 1024, però se si usano le +\acr{glibc} queste forniscono un \textit{wrapper} per le system call che si +accorge se una operazione supererà il precedente limite, in tal caso i dati +verranno letti o scritti con le usuali \func{read} e \func{write} usando un +buffer di dimensioni sufficienti appositamente allocato e sufficiente a +contenere tutti i dati indicati da \param{vector}. L'operazione avrà successo +ma si perderà l'atomicità del trasferimento da e verso la destinazione finale. + + +% TODO verificare cosa succederà a preadv e pwritev o alla nuova niovec +% vedi http://lwn.net/Articles/164887/ + + +\subsection{L'I/O diretto fra file descriptor} +\label{sec:file_sendfile_splice} + + +Uno dei problemi che si presenta nella gestione dell'I/O è quello in cui si +devono trasferire grandi quantità di dati da un file descriptor ed un altro; +questo usualmente comporta la lettura dei dati dal primo file descriptor in un +buffer in memoria, da cui essi vengono poi scritti sul secondo. + +Benché il kernel ottimizzi la gestione di questo processo quando si ha a che +fare con file normali, in generale quando i dati da trasferire sono molti si +pone il problema di effettuare trasferimenti di grandi quantità di dati da +kernel space a user space e all'indietro, quando in realtà sarebbe molto più +efficiente tenere tutto in kernel space. Tratteremo in questa sezione alcune +funzioni specialistiche che permettono di ottimizzare le prestazioni in questo +tipo di situazioni. + +La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei +dati fra due file descriptor è \funcd{sendfile}; la funzione è presente in +diverse versioni di Unix,\footnote{la si ritrova ad esempio in FreeBSD, HPUX + ed altri Unix.} ma non è presente né in POSIX.1-2001 né in altri standard, +per cui vengono utilizzati diversi prototipi e semantiche +differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere + programmi portabili.} nel caso di Linux il suo prototipo è: +\begin{functions} + \headdecl{sys/sendfile.h} + + \funcdecl{ssize\_t sendfile(int out\_fd, int in\_fd, off\_t *offset, size\_t + count)} + + Copia dei dati da un file descriptor ad un altro. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EAGAIN}] si è impostata la modalità non bloccante su + \param{out\_fd} e la scrittura si bloccherebbe. + \item[\errcode{EINVAL}] i file descriptor non sono validi, o sono bloccati + o una operazione di \func{mmap} non è disponibile per \param{in\_fd}. + \item[\errcode{EIO}] si è avuto un errore di lettura da \param{in\_fd}. + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per la lettura da + \param{in\_fd}. + \end{errlist} + ed inoltre \errcode{EBADF} e \errcode{EFAULT}. + } +\end{functions} + + +%NdA è da finire, sul perché non è abilitata fra file vedi: +%\href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html} +%{\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}} + + +% TODO documentare la funzione sendfile +% TODO documentare le funzioni tee e splice +% http://kerneltrap.org/node/6505 e http://lwn.net/Articles/178199/ e +% http://lwn.net/Articles/179492/ +% e http://en.wikipedia.org/wiki/Splice_(system_call) +% e http://kerneltrap.org/node/6505 + + + + +\subsection{Gestione avanzata dell'accesso ai dati dei file} +\label{sec:file_fadvise} + +Nell'uso generico dell'interfaccia per l'accesso al contenuto dei file le +operazioni di lettura e scrittura non necessitano di nessun intervento di +supervisione da parte dei programmi, si eseguirà una \func{read} o una +\func{write}, i dati verranno passati al kernel che provvederà ad effettuare +tutte le operazioni (e a gestire il \textit{caching} dei dati) per portarle a +termine in quello che ritiene essere il modo più efficiente. + +Il problema è che il concetto di migliore efficienza impiegato dal kernel è +relativo all'uso generico, mentre esistono molti casi in cui ci sono esigenze +specifiche dei singoli programmi, che avendo una conoscenza diretta di come +verranno usati i file, possono necessitare di effettuare delle ottimizzazioni +specifiche, relative alle proprie modalità di I/O sugli stessi. Tratteremo in +questa sezione una serie funzioni che consentono ai programmi di ottimizzare +il loro accesso ai dati dei file. + + +% TODO documentare \func{madvise} +% TODO documentare \func{mincore} +% TODO documentare \func{posix\_fadvise} +% vedi http://insights.oetiker.ch/linux/fadvise.html +% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html +% TODO documentare \func{fallocate}, introdotta con il 2.6.23 +% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/ + + +%\subsection{L'utilizzo delle porte di I/O} +%\label{sec:file_io_port} +% +% TODO l'I/O sulle porte di I/O +% consultare le manpage di ioperm, iopl e outb \subsection{File mappati in memoria} @@ -2071,7 +2312,7 @@ file in una sezione dello spazio di indirizzi del processo. che lo ha allocato \begin{figure}[htb] \centering - \includegraphics[width=10cm]{img/mmap_layout} + \includegraphics[width=12cm]{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} @@ -2308,7 +2549,7 @@ effettive del file o della sezione che si vuole mappare. \begin{figure}[!htb] \centering - \includegraphics[width=12cm]{img/mmap_boundary} + \includegraphics[width=13cm]{img/mmap_boundary} \caption{Schema della mappatura in memoria di una sezione di file di dimensioni non corrispondenti al bordo di una pagina.} \label{fig:file_mmap_boundary} @@ -2351,7 +2592,7 @@ che sono utilizzabili solo con questa interfaccia. \begin{figure}[htb] \centering - \includegraphics[width=12cm]{img/mmap_exceed} + \includegraphics[width=13cm]{img/mmap_exceed} \caption{Schema della mappatura in memoria di file di dimensioni inferiori alla lunghezza richiesta.} \label{fig:file_mmap_exceed} @@ -2682,104 +2923,6 @@ mappatura che gi \itindend{memory~mapping} -\subsection{L'I/O diretto fra file descriptor} -\label{sec:file_sendfile_splice} - - -Uno dei problemi che si presenta nella gestione dell'I/O è quello in cui si -devono trasferire grandi quantità di dati da un file descriptor ed un altro; -questo usualmente comporta la lettura dei dati dal primo file descriptor in un -buffer in memoria, da cui essi vengono poi scritti sul secondo. - -Benché il kernel ottimizzi la gestione di questo processo quando si ha a che -fare con file normali, in generale quando i dati da trasferire sono molti si -pone il problema di effettuare trasferimenti di grandi quantità di dati da -kernel space a user space e all'indietro, quando in realtà sarebbe molto più -efficiente tenere tutto in kernel space. Tratteremo in questa sezione alcune -funzioni specialistiche che permettono di ottimizzare le prestazioni in questo -tipo di situazioni. - -La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei -dati fra due file descriptor è \funcd{sendfile}; la funzione è presente in -diverse versioni di Unix,\footnote{la si ritrova ad esempio in FreeBSD, HPUX - ed altri Unix.} ma non è presente né in POSIX.1-2001 né in altri standard, -per cui vengono utilizzati diversi prototipi e semantiche -differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere - programmi portabili.} nel caso di Linux il suo prototipo è: -\begin{functions} - \headdecl{sys/sendfile.h} - - \funcdecl{ssize\_t sendfile(int out\_fd, int in\_fd, off\_t *offset, size\_t - count)} - - Copia dei dati da un file descriptor ad un altro. - - \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EAGAIN}] si è impostata la modalità non bloccante su - \param{out\_fd} e la scrittura si bloccherebbe. - \item[\errcode{EINVAL}] i file descriptor non sono validi, o sono bloccati - o una operazione di \func{mmap} non è disponibile per \param{in\_fd}. - \item[\errcode{EIO}] si è avuto un errore di lettura da \param{in\_fd}. - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per la lettura da - \param{in\_fd}. - \end{errlist} - ed inoltre \errcode{EBADF} e \errcode{EFAULT}. - } -\end{functions} - - -%NdA è da finire, sul perché non è abilitata fra file vedi: -%\href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html} -%{\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}} - - -% TODO documentare la funzione sendfile -% TODO documentare le funzioni tee e splice -% http://kerneltrap.org/node/6505 e http://lwn.net/Articles/178199/ e -% http://lwn.net/Articles/179492/ -% e http://en.wikipedia.org/wiki/Splice_(system_call) -% e http://kerneltrap.org/node/6505 - - - - -\subsection{Gestione avanzata dell'accesso ai dati dei file} -\label{sec:file_fadvise} - -Nell'uso generico dell'interfaccia per l'accesso al contenuto dei file le -operazioni di lettura e scrittura non necessitano di nessun intervento di -supervisione da parte dei programmi, si eseguirà una \func{read} o una -\func{write}, i dati verranno passati al kernel che provvederà ad effettuare -tutte le operazioni (e a gestire il \textit{caching} dei dati) per portarle a -termine in quello che ritiene essere il modo più efficiente. - -Il problema è che il concetto di migliore efficienza impiegato dal kernel è -relativo all'uso generico, mentre esistono molti casi in cui ci sono esigenze -specifiche dei singoli programmi, che avendo una conoscenza diretta di come -verranno usati i file, possono necessitare di effettuare delle ottimizzazioni -specifiche, relative alle proprie modalità di I/O sugli stessi. Tratteremo in -questa sezione una serie funzioni che consentono ai programmi di ottimizzare -il loro accesso ai dati dei file. - - -% TODO documentare \func{madvise} -% TODO documentare \func{mincore} -% TODO documentare \func{posix\_fadvise} -% vedi http://insights.oetiker.ch/linux/fadvise.html -% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html -% TODO documentare \func{fallocate}, introdotta con il 2.6.23 -% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/ - - -%\subsection{L'utilizzo delle porte di I/O} -%\label{sec:file_io_port} -% -% TODO l'I/O sulle porte di I/O -% consultare le manpage di ioperm, iopl e outb - - \section{Il file locking} @@ -3196,13 +3339,6 @@ ed impedirle restituendo un errore di \errcode{EDEADLK} alla funzione che cerca di acquisire un lock che porterebbe ad un \itindex{deadlock} \textit{deadlock}. -\begin{figure}[!bht] - \centering \includegraphics[width=13cm]{img/file_posix_lock} - \caption{Schema dell'architettura del file locking, nel caso particolare - del suo utilizzo secondo l'interfaccia standard POSIX.} - \label{fig:file_posix_lock} -\end{figure} - Per capire meglio il funzionamento del file locking in semantica POSIX (che differisce alquanto rispetto da quello di BSD, visto @@ -3221,6 +3357,13 @@ questo caso la titolarit voce nella \itindex{file~table} \textit{file table}, ma con il valore del \acr{pid} del processo. +\begin{figure}[!bht] + \centering \includegraphics[width=13cm]{img/file_posix_lock} + \caption{Schema dell'architettura del file locking, nel caso particolare + del suo utilizzo secondo l'interfaccia standard POSIX.} + \label{fig:file_posix_lock} +\end{figure} + Quando si richiede un lock il kernel effettua una scansione di tutti i lock presenti sul file\footnote{scandisce cioè la \itindex{linked~list} \textit{linked list} delle strutture \struct{file\_lock}, scartando @@ -3673,7 +3816,9 @@ possibilit % LocalWords: Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT % LocalWords: MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one % LocalWords: EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents ctlv ALL DONT HPUX -% LocalWords: FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching +% LocalWords: FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching sysctl instances name +% LocalWords: watches IGNORED ISDIR OVERFLOW overflow UNMOUNT queued cookie ls +% LocalWords: NUL sizeof casting printevent nread %%% Local Variables: