X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=fileadv.tex;h=75f299f9376e70667cf660044fbf942eb962267f;hb=7281907d38ca9d916bff5a3579c61d805a33c71d;hp=e7b93dcff3d3448739fbf361f88340e119f7d55c;hpb=74b559a3958675adf01c9a906cdd485eaf399290;p=gapil.git diff --git a/fileadv.tex b/fileadv.tex index e7b93dc..75f299f 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -127,10 +127,10 @@ degli insiemi specificati (\param{readfds}, \param{writefds} e Per specificare quali file descriptor si intende \textsl{selezionare}, la funzione usa un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo \type{fd\_set}, che serve ad identificare un insieme di -file descriptor, in maniera analoga a come un -\itindex{signal~set}\textit{signal set} (vedi sez.~\ref{sec:sig_sigset}) -identifica un insieme di segnali. Per la manipolazione di questi \textit{file - descriptor set} si possono usare delle opportune macro di preprocessore: +file descriptor, in maniera analoga a come un \itindex{signal~set} +\textit{signal set} (vedi sez.~\ref{sec:sig_sigset}) identifica un insieme di +segnali. Per la manipolazione di questi \textit{file descriptor set} si +possono usare delle opportune macro di preprocessore: \begin{functions} \headdecl{sys/time.h} \headdecl{sys/types.h} @@ -185,7 +185,6 @@ ritorni; se impostato a \val{NULL} la funzione attende indefinitamente. Si pu specificare anche un tempo nullo (cioè una struttura \struct{timeval} con i campi impostati a zero), qualora si voglia semplicemente controllare lo stato corrente dei file descriptor. -\itindend{file~descriptor~set} La funzione restituisce il numero di file descriptor pronti,\footnote{questo è il comportamento previsto dallo standard, ma la standardizzazione della @@ -198,6 +197,8 @@ modificati. In caso di errore la funzione restituisce -1, ed i valori dei tre insiemi sono indefiniti e non si può fare nessun affidamento sul loro contenuto. +\itindend{file~descriptor~set} + In Linux \func{select} modifica anche il valore di \param{timeout}, impostandolo al tempo restante in caso di interruzione prematura; questo è utile quando la funzione viene interrotta da un segnale, in tal caso infatti @@ -291,25 +292,26 @@ 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ò non è - presente la relativa system call, e la funzione è 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 manipolatore; 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: +contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al + kernel 2.6.26, non è presente la relativa system call, e la funzione è + 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: \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 +% ppoll mettere e verificare, vedi articolo LWN http://lwn.net/Articles/176750/ \subsection{La funzione \func{poll}} @@ -595,11 +597,10 @@ il segnale \const{SIGIO}, ma questo segnale pu comando \const{F\_SETSIG} di \func{fcntl}.\footnote{anche in questo caso si può rispecificare lo stesso \const{SIGIO}.} Se si è fatto questo\footnote{è in genere è opportuno farlo, come in precedenza, per utilizzare segnali - real-time.} e si è installato il manipolatore del segnale con -\const{SA\_SIGINFO} si riceverà nel campo \var{si\_fd} della struttura -\struct{siginfo\_t} il valore del file descriptor del file sul quale è stato -compiuto l'accesso; in questo modo un processo può mantenere anche più di un -\textit{file lease}. + real-time.} e si è installato il gestore del segnale con \const{SA\_SIGINFO} +si riceverà nel campo \var{si\_fd} della struttura \struct{siginfo\_t} il +valore del file descriptor del file sul quale è stato compiuto l'accesso; in +questo modo un processo può mantenere anche più di un \textit{file lease}. Esistono due tipi di \textit{file lease}: di lettura (\textit{read lease}) e di scrittura (\textit{write lease}). Nel primo caso la notifica avviene quando @@ -688,7 +689,7 @@ kernel \textit{lease breaker} rimaste bloccate proseguono automaticamente. -\index{file!notify|(} +\index{file!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 @@ -696,12 +697,13 @@ 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. -Per risolvere questo problema è stata allora creata un'altra interfaccia 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 manipolatore il file descriptor -che è stato modificato dal contenuto della struttura \struct{siginfo\_t}. +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}. \index{file!lease|)} @@ -758,18 +760,13 @@ ultimi si \textsl{accumulano}; cio 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!notify|)} - - - - - - +\index{file!dnotify|)} -% TODO inserire anche inotify +\index{file!inotify|)} +% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478 +\index{file!inotify|(} @@ -1140,7 +1137,8 @@ Oltre alle precedenti modalit accesso ai file più evolute rispetto alle normali funzioni di lettura e scrittura che abbiamo esaminato in sez.~\ref{sec:file_base_func}. In questa sezione allora prenderemo in esame le interfacce per l'\textsl{I/O - vettorizzato} e per l'\textsl{I/O mappato in memoria}. + vettorizzato} e per l'\textsl{I/O mappato in memoria} e la funzione +\func{sendfile}. \subsection{I/O vettorizzato} @@ -1343,7 +1341,7 @@ multiplo della dimensione di una pagina di memoria. Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux la memoria reale è divisa in pagine: ogni processo vede la sua memoria attraverso uno o più segmenti lineari di memoria virtuale. Per ciascuno di - questi segmenti il kernel mantiene nella \itindex{page~table}\textit{page + questi segmenti il kernel mantiene nella \itindex{page~table} \textit{page table} la mappatura sulle pagine di memoria reale, ed le modalità di accesso (lettura, esecuzione, scrittura); una loro violazione causa quella che si chiama una \textit{segment violation}, e la relativa emissione del @@ -1675,7 +1673,6 @@ una combinazione dei valori di tab.~\ref{tab:file_mmap_prot}. La nuova protezione verrà applicata a tutte le pagine contenute, anche parzialmente, dall'intervallo fra \param{addr} e \param{addr}+\param{size}-1. - Infine Linux supporta alcune operazioni specifiche non disponibili su altri kernel unix-like. La prima di queste è la possibilità di modificare un precedente \textit{memory mapping}, ad esempio per espanderlo o restringerlo. @@ -1838,6 +1835,19 @@ mappatura che gi \itindend{memory~mapping} +\subsection{L'I/O diretto fra file descriptor con \func{sendfile}} +\label{sec:file_sendfile} + +Uno dei problemi + +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 + + + % i raw device %\subsection{I \textit{raw} device} %\label{sec:file_raw_device} @@ -1852,6 +1862,8 @@ mappatura che gi % consultare le manpage di ioperm, iopl e outb + + \section{Il file locking} \label{sec:file_locking} @@ -2060,38 +2072,42 @@ piuttosto degli ulteriori riferimenti allo stesso. Questo viene realizzato dal kernel secondo lo schema di fig.~\ref{fig:file_flock_struct}, associando ad ogni nuovo \textit{file lock} un puntatore\footnote{il puntatore è mantenuto nel campo \var{fl\_file} di \struct{file\_lock}, e viene utilizzato solo per - i lock creati con la semantica BSD.} alla voce nella \textit{file table} da -cui si è richiesto il lock, che così ne identifica il titolare. + i lock creati con la semantica BSD.} alla voce nella \itindex{file~table} +\textit{file table} da cui si è richiesto il lock, che così ne identifica il +titolare. Questa struttura prevede che, quando si richiede la rimozione di un file lock, il kernel acconsenta solo se la richiesta proviene da un file descriptor che -fa riferimento ad una voce nella file table corrispondente a quella registrata -nel lock. Allora se ricordiamo quanto visto in sez.~\ref{sec:file_dup} e -sez.~\ref{sec:file_sharing}, e cioè che i file descriptor duplicati e quelli -ereditati in un processo figlio puntano sempre alla stessa voce nella file -table, si può capire immediatamente quali sono le conseguenze nei confronti -delle funzioni \func{dup} e \func{fork}. +fa riferimento ad una voce nella \itindex{file~table} \textit{file table} +corrispondente a quella registrata nel lock. Allora se ricordiamo quanto +visto in sez.~\ref{sec:file_dup} e sez.~\ref{sec:file_sharing}, e cioè che i +file descriptor duplicati e quelli ereditati in un processo figlio puntano +sempre alla stessa voce nella \itindex{file~table} \textit{file table}, si può +capire immediatamente quali sono le conseguenze nei confronti delle funzioni +\func{dup} e \func{fork}. Sarà così possibile rimuovere un file lock attraverso uno qualunque dei file -descriptor che fanno riferimento alla stessa voce nella file table, anche se -questo è diverso da quello con cui lo si è creato,\footnote{attenzione, questo - non vale se il file descriptor fa riferimento allo stesso file, ma - attraverso una voce diversa della file table, come accade tutte le volte che - si apre più volte lo stesso file.} o se si esegue la rimozione in un -processo figlio; inoltre una volta tolto un file lock, la rimozione avrà -effetto su tutti i file descriptor che condividono la stessa voce nella file -table, e quindi, nel caso di file descriptor ereditati attraverso una -\func{fork}, anche su processi diversi. +descriptor che fanno riferimento alla stessa voce nella \itindex{file~table} +\textit{file table}, anche se questo è diverso da quello con cui lo si è +creato,\footnote{attenzione, questo non vale se il file descriptor fa + riferimento allo stesso file, ma attraverso una voce diversa della + \itindex{file~table} \textit{file table}, come accade tutte le volte che si + apre più volte lo stesso file.} o se si esegue la rimozione in un processo +figlio; inoltre una volta tolto un file lock, la rimozione avrà effetto su +tutti i file descriptor che condividono la stessa voce nella +\itindex{file~table} \textit{file table}, e quindi, nel caso di file +descriptor ereditati attraverso una \func{fork}, anche su processi diversi. Infine, per evitare che la terminazione imprevista di un processo lasci attivi dei file lock, quando un file viene chiuso il kernel provveda anche a rimuovere tutti i lock ad esso associati. Anche in questo caso occorre tenere presente cosa succede quando si hanno file descriptor duplicati; in tal caso infatti il file non verrà effettivamente chiuso (ed il lock rimosso) fintanto -che non viene rilasciata la relativa voce nella file table; e questo avverrà -solo quando tutti i file descriptor che fanno riferimento alla stessa voce -sono stati chiusi. Quindi, nel caso ci siano duplicati o processi figli che -mantengono ancora aperto un file descriptor, il lock non viene rilasciato. +che non viene rilasciata la relativa voce nella \itindex{file~table} +\textit{file table}; e questo avverrà solo quando tutti i file descriptor che +fanno riferimento alla stessa voce sono stati chiusi. Quindi, nel caso ci +siano duplicati o processi figli che mantengono ancora aperto un file +descriptor, il lock non viene rilasciato. Si tenga presente infine che \func{flock} non è in grado di funzionare per i file mantenuti su NFS, in questo caso, se si ha la necessità di eseguire il @@ -2283,7 +2299,8 @@ di fig.~\ref{fig:file_flock_struct}:\footnote{in questo caso nella figura si impostato il bit \const{FL\_POSIX} ed il campo \var{fl\_file} non viene usato.} il lock è sempre associato all'inode\index{inode}, solo che in questo caso la titolarità non viene identificata con il riferimento ad una -voce nella file table, ma con il valore del \acr{pid} del processo. +voce nella \itindex{file~table} \textit{file table}, ma con il valore del +\acr{pid} del processo. Quando si richiede un lock il kernel effettua una scansione di tutti i lock presenti sul file\footnote{scandisce cioè la \itindex{linked~list} @@ -2613,7 +2630,7 @@ opportune verifiche nei processi, questo verrebbe comunque rispettato. Per poter utilizzare il \textit{mandatory locking} è stato introdotto un utilizzo particolare del bit \itindex{sgid~bit} \acr{sgid}. Se si ricorda -quanto esposto in sez.~\ref{sec:file_suid_sgid}), esso viene di norma +quanto esposto in sez.~\ref{sec:file_special_perm}), esso viene di norma utilizzato per cambiare il group-ID effettivo con cui viene eseguito un programma, ed è pertanto sempre associato alla presenza del permesso di esecuzione per il gruppo. Impostando questo bit su un file senza permesso di @@ -2622,9 +2639,10 @@ quest'ultimo venga attivato per il file in questione. In questo modo una combinazione dei permessi originariamente non contemplata, in quanto senza significato, diventa l'indicazione della presenza o meno del \textit{mandatory locking}.\footnote{un lettore attento potrebbe ricordare quanto detto in - sez.~\ref{sec:file_chmod} e cioè che il bit \acr{sgid} viene cancellato - (come misura di sicurezza) quando di scrive su un file, questo non vale - quando esso viene utilizzato per attivare il \textit{mandatory locking}.} + sez.~\ref{sec:file_perm_management} e cioè che il bit \acr{sgid} viene + cancellato (come misura di sicurezza) quando di scrive su un file, questo + non vale quando esso viene utilizzato per attivare il \textit{mandatory + locking}.} L'uso del \textit{mandatory locking} presenta vari aspetti delicati, dato che neanche l'amministratore può passare sopra ad un lock; pertanto un processo @@ -2734,4 +2752,4 @@ 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 +% LocalWords: SVID UX Documentation sendfile