%% fileadv.tex
%%
-%% Copyright (C) 2000-2012 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2013 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",
\itindbeg{file~locking}
-In sez.~\ref{sec:file_sharing} abbiamo preso in esame le modalità in cui un
-sistema unix-like gestisce la condivisione dei file da parte di processi
-diversi. In quell'occasione si è visto come, con l'eccezione dei file aperti
-in \itindex{append~mode} \textit{append mode}, quando più processi scrivono
-contemporaneamente sullo stesso file non è possibile determinare la sequenza
-in cui essi opereranno.
+In sez.~\ref{sec:file_shared_access} abbiamo preso in esame le modalità in cui
+un sistema unix-like gestisce l'accesso concorrente ai file da parte di
+processi diversi. In quell'occasione si è visto come, con l'eccezione dei file
+aperti in \itindex{append~mode} \textit{append mode}, quando più processi
+scrivono contemporaneamente sullo stesso file non è possibile determinare la
+sequenza in cui essi opereranno.
Questo causa la possibilità di una \itindex{race~condition} \textit{race
condition}; in generale le situazioni più comuni sono due: l'interazione fra
file descriptor che fa riferimento ad una voce nella \itindex{file~table}
\textit{file table} corrispondente a quella registrata nel blocco. 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
+sez.~\ref{sec:file_shared_access}, 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}.
La seconda interfaccia per l'\textit{advisory locking} disponibile in Linux è
quella standardizzata da POSIX, basata sulla funzione \func{fcntl}. Abbiamo
già trattato questa funzione nelle sue molteplici possibilità di utilizzo in
-sez.~\ref{sec:file_fcntl}. Quando la si impiega per il \textit{file locking}
-essa viene usata solo secondo il seguente prototipo:
+sez.~\ref{sec:file_fcntl_ioctl}. Quando la si impiega per il \textit{file
+ locking} essa viene usata solo secondo il seguente prototipo:
\begin{prototype}{fcntl.h}{int fcntl(int fd, int cmd, struct flock *lock)}
Applica o rimuove un \textit{file lock} sul file \param{fd}.
Oltre a quanto richiesto tramite i campi di \struct{flock}, l'operazione
effettivamente svolta dalla funzione è stabilita dal valore dall'argomento
-\param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl}, specifica
-l'azione da compiere; i valori relativi al \textit{file locking} sono tre:
+\param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl_ioctl},
+specifica l'azione da compiere; i valori relativi al \textit{file locking}
+sono tre:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{F\_GETLK}] verifica se il \textit{file lock} specificato dalla
struttura puntata da \param{lock} può essere acquisito: in caso negativo
questo comportamento passando alla system call una variabile locale, in modo
da mantenere l'aderenza allo standard POSIX che richiede che il valore di
\param{timeout} non sia modificato.} Inoltre prende un argomento aggiuntivo
-\param{sigmask} che è il puntatore ad una maschera di segnali (si veda
-sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa
-immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della
-funzione.
+\param{sigmask} che è il puntatore ad una \index{maschera~dei~segnali}
+maschera di segnali (si veda sez.~\ref{sec:sig_sigmask}). La maschera
+corrente viene sostituita da questa immediatamente prima di eseguire l'attesa,
+e ripristinata al ritorno della funzione.
L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
\textit{race condition} \itindex{race~condition} quando ci si deve porre in
\end{prototype}
La funzione ha lo stesso comportamento di \func{poll}, solo che si può
-specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di
-segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione
-resterà in attesa, all'uscita viene ripristinata la maschera originale. L'uso
-di questa funzione è cioè equivalente, come illustrato nella pagina di
-manuale, all'esecuzione atomica del seguente codice:
+specificare, con l'argomento \param{sigmask}, il puntatore ad una
+\index{maschera~dei~segnali} maschera di segnali; questa sarà la maschera
+utilizzata per tutto il tempo che la funzione resterà in attesa, all'uscita
+viene ripristinata la maschera originale. L'uso di questa funzione è cioè
+equivalente, come illustrato nella pagina di manuale, all'esecuzione atomica
+del seguente codice:
\includecodesnip{listati/ppoll_means.c}
Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
\label{tab:epoll_ctl_operation}
\end{table}
+% aggiunta EPOLL_CTL_DISABLE con il kernel 3.7, vedi
+% http://lwn.net/Articles/520012/ e http://lwn.net/Articles/520198/
+
La funzione prende sempre come primo argomento un file descriptor di
\textit{epoll}, \param{epfd}, che deve essere stato ottenuto in precedenza con
una chiamata a \func{epoll\_create}. L'argomento \param{fd} indica invece il
\footnotetext[48]{questa modalità è disponibile solo a partire dal kernel
2.6.2.}
+% TODO aggiunto EPOLLWAKEUP con il 3.5
+
+
Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è
l'insieme dei file descriptor da tenere sotto controllo tramite un certo
\textit{epoll descriptor} \param{epfd} attraverso una serie di chiamate a
\textit{epoll} si pone il problema di gestire l'attesa di segnali e di dati
contemporaneamente per le osservazioni fatte in sez.~\ref{sec:file_select},
per fare questo di nuovo è necessaria una variante della funzione di attesa
-che consenta di reimpostare all'uscita una maschera di segnali, analoga alle
-estensioni \func{pselect} e \func{ppoll} che abbiamo visto in precedenza per
-\func{select} e \func{poll}; in questo caso la funzione si chiama
-\funcd{epoll\_pwait}\footnote{la funziona è stata introdotta a partire dal
- kernel 2.6.19, ed è come tutta l'interfaccia di \textit{epoll}, specifica di
- Linux.} ed il suo prototipo è:
+che consenta di reimpostare all'uscita una \index{maschera~dei~segnali}
+maschera di segnali, analoga alle estensioni \func{pselect} e \func{ppoll} che
+abbiamo visto in precedenza per \func{select} e \func{poll}; in questo caso la
+funzione si chiama \funcd{epoll\_pwait}\footnote{la funziona è stata
+ introdotta a partire dal kernel 2.6.19, ed è come tutta l'interfaccia di
+ \textit{epoll}, specifica di Linux.} ed il suo prototipo è:
\begin{prototype}{sys/epoll.h}
{int epoll\_pwait(int epfd, struct epoll\_event * events, int maxevents,
int timeout, const sigset\_t *sigmask)}
\end{prototype}
La funzione è del tutto analoga \funcd{epoll\_wait}, soltanto che alla sua
-uscita viene ripristinata la maschera di segnali originale, sostituita durante
-l'esecuzione da quella impostata con l'argomento \param{sigmask}; in sostanza
-la chiamata a questa funzione è equivalente al seguente codice, eseguito però
-in maniera atomica:
+uscita viene ripristinata la \index{maschera~dei~segnali} maschera di segnali
+originale, sostituita durante l'esecuzione da quella impostata con
+l'argomento \param{sigmask}; in sostanza la chiamata a questa funzione è
+equivalente al seguente codice, eseguito però in maniera atomica:
\includecodesnip{listati/epoll_pwait_means.c}
Si tenga presente che come le precedenti funzioni di \textit{I/O multiplexing}
versione, \funcm{signalfd4}, introdotta con il kernel 2.6.27 e che è quella
che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un
argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della
- maschera dei segnali, il cui valore viene impostato automaticamente dalle
- \acr{glibc}.} il cui prototipo è:
+ \index{maschera~dei~segnali} maschera dei segnali, il cui valore viene
+ impostato automaticamente dalle \acr{glibc}.} il cui prototipo è:
\begin{prototype}{sys/signalfd.h}
{int signalfd(int fd, const sigset\_t *mask, int flags)}
L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere
specificato tramite l'argomento \param{mask}. Questo deve essere passato come
-puntatore ad una maschera di segnali creata con l'uso delle apposite macro già
-illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali
-segnali si intende operare con \func{signalfd}; l'elenco può essere modificato
-con una successiva chiamata a \func{signalfd}. Dato che \signal{SIGKILL} e
-\signal{SIGSTOP} non possono essere intercettati (e non prevedono neanche la
-possibilità di un gestore) un loro inserimento nella maschera verrà ignorato
-senza generare errori.
+puntatore ad una \index{maschera~dei~segnali} maschera di segnali creata con
+l'uso delle apposite macro già illustrate in sez.~\ref{sec:sig_sigset}. La
+maschera deve indicare su quali segnali si intende operare con
+\func{signalfd}; l'elenco può essere modificato con una successiva chiamata a
+\func{signalfd}. Dato che \signal{SIGKILL} e \signal{SIGSTOP} non possono
+essere intercettati (e non prevedono neanche la possibilità di un gestore) un
+loro inserimento nella maschera verrà ignorato senza generare errori.
L'argomento \param{flags} consente di impostare direttamente in fase di
creazione due flag per il file descriptor analoghi a quelli che si possono
quello che useremo per il controllo degli altri. É poi necessario
disabilitare la ricezione dei segnali (nel caso \signal{SIGINT},
\signal{SIGQUIT} e \signal{SIGTERM}) per i quali si vuole la notifica tramite
-file descriptor. Per questo prima li si inseriscono (\texttt{\small 22--25}) in
-una maschera di segnali \texttt{sigmask} che useremo con (\texttt{\small 26})
-\func{sigprocmask} per disabilitarli. Con la stessa maschera si potrà per
-passare all'uso (\texttt{\small 28--29}) di \func{signalfd} per abilitare la
-notifica sul file descriptor \var{sigfd}. Questo poi (\texttt{\small 30--33})
-dovrà essere aggiunto con \func{epoll\_ctl} all'elenco di file descriptor
-controllati con \texttt{epfd}.
+file descriptor. Per questo prima li si inseriscono (\texttt{\small 22--25})
+in una \index{maschera~dei~segnali} maschera di segnali \texttt{sigmask} che
+useremo con (\texttt{\small 26}) \func{sigprocmask} per disabilitarli. Con la
+stessa maschera si potrà per passare all'uso (\texttt{\small 28--29}) di
+\func{signalfd} per abilitare la notifica sul file descriptor
+\var{sigfd}. Questo poi (\texttt{\small 30--33}) dovrà essere aggiunto con
+\func{epoll\_ctl} all'elenco di file descriptor controllati con \texttt{epfd}.
Occorrerà infine (\texttt{\small 35--38}) creare la \textit{named fifo} se
questa non esiste ed aprirla per la lettura (\texttt{\small 39--40}); una
\section{L'accesso \textsl{asincrono} ai file}
-\label{sec:file_asyncronous_access}
+\label{sec:file_asyncronous_operation}
Benché l'\textit{I/O multiplexing} sia stata la prima, e sia tutt'ora una fra
le più diffuse modalità di gestire l'I/O in situazioni complesse in cui si
\subsection{Il \textit{Signal driven I/O}}
-\label{sec:file_asyncronous_operation}
+\label{sec:signal_driven_io}
\itindbeg{signal~driven~I/O}
\const{O\_ASYNC}, che consentirebbe di aprire un file in modalità asincrona,
anche se in realtà è opportuno attivare in un secondo tempo questa modalità
impostando questo flag attraverso l'uso di \func{fcntl} con il comando
-\const{F\_SETFL} (vedi sez.~\ref{sec:file_fcntl}).\footnote{l'uso del flag di
- \const{O\_ASYNC} e dei comandi \const{F\_SETOWN} e \const{F\_GETOWN} per
- \func{fcntl} è specifico di Linux e BSD.} In realtà parlare di apertura in
-modalità asincrona non significa che le operazioni di lettura o scrittura del
-file vengono eseguite in modo asincrono (tratteremo questo, che è ciò che più
-propriamente viene chiamato \textsl{I/O asincrono}, in
+\const{F\_SETFL} (vedi sez.~\ref{sec:file_fcntl_ioctl}).\footnote{l'uso del
+ flag di \const{O\_ASYNC} e dei comandi \const{F\_SETOWN} e \const{F\_GETOWN}
+ per \func{fcntl} è specifico di Linux e BSD.} In realtà parlare di apertura
+in modalità asincrona non significa che le operazioni di lettura o scrittura
+del file vengono eseguite in modo asincrono (tratteremo questo, che è ciò che
+più propriamente viene chiamato \textsl{I/O asincrono}, in
sez.~\ref{sec:file_asyncronous_io}), quanto dell'attivazione un meccanismo di
notifica asincrona delle variazione dello stato del file descriptor aperto in
questo modo.
kernel 2.6, anche per fifo e pipe.} il sistema genera un apposito segnale,
\signal{SIGIO}, tutte le volte che diventa possibile leggere o scrivere dal
file descriptor che si è posto in questa modalità. Inoltre è possibile, come
-illustrato in sez.~\ref{sec:file_fcntl}, selezionare con il comando
+illustrato in sez.~\ref{sec:file_fcntl_ioctl}, selezionare con il comando
\const{F\_SETOWN} di \func{fcntl} quale processo o quale gruppo di processi
dovrà ricevere il segnale. In questo modo diventa possibile effettuare le
operazioni di I/O in risposta alla ricezione del segnale, e non ci sarà più la
supportano meccanismi simili). Alcune di esse sono realizzate, e solo a
partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni
\textsl{comandi} aggiuntivi per la funzione \func{fcntl} (vedi
-sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è
+sez.~\ref{sec:file_fcntl_ioctl}), che divengono disponibili soltanto se si è
definita la macro \macro{\_GNU\_SOURCE} prima di includere \headfile{fcntl.h}.
\itindbeg{file~lease}
il file viene aperto in lettura; in quest'ultimo caso però il \textit{lease}
può essere ottenuto solo se nessun altro processo ha aperto lo stesso file.
-Come accennato in sez.~\ref{sec:file_fcntl} il comando di \func{fcntl} che
-consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che viene
-utilizzato anche per rilasciarlo. In tal caso il file descriptor \param{fd}
-passato a \func{fcntl} servirà come riferimento per il file su cui si vuole
-operare, mentre per indicare il tipo di operazione (acquisizione o rilascio)
-occorrerà specificare come valore dell'argomento \param{arg} di \func{fcntl}
-uno dei tre valori di tab.~\ref{tab:file_lease_fctnl}.
+Come accennato in sez.~\ref{sec:file_fcntl_ioctl} il comando di \func{fcntl}
+che consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che
+viene utilizzato anche per rilasciarlo. In tal caso il file
+descriptor \param{fd} passato a \func{fcntl} servirà come riferimento per il
+file su cui si vuole operare, mentre per indicare il tipo di operazione
+(acquisizione o rilascio) occorrerà specificare come valore
+dell'argomento \param{arg} di \func{fcntl} uno dei tre valori di
+tab.~\ref{tab:file_lease_fctnl}.
\begin{table}[htb]
\centering
essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e
con l'interfaccia di \textit{epoll};\footnote{ed a partire dal kernel 2.6.25 è
stato introdotto anche il supporto per il \itindex{signal~driven~I/O}
- \texttt{signal-driven I/O} trattato in
- sez.~\ref{sec:file_asyncronous_operation}.} siccome gli eventi vengono
-notificati come dati disponibili in lettura, dette funzioni ritorneranno tutte
-le volte che si avrà un evento di notifica. Così, invece di dover utilizzare i
-segnali,\footnote{considerati una pessima scelta dal punto di vista
- dell'interfaccia utente.} si potrà gestire l'osservazione degli eventi con
-una qualunque delle modalità di \textit{I/O multiplexing} illustrate in
-sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare l'osservazione,
-sarà sufficiente chiudere il file descriptor e tutte le risorse allocate
-saranno automaticamente rilasciate.
+ \texttt{signal-driven I/O} trattato in sez.~\ref{sec:signal_driven_io}.}
+siccome gli eventi vengono notificati come dati disponibili in lettura, dette
+funzioni ritorneranno tutte le volte che si avrà un evento di notifica. Così,
+invece di dover utilizzare i segnali,\footnote{considerati una pessima scelta
+ dal punto di vista dell'interfaccia utente.} si potrà gestire l'osservazione
+degli eventi con una qualunque delle modalità di \textit{I/O multiplexing}
+illustrate in sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare
+l'osservazione, sarà sufficiente chiudere il file descriptor e tutte le
+risorse allocate saranno automaticamente rilasciate.
Infine l'interfaccia di \textit{inotify} consente di mettere sotto
osservazione, oltre che una directory, anche singoli file. Una volta creata
socket (si veda sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
lettura sul file descriptor, utilizzando su di esso l'operazione
\const{FIONREAD}.\footnote{questa è una delle operazioni speciali per i file
- (vedi sez.~\ref{sec:file_ioctl}), che è disponibile solo per i socket e per
- i file descriptor creati con \func{inotify\_init}.} Si può così utilizzare
-questa operazione, oltre che per predisporre una operazione di lettura con un
-buffer di dimensioni adeguate, anche per ottenere rapidamente il numero di
-file che sono cambiati.
+ (vedi sez.~\ref{sec:file_fcntl_ioctl}), che è disponibile solo per i socket
+ e per i file descriptor creati con \func{inotify\_init}.} Si può così
+utilizzare questa operazione, oltre che per predisporre una operazione di
+lettura con un buffer di dimensioni adeguate, anche per ottenere rapidamente
+il numero di file che sono cambiati.
Una volta effettuata la lettura con \func{read} a ciascun evento sarà
associata una struttura \struct{inotify\_event} contenente i rispettivi dati.
% \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
% mappata con \func{mremap}, proposto ma pare non
% implementato.\\
+% \const{MAP\_HUGETLB}& da trattare.\\
+% TODO trattare MAP_HUGETLB introdotto con il kernel 2.6.32, e modifiche
+% introdotte con il 3.8 per le dimensioni variabili delle huge pages
+
\hline
\end{tabular}
\caption{Valori possibili dell'argomento \param{flag} di \func{mmap}.}
costanti analoghe (vedi sez.~\ref{sec:sys_limits}) in \headfile{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}).
+sez.~\ref{sec:sys_limits}).
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