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}
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
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
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}}
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
\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
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|)}
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|(}
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}
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
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.
\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}
% consultare le manpage di ioperm, iopl e outb
+
+
\section{Il file locking}
\label{sec:file_locking}
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
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}
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
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
% 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