trattazione preliminare di epoll.
-gb%% fileadv.tex
+%% fileadv.tex
%%
%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
-\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD} per le quali serve ad
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD}, per le quali serve ad
indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
-sotto controllo. L'argomento viene ignorato con
+sotto controllo. L'argomento viene ignorato con l'operazione
\const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
che questo fosse un puntatore valido, anche se poi veniva ignorato, a
partire dal 2.6.9 si può specificare anche anche un valore \texttt{NULL}.}
+
+
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
quest'ultima serve sia in ingresso (quando usata con \func{epoll\_ctl}) ad
impostare quali eventi osservare, che in uscita (nei risultati ottenuti con
\func{epoll\_wait}) per ricevere le notifiche degli eventi avvenuti. La sua
-definizione è riportata in fig.~\ref{fig:epoll_event}; il primo campo,
-\var{events}, è una maschera binaria in cui ciascun bit corrisponde o ad un
-tipo di evento, o una modalità di notifica. Detto campo deve essere
-specificato come OR aritmetico delle costanti riportate in
+definizione è riportata in fig.~\ref{fig:epoll_event}.
+
+Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit
+corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo
+deve essere specificato come OR aritmetico delle costanti riportate in
tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, serve ad indicare a
quale file descriptor si intende fare riferimento, ed in astratto può
contenere un valore qualsiasi che permetta di identificarlo, di norma comunque
\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.2.}
-Le modalità di utilizzo di \textit{epoll} prevedano che si definisca un
-insieme di file descriptor da tenere sotto controllo su un \textit{epoll
- descriptor} \param{epfd} con una serie di chiamate a
-\const{EPOLL\_CTL\_ADD}. Il default prevede la notifica in modalità
-\textit{level triggered}, a meno che sul file descriptor non si sia impostata
-la modalità \textit{edge triggered} con \const{EPOLLET}. Si tenga presente
-che è possibile tenere sotto osservazione uno stesso file descriptor su due
-\textit{epoll descriptor} diversi, ed entrambi riceveranno le notifiche, ma la
-pratica è sconsigliata.
-
-Una particolare modalità di notifica è quella impostata con
-\const{EPOLLONESHOT}: quando si è in modalità \textit{edge triggered} l'arrivo
-in rapida successione di dati in blocchi separati causa la generazione di una
-serie di eventi multipli; in questo caso si può utilizzare la modalità
-\textit{one-shot} in cui la notifica viene effettuata solo la prima volta,
-dopo di che il file descriptor osservato, pur restando nella lista di
-\param{epfd}, viene disattivato, e per essere riutilizzato dovrà essere
-riabilitato con una successiva chiamata con \const{EPOLL\_CTL\_MOD}.
-
-
-Infine qualora un file descriptor posto sotto osservazione dovesse essere
-chiuso, esso sarà automaticamente eliminato dall'insieme dei file descriptor
-osservati.
-
-
-
-
-La funzione che consente di attendere è \funcd{epoll\_wait}, il cui prototipo
-è:
+Le modalità di utilizzo di \textit{epoll} prevedano 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
+\const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è che queste
+ chiamate devono essere ripetute per ciascun file descriptor, incorrendo in
+ una perdita di prestazioni qualora il numero di file descriptor sia molto
+ grande; per questo è stato proposto di introdurre come estensione una
+ funzione \func{epoll\_ctlv} che consenta di effettuare con una sola chiamata
+ le impostazioni per un blocco di file descriptor.} L'uso di
+\const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di
+osservazione di un file descriptor che sia già stato aggiunto alla lista di
+osservazione.
+
+Le impostazioni di default prevedono che la notifica degli eventi richiesti
+sia effettuata in modalità \textit{level triggered}, a meno che sul file
+descriptor non si sia impostata la modalità \textit{edge triggered},
+registrandolo con \const{EPOLLET} attivo nel campo \var{events}. Si tenga
+presente che è possibile tenere sotto osservazione uno stesso file descriptor
+su due \textit{epoll descriptor} diversi, ed entrambi riceveranno le
+notifiche, anche se questa pratica è sconsigliata.
+
+Qualora non si abbia più interesse nell'osservazione di un file descriptor lo
+si può rimuovere dalla lista associata a \param{epfd} con
+\const{EPOLL\_CTL\_DEL}; si tenga conto inoltre che i file descriptor sotto
+osservazione che vengono chiusi sono eliminati dalla lista automaticamente e
+non è necessario usare \const{EPOLL\_CTL\_DEL}.
+
+Infine una particolare modalità di notifica è quella impostata con
+\const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti
+quando si è in modalità \textit{edge triggered} l'arrivo in rapida successione
+di dati in blocchi separati\footnote{questo è tipico con i socket di rete, in
+ quanto i dati arrivano a pacchetti.} può causare una generazione di eventi
+(ad esempio segnalazioni di dati in lettura disponibili) anche se la
+condizione è già stata rilevata.\footnote{si avrebbe cioè una rottura della
+ logica \textit{edge triggered}.}
+
+Anche se la situazione è facile da gestire, la si può evitare utilizzando
+\const{EPOLLONESHOT} per impostare la modalità \textit{one-shot}, in cui la
+notifica di un evento viene effettuata una sola volta, dopo di che il file
+descriptor osservato, pur restando nella lista di osservazione, viene
+automaticamente disattivato,\footnote{la cosa avviene contestualmente al
+ ritorno di \func{epoll\_wait} a causa dell'evento in questione.} e per
+essere riutilizzato dovrà essere riabilitato esplicitamente con una successiva
+chiamata con \const{EPOLL\_CTL\_MOD}.
+
+Una volta impostato l'insieme di file descriptor che si vogliono osservare con
+i relativi eventi, la funzione che consente di attendere l'occorrenza di uno
+di tali eventi è \funcd{epoll\_wait}, il cui prototipo è:
\begin{prototype}{sys/epoll.h}
{int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents, int
timeout)}
\item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
della scadenza di \param{timeout}.
\item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
- con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
- l'operazione richiesta con \param{op} non è supportata.
+ con \func{epoll\_create}, o \param{maxevents} non è maggiore di zero.
\end{errlist}
}
\end{prototype}
+La funzione si blocca in attesa di un evento per i file descriptor registrati
+nella lista di osservazione di \param{epfd} fino ad un tempo massimo
+specificato in millisecondi tramite l'argomento \param{timeout}. Gli eventi
+registrati vengono riportati in un vettore di strutture \struct{epoll\_event}
+(che deve essere stato allocato in precedenza) all'indirizzo indicato
+dall'argomento \param{events}, fino ad un numero massimo di eventi impostato
+con l'argomento \param{maxevents}.
+
+La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora
+sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
+oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
+indica di non attendere e ritornare immediatamente,\footnote{anche in questo
+ caso il valore di ritorno sarà nullo.} o $-1$, che indica un'attesa
+indefinita. L'argomento \param{maxevents} dovrà invece essere sempre un intero
+positivo.
+
+Come accennato la funzione restituisce i suoi risultati nel vettore di
+strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
+campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
+eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
+stato impostato (per il file descriptor per cui si è verificato l'evento)
+quando questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}.
+
+Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
+come si è impostata la modalità di osservazione (se \textit{level triggered} o
+\textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
+che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
+questi vengano combinati. Inoltre qualora su di esso fossero presenti eventi
+non ancora notificati, e si effettuasse una modifica dell'osservazione con
+\const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla luce delle modifiche.
+
+Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
+il ritorno di \func{epoll\_wait} indica un file descriptor è pronto e resterà
+tale fintanto che non si sono completamente esaurite le operazioni su di esso,
+questo può essere rilevato con un errore di \errcode{EAGAIN} in una
+\func{read} o una \func{write},\footnote{è opportuno ricordare ancora una
+ volta che l'uso dell'I/O multiplexing richiede di operare sui file in
+ modalità non bloccante.} ma anche con il fatto che sono stati restituiti
+meno dati di quelli richiesti.
+
+Come per le precedenti \func{select} e \func{poll}, essendo queste funzioni
+utiilizzate prevalentemente con i server di rete, tratteremo degli esempi del
+loro più avanti, nella trattazione dei socket, ed in particolare in
+sez.~\ref{sec:TCP_sock_multiplexing}.
+
\itindend{epoll}
-% TODO epoll
-%
+
+
\section{L'accesso \textsl{asincrono} ai file}
\label{sec:file_asyncronous_access}
\textsl{asincrona}, quelle cioè in cui un processo non deve bloccarsi in
attesa della disponibilità dell'accesso al file, ma può proseguire
nell'esecuzione utilizzando invece un meccanismo di notifica asincrono (di
-norma un segnale), per essere avvisato della possibilità di eseguire le
+norma un segnale, ma esistono anche altre interfacce, come \itindex{inotify}
+\textit{inotify}), per essere avvisato della possibilità di eseguire le
operazioni di I/O volute.
-\subsection{Operazioni asincrone sui file}
+\subsection{Il \textit{Signal driven I/O}}
\label{sec:file_asyncronous_operation}
-Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso l'uso
-del flag \const{O\_ASYNC},\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.} aprire un file in modalità asincrona, così come è possibile
-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}).
-
-In realtà in questo caso non si tratta di eseguire delle operazioni di lettura
-o scrittura del file in modo asincrono (tratteremo questo, che più
-propriamente è detto \textsl{I/O asincrono} in
-sez.~\ref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di
-notifica delle variazione dello stato del file descriptor aperto in questo
-modo.
-
-Quello che succede in questo caso è che il sistema genera un segnale
-(normalmente \const{SIGIO}, ma è possibile usarne altri con il comando
-\const{F\_SETSIG} di \func{fcntl}) tutte le volte che diventa possibile
-leggere o scrivere dal file descriptor che si è posto in questa modalità. Si
-può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
+Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso
+l'uso del flag \const{O\_ASYNC},\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.} aprire un file in modalità asincrona, così come è
+possibile 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}).
+
+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. Quello che succede in questo caso è che il
+sistema genera un segnale (normalmente \const{SIGIO}, ma è possibile usarne
+altri con il comando \const{F\_SETSIG} di \func{fcntl}) tutte le volte che
+diventa possibile leggere o scrivere dal file descriptor che si è posto in
+questa modalità.\footnote{questa modalità non è utilizzabile con i file
+ ordinari ma solo con socket, file di terminale o pseudo terminale, e, a
+ partire dal kernel 2.6, anche per fifo e pipe.}
+
+Si può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
sarà più la necessità di restare bloccati in attesa della disponibilità di
-accesso ai file; per questo motivo Stevens chiama questa modalità
-\textit{signal driven I/O}.
-
-Questa è un'altra modalità di gestione I/O, alternativa all'uso di
-\itindex{epoll} \textit{epoll}, che consente di evitare l'uso delle funzioni
-\func{poll} o \func{select} che, come illustrato in sez.~\ref{sec:file_epoll},
-quando vengono usate con un numero molto grande di file descriptor, non hanno
-buone prestazioni.
+accesso ai file.
+
+Per questo motivo Stevens, ed anche le pagine di manuale di
+Linux, chiamano questa modalità ``\textit{Signal driven I/O}''. Questa è
+ancora un'altra modalità di gestione dell'I/O, alternativa all'uso di
+\itindex{epoll} \textit{epoll},\footnote{anche se le prestazioni ottenute con
+ questa tecnica sono inferiori, il vantaggio è che questa modalità è
+ utilizzabile anche con kernel che non supportano \textit{epoll}, come quelli
+ della serie 2.4, ottenendo comunque prestazioni superiori a quelle che si
+ hanno con \func{poll} e \func{select}.} che consente di evitare l'uso delle
+funzioni \func{poll} o \func{select} che, come illustrato in
+sez.~\ref{sec:file_epoll}, quando vengono usate con un numero molto grande di
+file descriptor, non hanno buone prestazioni.
Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
presenta notevoli problemi, dato che non è possibile determinare, quando i
funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
la coda.
-Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
-più assicurare il comportamento corretto per un segnale real-time, invierà al
-suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti i segnali
-in eccesso, e si dovrà allora determinare con un ciclo quali sono i file
-diventati attivi.
+Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
+più assicurare il comportamento corretto per un segnale real-time, invierà al
+suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti i segnali
+in eccesso, e si dovrà allora determinare con un ciclo quali sono i file
+diventati attivi. L'unico modo per essere sicuri che questo non avvenga è di
+impostare la lunghezza della coda dei segnali real-time ad una dimensione
+identica al valore massimo del numero di file descriptor
+utilizzabili.\footnote{vale a dire impostare il contenuto di
+ \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore di quello di
+ \texttt{/proc/sys/fs/file-max}.}
% TODO fare esempio che usa O_ASYNC
In alcuni casi può essere necessario interrompere le operazioni (in genere
quando viene richiesta un'uscita immediata dal programma), per questo lo
-standard POSIX.1b prevede una funzioni apposita, \funcd{aio\_cancel}, che
+standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
permette di cancellare una operazione richiesta in precedenza; il suo
prototipo è:
\begin{prototype}{aio.h}
% LocalWords: dell'inode CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl
% LocalWords: attribute Universe epoll Solaris kqueue level triggered Jonathan
% LocalWords: Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
-% LocalWords: MOD
+% LocalWords: MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one
+% LocalWords: EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents
%%% Local Variables:
\param{newfd} è aperto la duplicazione avverrà su un altro file descriptor).
+
+\subsection{Le funzioni \func{openat}, \func{mkdirat} e affini}
+\label{sec:file_openat}
+
+Un problema che si pone con l'uso della funzione \func{open}, così come per
+molte altre funzioni che accettano come argomenti dei pathname relativi, è
+che, quando un pathname relativo non fa riferimento alla directory di lavoro
+corrente, è possibile che alcuni dei suoi componenti vengano modificati in
+parallelo alla chiamata a \func{open}, e questo lascia aperta la possibilità
+di una \itindex{race~condition} \textit{race condition}.
+
+Inoltre come già accennato, la directory di lavoro corrente è una proprietà
+del singolo processo; questo significa che quando si lavora con i thread essa
+sarà la stessa per tutti, ma esistono molti casi in cui sarebbe invece utile
+che ogni singolo thread avesse la sua directory di lavoro.
+
+Per risolvere questi problemi, riprendendo una interfaccia già presente in
+Solaris, a fianco delle normali funzioni che operano sui file (come
+\func{open}, \func{mkdir}, ecc.) sono state introdotte delle ulteriori
+funzioni, contraddistinte dal suffisso \texttt{at}, che permettono che
+permettano l'apertura di un file (o le rispettive altre operazioni) usando un
+pathname relativo ad una directory specificata.\footnote{l'introduzione è
+ avvenuta su proposta dello sviluppatore principale delle \acr{glibc} Urlich
+ Drepper; le corrispondenti system call sono state inserite nel kernel
+ ufficiale a partire dalla versione 2.6.16, in precedenza era disponibile una
+ emulazione che, sia pure con prestazioni inferiori, funzionava facendo
+ ricorso all'uso del filesystem \textit{proc} con l'apertura del file
+ attraverso il riferimento a pathname del tipo di
+ \texttt{/proc/self/fd/dirfd/relative\_path}.} Benché queste non siano
+funzioni standard esse sono disponibili anche su altri Unix\footnote{oltre al
+ citato Solaris ne è prevista l'inclusione anche in BSD.} e sono state
+proposte per l'inclusione nello standard POSIX.1, nelle future revisioni dello
+stesso.
+
+L'idea è che si apra prima la directory che si vuole usare come base dei
+pathname relativi, e si passi il relativo file descriptor alla funzione che
+userà quella directory come punto di partenza per la relativa
+risoluzione.\footnote{in questo modo, anche quando si lavora con i thread, si
+ può mantenere anche una directory di lavoro diversa per ciascuno di essi.}
+Con queste funzioni si possono anche ottenere grossi aumenti di prestazioni
+quando si devono eseguire operazioni su delle sezioni di albero dei file che
+prevedono gerarchie molto profonde e grandi quantità di file e directory, dato
+che basta eseguire la risoluzione di un pathname una sola volta (nell'apertura
+della directory) e non per ciascun file che essa contiene.
+
+La sintassi generale di queste nuove funzioni è che esse prendano come primo
+argomento il file descriptor della directory da usare come base, mentre gli
+argomenti successivi restano identici a quelli della corrispondente funzione
+ordinaria; ad esempio nel caso di \funcd{openat} avremo che essa è definita
+come:
+\begin{functions}
+ \headdecl{fcntl.h}
+ \funcdecl{int openat(int dirfd, const char *pathname, int flags)}
+ \funcdecl{int openat(int dirfd, const char *pathname, int flags, mode\_t
+ mode))}
+
+ Apre un file usando come directory di lavoro corrente \param{dirfd}.
+
+ \bodydesc{la funzione restituisce gli stessi valori e gli stessi codici di
+ errore di \func{open}, ed in più:
+ \begin{errlist}
+ \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
+ \item[\errcode{ENOTDIR}] \param{pathname} è un pathname relativo, ma
+ \param{dirfd} fa riferimento ad un file.
+ \end{errlist}}
+\end{functions}
+
+In tab.~\ref{tab:file_atfunc_corr} si sono riportate le funzioni introdotte
+con questa nuova interfaccia, con a fianco la corrispondente funzione
+classica. Tranne che nel caso di \func{faccessat} e \func{unlinkat} tutti i
+loro prototipi seguono la convenzione appena vista per \func{openat}, in cui
+agli argomenti della corrispondente funzione classica viene anteposto
+l'argomento \param{dirfd}.\footnote{non staremo pertanto a riportarli uno per
+ uno.}
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Funzione} & \textbf{Corrispondente} \\
+ \hline
+ \hline
+ \func{faccessat} &\func{access} \\
+ \func{fchmodat} &\func{chmod} \\
+ \func{fchownat} &\func{chown} \\
+ \func{fstatat} &\func{stat} \\
+ \func{futimesat} &\func{utimes} \\
+ \func{linkat} &\func{link} \\
+ \func{mkdirat} &\func{mkdir} \\
+ \func{mknodat} &\func{mknod} \\
+ \func{openat} &\func{open} \\
+ \func{readlinkat}&\func{readlink}\\
+ \func{renameat} &\func{rename} \\
+ \func{symlinkat} &\func{symlink} \\
+ \func{unlinkat} &\func{unlink} \\
+ \func{mkfifoat} &\func{mkfifo} \\
+ \hline
+ \end{tabular}
+ \caption{Corrispondenze fra le nuove funzioni ``\texttt{at}'' e le
+ corrispettive funzioni classiche.}
+ \label{tab:file_atfunc_corr}
+\end{table}
+
+Il comportamento delle nuove funzioni è del tutto analogo a quello delle
+corrispettive classiche, con la sola eccezione del fatto che se fra i loro
+argomenti si utilizza un pathname relativo questo sarà risolto rispetto alla
+directory indicata da \param{dirfd}; qualora invece si usi un pathname
+assoluto \param{dirfd} verrà semplicemente ignorato. Infine se per
+\param{dirfd} si usa il valore speciale \const{AT\_FDCWD}, la risoluzione sarà
+effettuata rispetto alla directory di lavoro corrente del processo.
+
+Così come il comportamento, anche i valori di ritorno e le condizioni di
+errore delle nuove funzioni sono gli stessi delle funzioni classiche, agli
+errori si aggiungono però quelli dovuti a valori errati per \param{dirfd}; in
+particolare si avrà un errore di \errcode{EBADF} se esso non è un file
+descriptor valido, ed un errore di \errcode{ENOTDIR} se esso non fa riferimento
+ad una directory.\footnote{tranne il caso in cui si sia specificato un
+ pathname assoluto, nel qual caso, come detto, il valore di \param{dirfd}
+ sarà completamente ignorato.}
+
+Come accennato ci sono due eccezioni alla precedente regola, \func{faccessat}
+e \func{unlinkat}, che tratteremo esplicitamente. Dette funzioni, oltre a
+prendere \param{dirfd} come primo argomento aggiuntivo, prendono un ulteriore
+argomento finale \param{flags}, utilizzato come maschera binaria. Nel caso di
+\funcd{faccessat} avremo cioè:
+\begin{functions}
+ \headdecl{unistd.h}
+ \funcdecl{int faccessat(int dirfd, const char *path, int mode, int flags)}
+
+ Controlla i permessi di accesso.
+
+ \bodydesc{la funzione restituisce gli stessi valori e gli stessi codici di
+ errore di \func{access}, ed in più:
+ \begin{errlist}
+ \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
+ \item[\errcode{ENOTDIR}] \param{pathname} è un pathname relativo, ma
+ \param{dirfd} fa riferimento ad un file.
+ \end{errlist}}
+\end{functions}
+
+La funzione esegue lo stesso controllo di accesso effettuabile con
+\func{access}, ma si può utilizzare l'argomento \param{flags} per modificarne
+il comportamento rispetto a quello ordinario di \func{access}; questo infatti
+può essere specificato come maschera binaria dei seguenti valori:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\const{AT\_EACCESS}] se impostato esegue il controllo dei permessi
+ usando l'\textsl{user-ID effettivo} invece di quello reale (il default come
+ viene fatto da \func{access}).
+\item[\const{AT\_SYMLINK\_NOFOLLOW}] se impostato non esegue la
+ dereferenziazione del link simbolico (il default, come viene fatto da
+ \func{access}), ma effettua il controllo sui permessi del link simbolico
+ stesso.
+\end{basedescript}
+
+Nel caso di \func{unlinkat} l'ulteriore argomento \param{flags} viene inserito
+perché detta funzione può comportarsi sia come analogo sia di \func{unlink}
+che di \func{rmdir}; pertanto il suo prototipo è:
+\begin{functions}
+ \headdecl{fcntl.h}
+ \funcdecl{int unlinkat(int dirfd, const char *pathname, int flags)}
+
+ Rimuove una voce da una directory.
+
+ \bodydesc{la funzione restituisce gli stessi valori e gli stessi codici di
+ errore di \func{unlink} o di \func{rmdir} a seconda del valore di
+ \param{flags}, ed in più:
+ \begin{errlist}
+ \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
+ \item[\errcode{ENOTDIR}] \param{pathname} è un pathname relativo, ma
+ \param{dirfd} fa riferimento ad un file.
+ \end{errlist}}
+\end{functions}
+
+Di default il comportamento di \func{unlinkat} è equivalente a quello che
+avrebbe \func{unlink} applicata a \param{pathname}, fallendo se questo è una
+directory, se però si imposta \param{flags} al valore di
+\const{AT\_REMOVEDIR},\footnote{anche se \param{flags} è una maschera binaria,
+ essendo questo l'unico flag disponibile, lo si può assegnare direttamente.}
+essa si comporterà come \func{rmdir}.
+
+
\subsection{La funzione \func{fcntl}}
\label{sec:file_fcntl}
% TODO estendere la lista delle ioctl sui file
+
% LocalWords: descriptor system call cap like kernel sez l'inode inode VFS tab
% LocalWords: process table struct files flags pos all'inode dentry fig shell
% LocalWords: error POSIX STDIN FILENO STDOUT STDERR unistd read write lseek
% LocalWords: SETFD GETFD GETFL SETFL GETLK SETLK SETLKW GETOWN group SIGURG
% LocalWords: SETOWN GETSIG SETSIG sigaction SIGINFO siginfo SETLEASE lease is
% LocalWords: truncate GETLEASE NOTIFY AND ACCMODE ioctl everything argp all'I
-% LocalWords: framebuffer request ENOTTY CDROM nell'header magic number
-% LocalWords: FIOCLEX FIONCLEX FIOASYNC FIONBIO NOATIME
+% LocalWords: framebuffer request ENOTTY CDROM nell'header magic number openat
+% LocalWords: FIOCLEX FIONCLEX FIOASYNC FIONBIO NOATIME redirezione FIOSETOWN
+% LocalWords: FIOGETOWN FIONREAD mkdirat thread Solaris mkdir at Urlich proc
+% LocalWords: Drepper path dirfd faccessat unlinkat access fchmodat chmod
+% LocalWords: fchownat chown fstatat futimesat utimes linkat mknodat mknod
+% LocalWords: readlinkat readlink renameat rename symlinkat symlink unlink
+% LocalWords: mkfifoat mkfifo FDCWD EACCESS dereferenziazione rmdir
%%% Local Variables:
%%% mode: latex
Ma anche questa implementazione comporta dei problemi; in questo caso infatti
non viene gestita correttamente l'interazione con gli altri segnali; se
-infatti il segnale di allarme interrompe un altro gestore, in questo caso
-l'esecuzione non riprenderà nel gestore in questione, ma nel ciclo
-principale, interrompendone inopportunamente l'esecuzione. Lo stesso tipo di
-problemi si presenterebbero se si volesse usare \func{alarm} per stabilire un
-timeout su una qualunque system call bloccante.
+infatti il segnale di allarme interrompe un altro gestore, l'esecuzione non
+riprenderà nel gestore in questione, ma nel ciclo principale, interrompendone
+inopportunamente l'esecuzione. Lo stesso tipo di problemi si presenterebbero
+se si volesse usare \func{alarm} per stabilire un timeout su una qualunque
+system call bloccante.
Un secondo esempio è quello in cui si usa il segnale per notificare una
qualche forma di evento; in genere quello che si fa in questo caso è impostare
nel gestore un opportuno flag da controllare nel corpo principale del
programma (con un codice del tipo di quello riportato in
-fig.~\ref{fig:sig_event_wrong}).
+fig.~\ref{fig:sig_event_wrong}). La logica è quella di far impostare al
+gestore (\texttt{\small 14-19}) una variabile globale preventivamente
+inizializzata nel programma principale, il quale potrà determinare,
+osservandone il contenuto, l'occorrenza o meno del segnale, e prendere le
+relative azioni conseguenti (\texttt{\small 6-11}).
\begin{figure}[!htb]
\footnotesize\centering
\label{fig:sig_event_wrong}
\end{figure}
-La logica è quella di far impostare al gestore (\texttt{\small 14-19}) una
-variabile globale preventivamente inizializzata nel programma principale, il
-quale potrà determinare, osservandone il contenuto, l'occorrenza o meno del
-segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}).
-
Questo è il tipico esempio di caso, già citato in
sez.~\ref{sec:proc_race_cond}, in cui si genera una \itindex{race~condition}
\textit{race condition}; infatti, in una situazione in cui un segnale è già
L'uso di questo campo permette ad esempio di risolvere il problema residuo
dell'implementazione di \code{sleep} mostrata in
fig.~\ref{fig:sig_sleep_incomplete}. In quel caso infatti se il segnale di
-allarme avesse interrotto un altro gestore questo non sarebbe stato
-eseguito correttamente; la cosa poteva essere prevenuta installando gli altri
-gestori usando \var{sa\_mask} per bloccare \const{SIGALRM} durante la
-loro esecuzione. Il valore di \var{sa\_flag} permette di specificare vari
-aspetti del comportamento di \func{sigaction}, e della reazione del processo
-ai vari segnali; i valori possibili ed il relativo significato sono riportati
-in tab.~\ref{tab:sig_sa_flag}.
+allarme avesse interrotto un altro gestore questo non sarebbe stato eseguito
+correttamente; la cosa poteva essere prevenuta installando gli altri gestori
+usando \var{sa\_mask} per bloccare \const{SIGALRM} durante la loro esecuzione.
+Il valore di \var{sa\_flag} permette di specificare vari aspetti del
+comportamento di \func{sigaction}, e della reazione del processo ai vari
+segnali; i valori possibili ed il relativo significato sono riportati in
+tab.~\ref{tab:sig_sa_flag}.
\begin{table}[htb]
\footnotesize
fermato da uno dei segnali \const{SIGSTOP},
\const{SIGTSTP}, \const{SIGTTIN} o
\const{SIGTTOU}.\\
- \const{SA\_ONESHOT} & Ristabilisce l'azione per il segnale al valore
+ \const{SA\_RESETHAND}& Ristabilisce l'azione per il segnale al valore
predefinito una volta che il gestore è stato
lanciato, riproduce cioè il comportamento della
semantica inaffidabile.\\
- \const{SA\_RESETHAND}& Sinonimo di \const{SA\_ONESHOT}. \\
+ \const{SA\_ONESHOT} & Nome obsoleto, sinonimo non standard di
+ \const{SA\_RESETHAND}; da evitare. \\
+ \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} stack
+ alternativo per l'esecuzione del gestore (vedi
+ sez.~\ref{sec:sig_specific_features}).\\
\const{SA\_RESTART} & Riavvia automaticamente le \textit{slow system
call} quando vengono interrotte dal suddetto
segnale; riproduce cioè il comportamento standard
di BSD.\index{system~call~lente}\\
- \const{SA\_NOMASK} & Evita che il segnale corrente sia bloccato durante
+ \const{SA\_NODEFER} & Evita che il segnale corrente sia bloccato durante
l'esecuzione del gestore.\\
- \const{SA\_NODEFER} & Sinonimo di \const{SA\_NOMASK}.\\
+ \const{SA\_NOMASK} & Nome obsoleto, sinonimo non standard di
+ \const{SA\_NODEFER}.\\
\const{SA\_SIGINFO} & Deve essere specificato quando si vuole usare un
gestore in forma estesa usando
- \var{sa\_sigaction} al posto di \var{sa\_handler}.\\
- \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} stack
- alternativo per l'esecuzione del gestore (vedi
- sez.~\ref{sec:sig_specific_features}).\\
+ \var{sa\_sigaction} al posto di
+ \var{sa\_handler}.\\
+ \const{SA\_NOCLDWAIT}& Se il segnale è \const{SIGCHLD} allora o processi
+ figli non divenire \textit{zombie} quando
+ terminano.\footnotemark \\
\hline
\end{tabular}
\caption{Valori del campo \var{sa\_flag} della struttura \struct{sigaction}.}
\label{tab:sig_sa_flag}
\end{table}
+\footnotetext{questa funzionalità è stata introdotta nel kernel 2.6 e va a
+ modificare il comportamento di \func{waitpid}.}
+
% TODO con il 2.6 sono stati aggiunti SA_NOCLDWAIT e altro, documentare
Come si può notare in fig.~\ref{fig:sig_sigaction} \func{sigaction} permette
\label{tab:sys_mount_flags}
\end{table}
+% TODO aggiornare con i nuovi flag di man mount
+
Per l'impostazione delle caratteristiche particolari di ciascun filesystem si
usa invece l'argomento \param{data} che serve per passare le ulteriori
informazioni necessarie, che ovviamente variano da filesystem a filesystem.
evitando l'errore di \errcode{EBUSY}. In tutti i casi prima dello smontaggio
viene eseguita una sincronizzazione dei dati.
+% TODO documentare MNT_DETACH e MNT_EXPIRE ...
+
Altre due funzioni specifiche di Linux,\footnote{esse si trovano anche su BSD,
ma con una struttura diversa.} utili per ottenere in maniera diretta
informazioni riguardo al filesystem su cui si trova un certo file, sono
tralasceremo la trattazione, rimandando al manuale delle \acr{glibc}
\cite{glibc} per la documentazione completa.
+
+
% TODO scrivere relativamente alle varie funzioni (getfsent e getmntent &C)
\subsection{La gestione delle informazioni su utenti e gruppi}
sez.~\ref{sec:sock_generic_options}) che provvede all'esecuzione di questo
controllo.
+
\section{L'uso dell'I/O multiplexing}
\label{sec:TCP_sock_multiplexing}
anche a questo server le considerazioni finali di
sez.~\ref{sec:TCP_serv_select}.
+% TODO fare esempio con epoll
+
+
% LocalWords: socket TCP client dell'I multiplexing stream three way handshake
% LocalWords: header stack kernel SYN ACK URG syncronize sez bind listen fig