From 0465908c904030ae51b43e72afa328e8dda27fd9 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 24 Jun 2007 21:05:13 +0000 Subject: [PATCH] Inserite funzioni "at", alcune modifiche per sigaction, finita trattazione preliminare di epoll. --- fileadv.tex | 235 ++++++++++++++++++++++++++++++++++----------------- fileunix.tex | 192 ++++++++++++++++++++++++++++++++++++++++- signal.tex | 60 +++++++------ system.tex | 6 ++ tcpsock.tex | 4 + 5 files changed, 392 insertions(+), 105 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index 9a717f2..ee49313 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1,4 +1,4 @@ -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 @@ -694,13 +694,15 @@ file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}. 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} @@ -717,10 +719,11 @@ La struttura \struct{epoll\_event} 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 @@ -764,35 +767,54 @@ si usa come valore lo stesso \param{fd}. \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)} @@ -808,16 +830,61 @@ La funzione che consente di attendere \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} @@ -830,44 +897,52 @@ contesto le modalit \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 @@ -905,11 +980,16 @@ un file su cui l'accesso 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 @@ -1575,7 +1655,7 @@ operazioni di sincronizzazione dei dati saranno completate. 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} @@ -3318,7 +3398,8 @@ possibilit % 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: diff --git a/fileunix.tex b/fileunix.tex index 09bcbd2..0b134c4 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -1053,6 +1053,188 @@ file descriptor libero di valore uguale o maggiore di \param{newfd} (e se \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} @@ -1323,6 +1505,7 @@ anche tramite \func{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 @@ -1342,8 +1525,13 @@ anche tramite \func{fcntl}. % 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 diff --git a/signal.tex b/signal.tex index 7d3751b..2d9d439 100644 --- a/signal.tex +++ b/signal.tex @@ -1553,17 +1553,21 @@ vuoto. 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 @@ -1576,11 +1580,6 @@ fig.~\ref{fig:sig_event_wrong}). \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à @@ -1738,13 +1737,13 @@ l'invocazione. 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 @@ -1759,30 +1758,39 @@ in tab.~\ref{tab:sig_sa_flag}. 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 diff --git a/system.tex b/system.tex index cb01cfd..ec3a084 100644 --- a/system.tex +++ b/system.tex @@ -793,6 +793,8 @@ valori riportati in tab.~\ref{tab:sys_mount_flags}. \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. @@ -854,6 +856,8 @@ seconda del tipo di filesystem alcune (o tutte) possono essere superate, 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 @@ -913,6 +917,8 @@ semplice invocare direttamente il programma \cmd{mount}, per cui ne 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} diff --git a/tcpsock.tex b/tcpsock.tex index 9382638..a2c674a 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -2744,6 +2744,7 @@ impostazione speciale del socket (ci torneremo in 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} @@ -3580,6 +3581,9 @@ quanto l'uscita 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 -- 2.30.2