X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=fileadv.tex;h=90157c715da86c92208ea7e496c163e12327242b;hb=60e20d29c0515f95b8a171fb33c7214c9bf92021;hp=330bed97ac81bd6bb049ee4953d822d6f7b51618;hpb=b34574d507f26ade7f9d4d120770fc1235ff6dff;p=gapil.git diff --git a/fileadv.tex b/fileadv.tex index 330bed9..90157c7 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -410,13 +410,13 @@ nel campo \var{revents} per notificare delle condizioni di errore. \hline \const{POLLIN} & È possibile la lettura.\\ \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\ - \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\ + \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari.\\ \const{POLLPRI} & È possibile la lettura di \itindex{out-of-band} dati urgenti.\\ \hline \const{POLLOUT} & È possibile la scrittura immediata.\\ - \const{POLLWRNORM}& È possibile la scrittura di dati normali. \\ - \const{POLLWRBAND}& È possibile la scrittura di dati prioritari. \\ + \const{POLLWRNORM}& È possibile la scrittura di dati normali.\\ + \const{POLLWRBAND}& È possibile la scrittura di dati prioritari.\\ \hline \const{POLLERR} & C'è una condizione di errore.\\ \const{POLLHUP} & Si è verificato un hung-up.\\ @@ -668,15 +668,15 @@ delle operazioni cui fanno riferimento. \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{EPOLL\_CTL\_ADD}& aggiunge un nuovo file descriptor da osservare + \const{EPOLL\_CTL\_ADD}& Aggiunge un nuovo file descriptor da osservare \param{fd} alla lista dei file descriptor controllati tramite \param{epfd}, in \param{event} devono essere specificate le modalità di osservazione.\\ - \const{EPOLL\_CTL\_MOD}& modifica le modalità di osservazione del file + \const{EPOLL\_CTL\_MOD}& Modifica le modalità di osservazione del file descriptor \param{fd} secondo il contenuto di \param{event}.\\ - \const{EPOLL\_CTL\_DEL}& rimuove il file descriptor \param{fd} dalla lista + \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista dei file controllati tramite \param{epfd}.\\ \hline \end{tabular} @@ -848,38 +848,45 @@ La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo, oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che indica di non attendere e ritornare immediatamente,\footnote{anche in questo - caso il valore di ritorno sarà nullo.} o $-1$, che indica un'attesa -indefinita. L'argomento \param{maxevents} dovrà invece essere sempre un intero -positivo. + caso il valore di ritorno sarà nullo.} o il valore $-1$, che indica +un'attesa indefinita. L'argomento \param{maxevents} dovrà invece essere sempre +un intero positivo. Come accennato la funzione restituisce i suoi risultati nel vettore di strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era -stato impostato (per il file descriptor per cui si è verificato l'evento) -quando questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o -\const{EPOLL\_CTL\_ADD}. +stato impostato per il file descriptor per cui si è verificato l'evento quando +questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o +\const{EPOLL\_CTL\_ADD}, in questo modo il campo \var{data} consente di +identificare il file descriptor.\footnote{ed è per questo che, come accennato, + è consuetudine usare per \var{data} il valore del file descriptor stesso.} Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da come si è impostata la modalità di osservazione (se \textit{level triggered} o \textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait} -questi vengano combinati. Inoltre qualora su di esso fossero presenti eventi -non ancora notificati, e si effettuasse una modifica dell'osservazione con -\const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla luce delle modifiche. +questi vengano combinati. Inoltre qualora su un file descriptor fossero +presenti eventi non ancora notificati, e si effettuasse una modifica +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 un file descriptor è pronto e resterà -tale fintanto che non si sono completamente esaurite le operazioni su di esso, -questo può essere rilevato con un errore di \errcode{EAGAIN} in una -\func{read} o una \func{write},\footnote{è opportuno ricordare ancora una - volta che l'uso dell'I/O multiplexing richiede di operare sui file in - modalità non bloccante.} ma anche con il fatto che sono stati restituiti -meno dati di quelli richiesti. - -Come per le precedenti \func{select} e \func{poll}, essendo queste funzioni -utiilizzate prevalentemente con i server di rete, tratteremo degli esempi del -loro più avanti, nella trattazione dei socket, ed in particolare in +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'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 con il fatto che sono stati restituiti meno dati di quelli richiesti. + +Come le precedenti \func{select} e \func{poll}, le funzioni dell'interfaccia +di \textit{epoll} vengono utiilizzate prevalentemente con i server di rete, +quando si devono tenere sotto osservazione un gran numero di socket; per +questo motivo rimandiamo di nuovo la trattazione di un esempio concreto a +quando avremo esaminato in dettaglio le caratteristiche dei socket, in +particolare si potrà trovare un programma che utilizza questa interfaccia in sez.~\ref{sec:TCP_sock_multiplexing}. @@ -989,7 +996,7 @@ diventati attivi. L'unico modo per essere sicuri che questo non avvenga impostare la lunghezza della coda dei segnali real-time ad una dimensione identica al valore massimo del numero di file descriptor utilizzabili.\footnote{vale a dire impostare il contenuto di - \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore di quello di + \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di \texttt{/proc/sys/fs/file-max}.} % TODO fare esempio che usa O_ASYNC @@ -1004,27 +1011,29 @@ risposta\footnote{o meglio la non risposta, tanto che questa nelle Unix FAQ \cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered Question}.} è che nell'architettura classica di Unix questo non è possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like -non prevede alcun meccanismo per cui un processo possa essere +classico non prevedeva alcun meccanismo per cui un processo possa essere \textsl{notificato} di eventuali modifiche avvenute su un file. Questo è il motivo per cui i demoni devono essere \textsl{avvisati} in qualche modo\footnote{in genere questo vien fatto inviandogli un segnale di - \const{SIGHUP} che, per convenzione adottata dalla gran parte di detti + \const{SIGHUP} che, per una convenzione adottata dalla gran parte di detti programmi, causa la rilettura della configurazione.} se il loro file di configurazione è stato modificato, perché possano rileggerlo e riconoscere le modifiche. Questa scelta è stata fatta perché provvedere un simile meccanismo a livello -generale comporterebbe un notevole aumento di complessità dell'architettura -della gestione dei file, per fornire una funzionalità necessaria soltanto in -casi particolari. Dato che all'origine di Unix i soli programmi che potevano -avere una tale esigenza erano i demoni, attenendosi a uno dei criteri base -della progettazione, che era di far fare al kernel solo le operazioni -strettamente necessarie e lasciare tutto il resto a processi in user space, -non era stata prevista nessuna funzionalità di notifica. +generico per qualunque file comporterebbe un notevole aumento di complessità +dell'architettura della gestione dei file, il tutto per fornire una +funzionalità che serve soltanto in alcuni casi particolari. Dato che +all'origine di Unix i soli programmi che potevano avere una tale esigenza +erano i demoni, attenendosi a uno dei criteri base della progettazione, che +era di far fare al kernel solo le operazioni strettamente necessarie e +lasciare tutto il resto a processi in user space, non era stata prevista +nessuna funzionalità di notifica. Visto però il crescente interesse nei confronti di una funzionalità di questo -tipo (molto richiesta specialmente nello sviluppo dei programmi ad interfaccia -grafica) sono state successivamente introdotte delle estensioni che +tipo, che è molto richiesta specialmente nello sviluppo dei programmi ad +interfaccia grafica, quando si deve presentare all'utente lo stato del +filesystem, sono state successivamente introdotte delle estensioni che permettessero la creazione di meccanismi di notifica più efficienti dell'unica soluzione disponibile con l'interfaccia tradizionale, che è quella del \itindex{polling} \textit{polling}. @@ -1153,13 +1162,19 @@ 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 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}. +Per risolvere questo problema a partire dal kernel 2.4 è stata allora creata +un'altra interfaccia,\footnote{si ricordi che anche questa è una interfaccia + specifica di Linux che deve essere evitata se si vogliono scrivere progammi + portabili, e che le funzionalità illustrate sono disponibili soltato se è + stata definita la macro \macro{\_GNU\_SOURCE}.} chiamata \textit{dnotify}, +che consente di richiedere una notifica quando una directory, o 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 se ne +può utilizzare un altro.\footnote{e di nuovo, per le ragioni già esposte in + precedenza, è opportuno che si utilizzino dei segnali real-time.} Inoltre, +come in precedenza, si potrà ottenere nel gestore del segnale il file +descriptor che è stato modificato tramite il contenuto della struttura +\struct{siginfo\_t}. \index{file!lease|)} @@ -1189,7 +1204,7 @@ tramite il contenuto della struttura \struct{siginfo\_t}. \const{DN\_ATTRIB} & È stato modificato un attributo di un file con l'esecuzione di una fra \func{chown}, \func{chmod}, \func{utime}.\\ - \const{DN\_MULTISHOT}& richiede una notifica permanente di tutti gli + \const{DN\_MULTISHOT}& Richiede una notifica permanente di tutti gli eventi.\\ \hline \end{tabular} @@ -1221,30 +1236,33 @@ specificare un valore nullo. Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve usare un file descriptor per ciascuna directory che si vuole tenere sotto -controllo, il che porta facilmente ad un eccesso di file aperti. Inoltre -quando la directory è su un dispositivo rimovibile, mantenere un file -descriptor aperto comporta l'impossibilità di smontare il dispositivo e -rimuoverlo, complicando la gestione. - -Un secondo problema è che l'interfaccia consente solo di tenere sotto -controllo il contenuto di una directory; la modifica di un file viene -segnalata, ma poi devo verificare quale è. 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_control}, e per questo in -generale quella di \textit{dnotify} viene considerata una interfaccia di -usabilità problematica. +controllo, il che porta facilmente ad avere un eccesso di file aperti. Inoltre +quando la directory che si controlla è all'interno di un dispositivo +rimovibile, mantenere il relativo file descriptor aperto comporta +l'impossibilità di smontare il dispositivo e di rimuoverlo, il che in genere +complica notevolmente la gestione dell'uso di questi dispositivi. + +Un altro problema è che l'interfaccia di \textit{dnotify} consente solo di +tenere sotto controllo il contenuto di una directory; la modifica di un file +viene segnalata, ma poi è necessario verificare di quale file si tratta +(operazione che può essere molto onerosa quando una directory contiene un gran +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_control}. Per tutta questa serie di motivi in generale +quella di \textit{dnotify} viene considerata una interfaccia di usabilità +problematica. \index{file!dnotify|)} -Per questa serie di motivi, 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.} Questa è una interfaccia 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 singolo file descriptor, risolvendo così il principale -problema di \itindex{dnotify} \textit{dnotify}. La coda viene creata -attraverso la funzione \funcd{inotify\_init}, il cui prototipo è: +Per risolvere i problemi appena illustrati, 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.} Anche questa +è una interfaccia 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 singolo file descriptor, risolvendo così +il principale problema di \itindex{dnotify} \textit{dnotify}. La coda viene +creata attraverso la funzione \funcd{inotify\_init}, il cui prototipo è: \begin{prototype}{sys/inotify.h} {int inotify\_init(void)} @@ -1266,22 +1284,22 @@ attraverso la funzione \funcd{inotify\_init}, il cui prototipo 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 +nessun file su disco, ma che viene utilizzato per notificare gli eventi che si +sono posti in osservazione all'applicazione che usa l'interfaccia di \textit{inotify}. Dato che questo file descriptor non è associato a nessun -file o directory, questo consente di evitare l'inconveniente di non poter -smontare un filesystem i cui file sono tenuti sotto osservazione.\footnote{ed - una delle caratteristiche dell'interfaccia di \textit{inotify} è proprio - quella di notificare il fatto che il filesystem su cui si trova il file o la - directory osservata è stato smontato.} +file o directory, questo consente anche di evitare l'inconveniente di non +poter smontare un filesystem i cui file sono tenuti sotto +osservazione.\footnote{anzi, una delle capacità dell'interfaccia di + \textit{inotify} è proprio quella di notificare il fatto che il filesystem + su cui si trova il file o la directory osservata è stato smontato.} Inoltre trattandosi di un file descriptor a tutti gli effetti, esso potrà -essere utilizzato come argomento per le funzioni \func{select} e \func{poll}, -e siccome gli eventi vengono notificati come dati disponibili in lettura sul -file descriptor, dette funzioni ritorneranno tutte le volte che si avrà un -evento di notifica. Così, invece di dover utilizzare i segnali, si potrà -gestire l'osservazione delle modifiche con l'\textit{I/O multiplexing}, -utilizzando secondo le modalità illustrate in +essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e +con l'interfaccia di \textit{epoll}, e siccome gli eventi vengono notificati +come dati disponibili in lettura sul file descriptor, dette funzioni +ritorneranno tutte le volte che si avrà un evento di notifica. Così, invece di +dover utilizzare i segnali, si potrà gestire l'osservazione delle modifiche +con l'\textit{I/O multiplexing}, utilizzando secondo le modalità illustrate in sez.~\ref{sec:file_multiplexing}. Infine l'interfaccia di \textit{inotify} consente di mettere sotto @@ -1328,30 +1346,32 @@ per una directory, vengono osservati anche su tutti i file che essa contiene. \textbf{Valore} & & \textbf{Significato} \\ \hline \hline - \const{IN\_ACCESS} &$\bullet$& c'è stato accesso al file in + \const{IN\_ACCESS} &$\bullet$& C'è stato accesso al file in lettura.\\ - \const{IN\_ATTRIB} &$\bullet$& ci sono stati cambiamenti sui dati - dell'inode.\\ - \const{IN\_CLOSE\_WRITE} &$\bullet$& è stato chiuso un file aperto in + \const{IN\_ATTRIB} &$\bullet$& Ci sono stati cambiamenti sui dati + dell'inode (o sugli attributi + estesi, vedi + sez.~\ref{sec:file_xattr}).\\ + \const{IN\_CLOSE\_WRITE} &$\bullet$& È stato chiuso un file aperto in scrittura.\\ - \const{IN\_CLOSE\_NOWRITE}&$\bullet$& è stato chiuso un file aperto in + \const{IN\_CLOSE\_NOWRITE}&$\bullet$& È stato chiuso un file aperto in sola lettura.\\ - \const{IN\_CREATE} &$\bullet$& è stato creato un file o una + \const{IN\_CREATE} &$\bullet$& È stato creato un file o una directory in una directory sotto osservazione.\\ - \const{IN\_DELETE} &$\bullet$& è stato cancellato un file o una + \const{IN\_DELETE} &$\bullet$& È stato cancellato un file o una directory in una directory sotto osservazione.\\ - \const{IN\_DELETE\_SELF} & & è stato cancellato il file (o la + \const{IN\_DELETE\_SELF} & & È stato cancellato il file (o la directory) sotto osservazione.\\ - \const{IN\_MODIFY} &$\bullet$& è stato modificato il file.\\ + \const{IN\_MODIFY} &$\bullet$& È stato modificato il file.\\ \const{IN\_MOVE\_SELF} & & è stato rinominato il file (o la directory) sotto osservazione.\\ - \const{IN\_MOVED\_FROM} &$\bullet$& un file è stato spostato fuori dalla + \const{IN\_MOVED\_FROM} &$\bullet$& Un file è stato spostato fuori dalla directory sotto osservazione.\\ - \const{IN\_MOVED\_TO} &$\bullet$& un file è stato spostato nella + \const{IN\_MOVED\_TO} &$\bullet$& Un file è stato spostato nella directory sotto osservazione.\\ - \const{IN\_OPEN} &$\bullet$& un file è stato aperto.\\ + \const{IN\_OPEN} &$\bullet$& Un file è stato aperto.\\ \hline \end{tabular} \caption{Le costanti che identificano i valori per la maschera binaria @@ -1359,7 +1379,7 @@ per una directory, vengono osservati anche su tutti i file che essa contiene. \label{tab:inotify_event_watch} \end{table} -Se non esiste nessun \textit{watch} per il file (o la directory) specificata +Se non esiste nessun \textit{watch} per il file o la directory specificata questo verrà creato per gli eventi specificati dall'argomento \param{mask}, altrimenti la funzione sovrascriverà le impostazioni precedenti. In caso di successo la funzione ritorna un intero positivo, detto \textit{watch @@ -1418,7 +1438,8 @@ numero di file che sono cambiati. % TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/) - +% e le restanti signalfd e timerfd introdotte con il 2.6.22 +% o trovargli un posto migliore \subsection{L'interfaccia POSIX per l'I/O asincrono} @@ -2015,7 +2036,7 @@ tab.~\ref{tab:file_mmap_flag}. da \param{start}, se questo non può essere usato \func{mmap} fallisce. Se si imposta questo flag il valore di \param{start} deve essere allineato - alle dimensioni di una pagina. \\ + alle dimensioni di una pagina.\\ \const{MAP\_SHARED} & I cambiamenti sulla memoria mappata vengono riportati sul file e saranno immediatamente visibili agli altri processi che mappano lo stesso @@ -2023,7 +2044,7 @@ tab.~\ref{tab:file_mmap_flag}. aggiornato fino alla chiamata di \func{msync} o \func{munmap}), e solo allora le modifiche saranno visibili per l'I/O convenzionale. Incompatibile - con \const{MAP\_PRIVATE}. \\ + con \const{MAP\_PRIVATE}.\\ \const{MAP\_PRIVATE} & I cambiamenti sulla memoria mappata non vengono riportati sul file. Ne viene fatta una copia privata cui solo il processo chiamante ha @@ -2033,13 +2054,13 @@ tab.~\ref{tab:file_mmap_flag}. salvate su swap in caso di necessità. Non è specificato se i cambiamenti sul file originale vengano riportati sulla regione - mappata. Incompatibile con \const{MAP\_SHARED}. \\ + mappata. Incompatibile con \const{MAP\_SHARED}.\\ \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare \textit{DoS} \itindex{Denial~of~Service~(DoS)} (veniva usato per segnalare che tentativi di scrittura sul file dovevano fallire con \errcode{ETXTBSY}).\\ - \const{MAP\_EXECUTABLE}& Ignorato. \\ + \const{MAP\_EXECUTABLE}& Ignorato.\\ \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva delle pagine di swap ad uso del meccanismo del \textit{copy on write} \itindex{copy~on~write} @@ -2047,7 +2068,7 @@ tab.~\ref{tab:file_mmap_flag}. modifiche fatte alla regione mappata, in questo caso dopo una scrittura, se non c'è più memoria disponibile, si ha l'emissione di - un \const{SIGSEGV}. \\ + un \const{SIGSEGV}.\\ \const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine mappate.\\ \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica @@ -2065,9 +2086,9 @@ tab.~\ref{tab:file_mmap_flag}. richiesto \const{MAP\_FIXED}.\\ \const{MAP\_POPULATE} & Esegue il \itindex{prefaulting} \textit{prefaulting} delle pagine di memoria - necessarie alla mappatura. \\ + necessarie alla mappatura.\\ \const{MAP\_NONBLOCK} & Esegue un \textit{prefaulting} più limitato che - non causa I/O.\footnotemark \\ + non causa I/O.\footnotemark\\ % \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area % mappata con \func{mremap}, proposto ma pare non % implementato.\\ @@ -2421,7 +2442,7 @@ nuova system call, \funcd{remap\_file\_pages}, il cui prototipo Permette di rimappare non linearmente un precedente \textit{memory mapping}. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + \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{EINVAL}] Si è usato un valore non valido per uno degli @@ -2484,14 +2505,55 @@ mappatura che gi \itindend{memory~mapping} -%\subsection{L'I/O diretto fra file descriptor} -%\label{sec:file_sendfile_splice} +\subsection{L'I/O diretto fra file descriptor} +\label{sec:file_sendfile_splice} -%Uno dei problemi +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 menoria, da cui essi vengono poi scritti sul secondo. -%NdA è da finire, sul perché non è abilitata fra file vedi: +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}} @@ -2501,18 +2563,38 @@ mappatura che gi % 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 del caching dei dati} -%\label{sec:file_fadvise} +\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 inpiegato 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} +% 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} @@ -3257,7 +3339,7 @@ tab.~\ref{tab:file_lockf_type}. \const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono mantenere un lock condiviso sullo stesso file.\\ \const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo - alla volta può mantenere un lock esclusivo su un file. \\ + alla volta può mantenere un lock esclusivo su un file.\\ \const{LOCK\_UN}& Sblocca il file.\\ \const{LOCK\_NB}& Non blocca la funzione quando il lock non è disponibile, si specifica sempre insieme ad una delle altre operazioni