%% fileadv.tex
%%
-%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
\headdecl{sys/time.h}
\headdecl{sys/types.h}
\headdecl{unistd.h}
- \funcdecl{FD\_ZERO(fd\_set *set)}
+ \funcdecl{void \macro{FD\_ZERO}(fd\_set *set)}
Inizializza l'insieme (vuoto).
- \funcdecl{FD\_SET(int fd, fd\_set *set)}
+ \funcdecl{void \macro{FD\_SET}(int fd, fd\_set *set)}
Inserisce il file descriptor \param{fd} nell'insieme.
- \funcdecl{FD\_CLR(int fd, fd\_set *set)}
+ \funcdecl{void \macro{FD\_CLR}(int fd, fd\_set *set)}
Rimuove il file descriptor \param{fd} nell'insieme.
- \funcdecl{FD\_ISSET(int fd, fd\_set *set)}
+ \funcdecl{int \macro{FD\_ISSET}(int fd, fd\_set *set)}
Controlla se il file descriptor \param{fd} è nell'insieme.
\end{functions}
Dato che in genere non si tengono mai sotto controllo fino a
\const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
-specificare qual'è il numero massimo dei file descriptor indicati nei tre
+specificare qual è il numero massimo dei file descriptor indicati nei tre
insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
e far controllare al kernel una quantità di memoria superiore a quella
necessaria. Questo limite viene indicato tramite l'argomento \param{n}, che
funzione è recente, ed esistono ancora alcune versioni di Unix che non si
comportano in questo modo.} e ciascun insieme viene sovrascritto per
indicare quali sono i file descriptor pronti per le operazioni ad esso
-relative, in modo da poterli controllare con \const{FD\_ISSET}. Se invece si
+relative, in modo da poterli controllare con \macro{FD\_ISSET}. Se invece si
ha un timeout viene restituito un valore nullo e gli insiemi non vengono
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
sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce
alle varie condizioni dei socket torneremo in sez.~\ref{sec:TCP_serv_poll},
dove vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le
-costanti relative ai diversi tipi di dati (come \macro{POLLRDNORM} e
-\macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la
+costanti relative ai diversi tipi di dati (come \const{POLLRDNORM} e
+\const{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la
macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in
testa al file, definirla soltanto prima di includere \file{sys/poll.h} non è
sufficiente.}
Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
presenta notevoli problemi, dato che non è possibile determinare, quando i
-file descriptor sono più di uno, qual'è quello responsabile dell'emissione del
+file descriptor sono più di uno, qual è quello responsabile dell'emissione del
segnale. Inoltre dato che i segnali normali non si accodano (si ricordi quanto
illustrato in sez.~\ref{sec:sig_notification}), in presenza di più file
descriptor attivi contemporaneamente, più segnali emessi nello stesso momento
Oltre alle operazioni di lettura e scrittura l'interfaccia POSIX.1b mette a
disposizione un'altra operazione, quella di sincronizzazione dell'I/O,
-compiuta dalla funzione \func{aio\_fsync}, che ha lo stesso effetto della
+compiuta dalla funzione \funcd{aio\_fsync}, che ha lo stesso effetto della
analoga \func{fsync}, ma viene eseguita in maniera asincrona; il suo prototipo
è:
\begin{prototype}{aio.h}
\end{errlist}
ed inoltre \errval{EISDIR}, \errval{ENOMEM}, \errval{EFAULT} (se non sono
stato allocati correttamente i buffer specificati nei campi
- \func{iov\_base}), più tutti gli ulteriori errori che potrebbero avere le
+ \var{iov\_base}), più tutti gli ulteriori errori che potrebbero avere le
usuali funzioni di lettura e scrittura eseguite su \param{fd}.}
\end{functions}
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. Il meccanismo è
-illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del file viene
-riportata direttamente nello spazio degli indirizzi del programma. Tutte le
-operazioni su questa zona verranno riportate indietro sul file dal meccanismo
-della memoria virtuale\index{memoria~virtuale} che trasferirà il contenuto di
-quel segmento sul file invece che nella swap, per cui si può parlare tanto di
-file mappato in memoria, quanto di memoria mappata su file.
+file in una sezione dello spazio di indirizzi del processo.
+
+Il meccanismo è illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del
+file viene \textsl{mappata} direttamente nello spazio degli indirizzi del
+programma. Tutte le operazioni di lettura e scrittura su variabili contenute
+in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto
+del file attraverso il sistema della memoria virtuale\index{memoria~virtuale}
+che in maniera analoga a quanto avviene per le pagine che vengono salvate e
+rilette nella swap, si incaricherà di sincronizzare il contenuto di quel
+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=7.cm]{img/mmap_layout}
+ \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}
-Tutto questo 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, ma questi potranno essere acceduti
-direttamente nella sezione di memoria mappata; inoltre questa interfaccia è
-più efficiente delle usuali funzioni di I/O, in quanto permette di caricare in
-memoria solo le parti del file che sono effettivamente usate ad un dato
-istante.
+L'uso del \textit{memory-mappung} 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
+acceduti direttamente nella sezione di memoria mappata; inoltre questa
+interfaccia è più efficiente delle usuali funzioni di I/O, in quanto permette
+di caricare in memoria solo le parti del file che sono effettivamente usate ad
+un dato istante.
Infatti, dato che l'accesso è fatto direttamente attraverso la memoria
virtuale,\index{memoria~virtuale} la sezione di memoria mappata su cui si
per le parti effettivamente usate, il tutto in maniera completamente
trasparente al processo; l'accesso alle pagine non ancora caricate avverrà
allo stesso modo con cui vengono caricate in memoria le pagine che sono state
-salvate sullo swap. Infine in situazioni in cui la memoria è scarsa, le
-pagine che mappano un file vengono salvate automaticamente, così come le
-pagine dei programmi vengono scritte sulla swap; questo consente di accedere
-ai file su dimensioni il cui solo limite è quello dello spazio di indirizzi
-disponibile, e non della memoria su cui possono esserne lette delle porzioni.
-
-L'interfaccia prevede varie funzioni per la gestione del \textit{memory mapped
- I/O}, la prima di queste è \funcd{mmap}, che serve ad eseguire la mappatura
-in memoria di un file; il suo prototipo è:
+salvate sullo swap.
+
+Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un file
+vengono salvate automaticamente, così come le pagine dei programmi vengono
+scritte sulla swap; questo consente di accedere ai file su dimensioni il cui
+solo limite è quello dello spazio di indirizzi disponibile, e non della
+memoria su cui possono esserne lette delle porzioni.
+
+L'interfaccia POSIX implementata da Linux prevede varie funzioni per la
+gestione del \textit{memory mapped I/O}, la prima di queste, che serve ad
+eseguire la mappatura in memoria di un file, è \funcd{mmap}; il suo prototipo
+è:
\begin{functions}
\headdecl{unistd.h}
riportati in tab.~\ref{tab:file_mmap_flag}; il valore specificato deve essere
compatibile con la modalità di accesso con cui si è aperto il file.
-L'argomento \param{flags} specifica infine qual'è il tipo di oggetto mappato,
+L'argomento \param{flags} specifica infine qual è il tipo di oggetto mappato,
le opzioni relative alle modalità con cui è effettuata la mappatura e alle
modalità con cui le modifiche alla memoria mappata vengono condivise o
mantenute private al processo che le ha effettuate. Deve essere specificato
visibili agli altri processi che mappano lo stesso
file.\footnotemark Il file su disco però non sarà
aggiornato fino alla chiamata di \func{msync} o
- \func{unmap}), e solo allora le modifiche saranno
+ \func{munmap}), e solo allora le modifiche saranno
visibili per l'I/O convenzionale. Incompatibile
con \const{MAP\_PRIVATE}. \\
\const{MAP\_PRIVATE} & I cambiamenti sulla memoria mappata non vengono
perciò le informazioni relative agli eventuali \textit{file lock} sono
mantenute a livello di inode\index{inode},\footnote{in particolare, come
accennato in fig.~\ref{fig:file_flock_struct}, i \textit{file lock} sono
- mantenuti un una \textit{linked list}\index{linked list} di strutture
- \struct{file\_lock}. La lista è referenziata dall'indirizzo di partenza
- mantenuto dal campo \var{i\_flock} della struttura \struct{inode} (per le
- definizioni esatte si faccia riferimento al file \file{fs.h} nei sorgenti
- del kernel). Un bit del campo \var{fl\_flags} di specifica se si tratta di
- un lock in semantica BSD (\const{FL\_FLOCK}) o POSIX (\const{FL\_POSIX}).}
-dato che questo è l'unico riferimento in comune che possono avere due processi
-diversi che aprono lo stesso file.
+ mantenuti un una \textit{linked~list}\index{\textit{linked list}} di
+ strutture \struct{file\_lock}. La lista è referenziata dall'indirizzo di
+ partenza mantenuto dal campo \var{i\_flock} della struttura \struct{inode}
+ (per le definizioni esatte si faccia riferimento al file \file{fs.h} nei
+ sorgenti del kernel). Un bit del campo \var{fl\_flags} di specifica se si
+ tratta di un lock in semantica BSD (\const{FL\_FLOCK}) o POSIX
+ (\const{FL\_POSIX}).} dato che questo è l'unico riferimento in comune che
+possono avere due processi diversi che aprono lo stesso file.
\begin{figure}[htb]
\centering
voce nella 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 linked list delle strutture
+presenti sul file\footnote{scandisce cioè la
+ \index{\textit{linked~list}}\textit{linked list} delle strutture
\struct{file\_lock}, scartando automaticamente quelle per cui
\var{fl\_flags} non è \const{FL\_POSIX}, così che le due interfacce restano
ben separate.} per verificare se la regione richiesta non si sovrappone ad
lock (bloccante o meno), a seconda dell'opzione \cmd{-b}.
Il programma inizia col controllare (\texttt{\small 11--14}) che venga passato
-un parametro (il file da bloccare), che sia stato scelto (\texttt{\small
+un argomento (il file da bloccare), che sia stato scelto (\texttt{\small
15--18}) il tipo di lock, dopo di che apre (\texttt{\small 19}) il file,
uscendo (\texttt{\small 20--23}) in caso di errore. A questo punto il
comportamento dipende dalla semantica scelta; nel caso sia BSD occorre