il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in
tutti i casi in cui la successiva esecuzione di \func{read} risulti non
- bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
+ bloccante, quindi anche in caso di \textit{end-of-file}; inoltre con Linux
+ possono verificarsi casi particolari, ad esempio quando arrivano dati su un
+ socket dalla rete che poi risultano corrotti e vengono scartati, può
+ accadere che \func{select} riporti il relativo file descriptor come
+ leggibile, ma una successiva \func{read} si blocchi.} il secondo,
\param{writefds}, per verificare la possibilità effettuare una scrittura ed il
-terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
+terzo,
+\param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
urgenti \itindex{out-of-band} su un socket, vedi
sez.~\ref{sec:TCP_urgent_data}).
La funzione è sostanzialmente identica a \func{select}, solo che usa una
struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timeval_struct}) per
indicare con maggiore precisione il timeout e non ne aggiorna il valore in
-caso di interruzione. 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
+caso di interruzione.\footnote{in realtà la system call di Linux aggiorna il
+ valore al tempo rimanente, ma la funzione fornita dalle \acr{glibc} modifica
+ 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.
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ò, fino al
- kernel 2.6.16, non è presente la relativa system call, e la funzione è
+ kernel 2.6.16, non era presente la relativa system call, e la funzione era
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:
+ \textit{race condition} permaneva; in tale situzione si può ricorrere ad una
+ soluzione alternativa, 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; si può 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, vedi articolo LWN http://lwn.net/Articles/176750/
-
-\subsection{La funzione \func{poll}}
+\subsection{Le funzioni \func{poll} e \func{ppoll}}
\label{sec:file_poll}
Nello sviluppo di System V, invece di utilizzare l'interfaccia di
indica un errore nella chiamata, il cui codice viene riportato al solito
tramite \var{errno}.
+Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una
+variante di \func{select} che consente di gestire correttamente la ricezione
+dei segnali nell'attesa su un file descriptor. Con l'introduzione di una
+implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta
+anche una analoga funzione che svolga lo stesso ruolo per \func{poll}.
+
+In questo caso si tratta di una estensione che è specifica di Linux e non è
+prevista da nessuno standard; essa può essere utilizzata esclusivamente se si
+definisce la macro \macro{\_GNU\_SOURCE} ed ovviamente non deve essere usata
+se si ha a cuore la portabilità. La funzione è \funcd{ppoll}, ed il suo
+prototipo è:
+\begin{prototype}{sys/poll.h}
+ {int ppoll(struct pollfd *fds, nfds\_t nfds, const struct timespec *timeout,
+ const sigset\_t *sigmask)}
+
+ La funzione attende un cambiamento di stato su un insieme di file
+ descriptor.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor con attività
+ in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
+ ed in quest'ultimo caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+ degli insiemi.
+ \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] Il valore di \param{nfds} eccede il limite
+ \macro{RLIMIT\_NOFILE}.
+ \end{errlist}
+ ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
+\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:
+\includecodesnip{listati/ppoll_means.c}
+
+Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
+puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
+\func{poll} hanno lo stesso significato, e la funzione restituisce gli stessi
+risultati illustrati in precedenza.
-% TODO accennare a ppoll
+
+% TODO accennare a ppoll vedi articolo LWN http://lwn.net/Articles/176750/
%\subsection{L'interfaccia di \textit{epoll}}
%\label{sec:file_epoll}
% placeholder ...
-% TODO epoll
+% TODO epoll
\section{L'accesso \textsl{asincrono} ai file}
\label{sec:file_asyncronous_access}
In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
che, quando vengono usate con un numero molto grande di file descriptor, non
-hanno buone prestazioni. % aggiungere cenno a epoll quando l'avrò scritta
+hanno buone prestazioni. % TODO aggiungere cenno a epoll quando l'avrò scritta
In tal caso infatti la maggior parte del loro tempo
di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor
tenuti sotto controllo per determinare quali di essi (in genere una piccola
Queste nuove funzionalità sono delle estensioni specifiche, non
standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel
-supportano meccanismi simili). 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 è definita la macro \macro{\_GNU\_SOURCE}
-prima di includere \file{fcntl.h}.
+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 è
+definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}.
\index{file!lease|(}
può ottenere un \textit{lease} soltanto per un file appartenente ad un
\acr{uid} corrispondente a quello del processo. Soltanto un processo con
privilegi di amministratore (cioè con la \itindex{capabilities} capability
-\const{CAP\_LEASE}) può acquisire \textit{lease} su qualunque file.
+\const{CAP\_LEASE}, vedi sez.~\ref{sec:proc_capabilities}) può acquisire
+\textit{lease} su qualunque file.
Se su un file è presente un \textit{lease} quando il \textit{lease breaker}
esegue una \func{truncate} o una \func{open} che confligge con
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
-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.
+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 questo può essere modificato e si può ottenere nel
-gestore il file descriptor che è stato modificato dal contenuto della
-struttura \struct{siginfo\_t}.
+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}.
\index{file!lease|)}
-Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
-certa directory eseguendo \func{fcntl} su un file descriptor \param{fd}
-associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
-l'argomento \param{arg} serve ad indicare per quali classi eventi si vuole
-ricevere la notifica, e prende come valore una maschera binaria composta
-dall'OR aritmetico di una o più delle costanti riportate in
-tab.~\ref{tab:file_notify}.
-
\begin{table}[htb]
\centering
\footnotesize
\label{tab:file_notify}
\end{table}
-A meno di non impostare in maniera esplicita una notifica permanente usando
-\const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una sola
-volta quando si verifica uno qualunque fra gli eventi per i quali la si è
-richiesta. Questo significa che un programma deve registrarsi un'altra volta se
-desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse
+
+Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
+certa directory eseguendo la funzione \func{fcntl} su un file descriptor
+associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
+l'argomento \param{arg} di \func{fcntl} serve ad indicare per quali classi
+eventi si vuole ricevere la notifica, e prende come valore una maschera
+binaria composta dall'OR aritmetico di una o più delle costanti riportate in
+tab.~\ref{tab:file_notify}.
+
+A meno di non impostare in maniera esplicita una notifica permanente usando il
+valore \const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una
+sola volta quando si verifica uno qualunque fra gli eventi per i quali la si è
+richiesta. Questo significa che un programma deve registrarsi un'altra volta
+se desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse
chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi
ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi
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!inotify|(}
+
+Il maggiore problema di \textit{dnotify} è quello della scalabilità, e della
+complessità di gestione dovuta all'uso dei segnali. Per questo motivo 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.}
+
\index{file!dnotify|)}
+L'interfaccia di \textit{inotify} è una caratteristica 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 file
+descriptor. La coda viene creata attraverso la funzione \funcd{inotify\_init},
+il cui prototipo è:
+\begin{prototype}{sys/inotify.h}
+ {int inotify\_init(void)}
+
+ Inizializza una istanza di \textit{inotify}.
+
+ \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
+ $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EMFILE}] si è raggiunto il numero massimo di istanze di
+ \textit{inotify} consentite all'utente.
+ \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+ nel sistema.
+ \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+ l'istanza.
+ \end{errlist}
+}
+\end{prototype}
+
+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
+\textit{inotify}.
+
+Trattandosi di file descriptor a tutti gli effetti, esso potrà essere
+utilizzato con le funzioni \func{select} e \func{poll}. Dato che gli eventi
+vengono notificati come dati disponibili in lettura sul file descriptor
+stesso, dette funzioni ritorneranno tutte le volte che si avrà un evento di
+notifica. Si potrà cioè gestirlo secondo le modalità illustrate in
+sez.~\ref{sec:file_multiplexing}. Inoltre, come per i file descriptor
+associati ai socket (vedi sez.~\ref{sec:sock_ioctl_IP}) si potrà ottenere il
+numero di byte disponibili in lettura eseguendo su di esso l'operazione
+\const{FIONREAD} con \func{ioctl}.
+
+Una volta creata la coda di notifica, ed ottenuto il relativo file descriptor,
+l'interfaccia prevede che si definiscano gli eventi da tenere sotto
+osservazione associando ad esso una \textsl{lista di osservazione} (o
+\textit{watch list}) che indica quali file e directory tenere d'occhio. Per
+gestire la lista di osservazione l'interfaccia fornisce due funzioni, la prima
+è \funcd{inotify\_add\_watch}, il cui prototipo è:
+\begin{prototype}{sys/inotify.h}
+ {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)}
+
+ Aggiunge una voce alla lista di osservazione di \param{fd}.
+
+ \bodydesc{La funzione restituisce un valore positivo in caso di successo, o
+ $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato.
+ \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd}
+ non è un filesystem di \textit{inotify}.
+ \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di
+ osservazione o il kernel non ha potuto allocare una risorsa necessaria.
+ \end{errlist}
+ ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.}
+\end{prototype}
+
+
-\index{file!inotify|)}
% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
-\index{file!inotify|(}
+% TODO e man inotify
+
+\index{file!inotify|)}
+
+
+
\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.
-
+ che lo ha allocato
\begin{figure}[htb]
\centering
- \includegraphics[width=12cm]{img/mmap_layout}
+ \includegraphics[width=10cm]{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}
\begin{table}[htb]
\centering
\footnotesize
- \begin{tabular}[c]{|l|p{10cm}|}
+ \begin{tabular}[c]{|l|p{11cm}|}
\hline
\textbf{Valore} & \textbf{Significato} \\
\hline
\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di
memoria.}
-\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è
- stato implementato in Linux a partire dai kernel della serie 2.4.x.}
+
+\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato
+ implementato in Linux a partire dai kernel della serie 2.4.x; esso consente
+ di creare segmenti di memoria condivisa e torneremo sul suo utilizzo in
+ sez.~\ref{sec:ipc_mmap_anonymous}.}
\footnotetext{questo flag ed il precedente \const{MAP\_POPULATE} sono stati
introdotti nel kernel 2.5.46 insieme alla mappatura non lineare di cui