From 3fce8d71dc08554143eaf3613f27289337950ef2 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Wed, 5 Feb 2003 11:53:07 +0000 Subject: [PATCH] Corretta ed integrata la parte relativa alla notifica dei sengali, e sistemate le varie sezioni che fanno riferimento all'uso di sigval_t e sigevent. --- fileadv.tex | 18 ++++---- ipc.tex | 89 +++++++++++++++++++++++++----------- signal.tex | 128 +++++++++++++++++++++++++++++----------------------- 3 files changed, 144 insertions(+), 91 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index 113e0f4..75bc689 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -476,8 +476,8 @@ struct sigevent sigval_t sigev_value; int sigev_signo; int sigev_notify; - sigev_notify_function; - sigev_notify_attributes; + void (*sigev_notify_function)(sigval_t); + pthread_attr_t *sigev_notify_attributes; }; \end{lstlisting} \end{minipage} @@ -493,15 +493,17 @@ notifica del completamento delle operazioni richieste. La struttura riportata in \secref{fig:file_sigevent}; il campo \var{sigev\_notify} è quello che indica le modalità della notifica, esso può assumere i tre valori: \begin{basedescript}{\desclabelwidth{3.0cm}} -\item[\const{SIGEV\_NONE}] Non viene inviata nessuna notifica. +\item[\const{SIGEV\_NONE}] Non viene inviata nessuna notifica. \item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo - chiamante il segnale specificato nel campo \var{sigev\_signo}, se il - gestore è installato con \const{SA\_SIGINFO}, il gli verrà restituito - il valore di \var{sigev\_value} in come valore del campo \var{si\_value} per + chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di + questo è stato installato con \const{SA\_SIGINFO} gli verrà restituito il + valore di \var{sigev\_value} (la cui definizione è in + \figref{fig:sig_sigval}) come valore del campo \var{si\_value} di \struct{siginfo\_t}. \item[\const{SIGEV\_THREAD}] La notifica viene effettuata creando un nuovo - thread che esegue la funzione specificata da \var{sigev\_notify\_function}, - con gli attributi specificati da \var{sigev\_notify\_attribute}. + thread che esegue la funzione specificata da \var{sigev\_notify\_function} + con argomento \var{sigev\_value}, e con gli attributi specificati da + \var{sigev\_notify\_attribute}. \end{basedescript} Le due funzioni base dell'interfaccia per l'I/O asincrono sono diff --git a/ipc.tex b/ipc.tex index de0823f..5f3b5af 100644 --- a/ipc.tex +++ b/ipc.tex @@ -3847,12 +3847,14 @@ processo che esegue la creazione). Le code di messaggi non sono ancora supportate nel kernel ufficiale, esiste però una implementazione sperimentale di Michal Wronski e Krzysztof Benedyczak,\footnote{i patch al kernel e la relativa libreria possono essere - trovati \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc} - {http://www.mat.uni.torun.pl/\~{}wrona/posix\_ipc}.}. In generale, come le -corrispettive del SysV IPC, le code di messaggi sono poco usate, dato che i -socket\index{socket}, nei casi in cui sono sufficienti, sono più comodi, e che -in casi più complessi la comunicazione può essere gestita direttamente con -mutex e memoria condivisa con tutta la flessibilità che occorre. +trovati su +\href{http://www.mat.uni.torun.pl/~wrona/posix_ipc} +{http://www.mat.uni.torun.pl/\~{}wrona/posix\_ipc}.}. +In generale, come le corrispettive del SysV IPC, le code di messaggi sono poco +usate, dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono +più comodi, e che in casi più complessi la comunicazione può essere gestita +direttamente con mutex e memoria condivisa con tutta la flessibilità che +occorre. Per poter utilizzare le code di messaggi, oltre ad utilizzare un kernel cui siano stati opportunamente applicati i relativi patch, occorre utilizzare la @@ -4010,7 +4012,7 @@ essere richiesta da qualche altro processo. Quando si vuole effettivamente rimuovere una coda dal sistema occorre usare la funzione \funcd{mq\_unlink}, il cui prototipo è: \begin{prototype}{mqueue.h} -{int mq_unlink(const char *name)} +{int mq\_unlink(const char *name)} Rimuove una coda di messaggi. @@ -4132,11 +4134,12 @@ prototipi sono: \begin{functions} \headdecl{mqueue.h} - \funcdecl{ssize\_t mq\_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, - unsigned int *msg_prio)} Effettua la ricezione di un messaggio da una coda. + \funcdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t + msg\_len, unsigned int *msg\_prio)} + Effettua la ricezione di un messaggio da una coda. \funcdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t - msg\_len, unsigned int *msg\_prio, const struct timespec *abs'_timeout)} + msg\_len, unsigned int *msg\_prio, const struct timespec *abs\_timeout)} Effettua la ricezione di un messaggio da una coda entro il tempo \param{abs\_timeout}. @@ -4153,25 +4156,34 @@ prototipi sono: \item[\errcode{ETIMEDOUT}] La ricezione del messaggio non è stata effettuata entro il tempo stabilito. \end{errlist} - \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o \errval{EINVAL}.} + ed inoltre \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o + \errval{EINVAL}.} \end{functions} La funzione estrae dalla coda il messaggio a priorità più alta, o il più -vecchio fra quelli della stessa priorità, una volta ricevuto il messaggio +vecchio fra quelli della stessa priorità. Una volta ricevuto il messaggio viene tolto dalla coda e la sua dimensione viene restituita come valore di -ritorno. Se la dimensione specificata da \param{msg\_len} non è sufficiente a -contenere il messaggio le funzioni, al contrario di quanto avveniva nelle code -di messaggi di SysV, ritornano un errore di \errcode{EMSGSIZE} senza estrarre -il messaggio. È pertanto opportuno chiamare sempre \func{mq\_getaddr} prima -di eseguire una ricezione, per allocare per i messaggi dei buffer di -dimensione opportuna. +ritorno. -Se si specifica un valore non nullo per l'argomento \param{msg\_prio} il -valore della priorità del messaggio viene memorizzato all'indirizzo da esso -puntato. Si noti che con le code di messaggi POSIX non si ha la possibilità di -selezionare quale messaggio estrarre in base alla priorità, a differenza di -quanto avveniva con le code di messaggi di SysV che permettono la selezione in -base al valore del campo \var{mtype}. +Se la dimensione specificata da \param{msg\_len} non è sufficiente a contenere +il messaggio, entrambe le funzioni, al contrario di quanto avveniva nelle code +di messaggi di SysV, ritornano un errore di \errcode{EMSGSIZE} senza estrarre +il messaggio. È pertanto opportuno eseguire sempre una chiamata a +\func{mq\_getaddr} prima di eseguire una ricezione, in modo da ottenere la +dimensione massima dei messaggi sulla coda, per poter essere in grado di +allocare dei buffer sufficientemente ampi per la lettura. + +Se si specifica un puntatore per l'argomento \param{msg\_prio} il valore della +priorità del messaggio viene memorizzato all'indirizzo da esso indicato. +Qualora non interessi usare la priorità dei messaggi si può specificare +\var{NULL}, ed usare un valore nullo della priorità nelle chiamate a +\func{mq\_send}. + +Si noti che con le code di messaggi POSIX non si ha la possibilità di +selezionare quale messaggio estrarre con delle condizioni sulla priorità, a +differenza di quanto avveniva con le code di messaggi di SysV che permettono +invece la selezione in base al valore del campo \var{mtype}. Qualora non +interessi usare la priorità dei messaggi si Qualora la coda sia vuota entrambe le funzioni si bloccano, a meno che non si sia selezionata la modalità non bloccante; in tal caso entrambe ritornano @@ -4180,7 +4192,16 @@ differenza fra le due funzioni passato il tempo massimo \param{abs\_timeout} ritorna comunque con un errore di \errcode{ETIMEDOUT}. -Un'altra caratteristica specifica delle code di messaggi POSIX è la +Uno dei problemi sottolineati da Stevens in \cite{UNP2}, comuni ad entrambe le +tipologie di code messaggi, è che non è possibile per chi riceve identificare +chi è che ha inviato il messaggio, in particolare non è possibile sapere da +quale utente esso provenga. Infatti, in mancanza di un meccanismo interno al +kernel, anche se si possono inserire delle informazioni nel messaggio, queste +non possono essere credute, essendo completamente dipendenti da chi lo invia. +Vedremo però come, attraverso l'uso del meccanismo di notifica, sia possibile +superare questo problema. + +Una caratteristica specifica delle code di messaggi POSIX è infatti la possibilità di usufruire di un meccanismo di notifica asincrono; questo può essere attivato usando la funzione \funcd{mq\_notify}, il cui prototipo è: \begin{prototype}{mqueue.h} @@ -4212,13 +4233,18 @@ particolare il campo \var{sigev\_notify} deve essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato sui thread, specificato tramite il valore \const{SIGEV\_THREAD}, non è implementato.} ed il campo \var{sigev\_signo} deve indicare il valore del segnale che sarà -inviato al processo. +inviato al processo. Inoltre il campo \var{sigev\_value} (la cui definizione è +riportata in \figref{fig:sig_sigval}) permette di restituire al gestore del +segnale un valore numerico o un indirizzo. La funzione registra il processo chiamante per la notifica se \param{notification} punta ad una struttura \struct{sigevent} opportunamente inizializzata, o cancella una precedente registrazione se è \val{NULL}. Dato che un solo processo alla volta può essere registrato, la funzione fallisce -con \errcode{EBUSY} se c'è un altro processo già registrato. +con \errcode{EBUSY} se c'è un altro processo già registrato. Si tenga +presente inoltre che alla chiusura del descrittore (e quindi anche all'uscita +del processo) ogni eventuale registrazione di notifica presente viene +cancellata. La notifica avviene all'arrivo di un messaggio in una coda vuota (e non se ci sono messaggi sulla coda), in tal caso il segnale specificato da @@ -4229,6 +4255,15 @@ tenga presente per enventuale messaggio viene immediatamente inviato a quest'ultimo, e per il meccanismo di notifica funziona tutto come se la coda fosse restata vuota. +L'invio del segnale avvalora i campi seguenti campi di \struct{siginfo\_t} (la +cui definizione è in \figref{fig:sig_siginfo_t}): \var{si\_pid} con il +\acr{pid} del processo che ha emesso il segnale, \var{si\_uid} con l'userid +effettivo, \var{si\_code} con \const{SI\_MESGQ}, e \var{si\_errno} a 0. Questo +ci dice che, se si effettua la ricezione usando esclusivamente il meccanismo +di notifica, è possibile ottenere le informazioni sul processo che ha inserito +un messaggio usando un gestore per il segnale in forma estesa (si ricordi +quanto già detto al proposito in \secref{sec:sig_sigaction} e +\secref{sec:sig_real_time}). diff --git a/signal.tex b/signal.tex index 250653e..b304add 100644 --- a/signal.tex +++ b/signal.tex @@ -1889,15 +1889,15 @@ permette\footnote{La possibilit real-time (vedi \secref{sec:sig_real_time}). In precedenza era possibile ottenere alcune informazioni addizionali usando \var{sa\_handler} con un secondo parametro addizionale di tipo \var{sigcontext}, che adesso è - deprecato.} di utilizzare due forme diverse di gestore, da -specificare, a seconda dell'uso o meno del flag \const{SA\_SIGINFO}, -rispettivamente attraverso i campi \var{sa\_sigaction} o \var{sa\_handler}, -(che devono essere usati in maniera alternativa, in certe implementazioni -questi vengono addirittura definiti come \ctyp{union}): la prima è quella -classica usata anche con \func{signal}, la seconda permette invece di usare un -gestore in grado di ricevere informazioni più dettagliate dal sistema, -attraverso la struttura \struct{siginfo\_t}, riportata in -\figref{fig:sig_siginfo_t}. + deprecato.} di utilizzare due forme diverse di gestore, da specificare, a +seconda dell'uso o meno del flag \const{SA\_SIGINFO}, rispettivamente +attraverso i campi \var{sa\_sigaction} o \var{sa\_handler},\footnote{i due + tipi devono essere usati in maniera alternativa, in certe implementazioni + questi campi vengono addirittura definiti come \ctyp{union}.} Quest'ultima +è quella classica usata anche con \func{signal}, mentre la prima permette di +usare un gestore più complesso, in grado di ricevere informazioni più +dettagliate dal sistema, attraverso la struttura \struct{siginfo\_t}, +riportata in \figref{fig:sig_siginfo_t}. \begin{figure}[!htb] \footnotesize \centering @@ -2396,30 +2396,28 @@ presenta dei significativi miglioramenti,\footnote{questa estensione introdotta in Linux a partire dal kernel 2.1.43(?), e dalle \acr{glibc} 2.1(?).} in particolare sono stati superati tre limiti fondamentali dei segnali classici: -\begin{description} +\begin{basedescript}{\desclabelwidth{1cm}\desclabelstyle{\nextlinelabel}} \item[I segnali non sono accumulati] - se più segnali vengono generati prima dell'esecuzione di un gestore questo sarà eseguito una sola volta, ed il processo non sarà in grado di accorgersi di quante volte l'evento che ha generato il segnale è accaduto. -\item[I segnali non trasportano informazione] - +\item[I segnali non trasportano informazione] i segnali classici non prevedono prevedono altra informazione sull'evento che li ha generati se non il fatto che sono stati emessi (tutta l'informazione che il kernel associa ad un segnale è il suo numero). \item[I segnali non hanno un ordine di consegna] - l'ordine in cui diversi segnali vengono consegnati è casuale e non prevedibile. Non è possibile stabilire una priorità per cui la reazione a certi segnali ha la precedenza rispetto ad altri. -\end{description} +\end{basedescript} Per poter superare queste limitazioni lo standard ha introdotto delle nuove caratteristiche, che sono state associate ad una nuova classe di segnali, che -vengono chiamati \textsl{segnali real-time}, in particolare: +vengono chiamati \textsl{segnali real-time}, in particolare le funzionalità +aggiunte sono: -\begin{itemize*} +\begin{enumerate} \item i segnali sono inseriti in una coda che permette di consegnare istanze multiple dello stesso segnale qualora esso venga inviato più volte prima dell'esecuzione del gestore; si assicura così che il processo riceva un @@ -2427,20 +2425,20 @@ vengono chiamati \textsl{segnali real-time}, in particolare: \item è stata introdotta una priorità nella consegna dei segnali: i segnali vengono consegnati in ordine a seconda del loro valore, partendo da quelli con un numero minore, che pertanto hanno una priorità maggiore. -\item è stata introdotta la possibilità di restituire dei dati al - gestore, attraverso l'uso di un campo apposito nella struttura - \struct{siginfo\_t} accessibile tramite gestori di tipo +\item è stata introdotta la possibilità di restituire dei dati al gestore, + attraverso l'uso di un apposito campo \var{si\_value} nella struttura + \struct{siginfo\_t}, accessibile tramite gestori di tipo \var{sa\_sigaction}. -\end{itemize*} +\end{enumerate} -Queste nuove caratteristiche (eccetto l'ultima, che, come visto in -\secref{sec:sig_sigaction}, è parzialmente disponibile anche con i segnali -ordinari) si applicano solo ai nuovi segnali real-time; questi ultimi sono -accessibili in un range di valori specificati dalle due macro \const{SIGRTMIN} -e \const{SIGRTMAX},\footnote{in Linux di solito il primo valore è 32, ed il - secondo \code{\_NSIG-1}, che di norma è 63, per un totale di 32 segnali - disponibili, contro gli almeno 8 richiesti da POSIX.1b.} che specificano il -numero minimo e massimo associato ad un segnale real-time. +Queste nuove funzionalità (eccetto l'ultima, che, come vedremo, è parzialmente +disponibile anche con i segnali ordinari) si applicano solo ai nuovi segnali +real-time; questi ultimi sono accessibili in un range di valori specificati +dalle due macro \const{SIGRTMIN} e \const{SIGRTMAX},\footnote{in Linux di + solito il primo valore è 32, ed il secondo \code{\_NSIG-1}, che di norma è + 63, per un totale di 32 segnali disponibili, contro gli almeno 8 richiesti + da POSIX.1b.} che specificano il numero minimo e massimo associato ad un +segnale real-time. I segnali con un numero più basso hanno una priorità maggiore e vengono consegnati per primi, inoltre i segnali real-time non possono interrompere @@ -2450,37 +2448,54 @@ tutti la stessa priorit real-time. Si tenga presente che questi nuovi segnali non sono associati a nessun evento -specifico (a meno di non utilizzarli, come vedremo in -\secref{sec:file_asyncronous_io}, per l'I/O asincrono) e devono essere inviati -esplicitamente. Tutti i segnali real-time restituiscono al gestore, oltre ai -campi \var{si\_pid} e \var{si\_uid} di \struct{siginfo\_t} una struttura -\struct{sigval} (riportata in \figref{fig:sig_sigval}) in cui può essere -restituito al processo un valore o un indirizzo, che costituisce il meccanismo -con cui il segnale è in grado di inviare una ulteriore informazione al -processo. +specifico, a meno di non utilizzarli in meccanismi di notifica come quelli per +l'I/O asincrono (vedi \secref{sec:file_asyncronous_io}) o per le code di +messaggi POSIX (vedi \secref{sec:ipc_posix_mq}); pertanto devono essere +inviati esplicitamente. + +Inoltre per poter usufruire della capacità di restituire dei dati i relativi +gestori devono essere installati con \func{sigaction} specificando la modalità +\const{SA\_SIGINFO} che permette di utilizzare la forma estesa +\var{sa\_sigaction} (vedi \secref{sec:sig_sigaction}). In questo modo tutti i +segnali real-time possono restituire al gestore una serie di informazioni +aggiuntive attraverso l'argomento \struct{siginfo\_t} (la cui definizione è +riportata in \figref{fig:sig_siginfo_t}). + +In particolare i campi utilizzati dai segnali real-time sono \var{si\_pid} e +\var{si\_uid} in cui vengono memorizzati rispettivamente \acr{pid} e userid +effettivo del processo che ha inviato il segnale, mentre per la restituzione +dei dati viene usato il campo \var{si\_value}, questo è una \ctyp{union} di +tipo \struct{sigval\_t} (la sua definizione è in \figref{fig:sig_sigval}) in +cui può essere memorizzato o un valore numerico o un indirizzo,\footnote{un + campo di tipo \struct{sigval\_t} è presente anche nella struttura + \struct{sigevent} che viene usata dai meccanismi di notifica come quelli per + l'I/O asincrono (vedi \secref{sec:file_asyncronous_io}) o le code di + messaggi POSIX (vedi \secref{sec:ipc_posix_mq}).} \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} -union sigval { +union sigval_t { int sival_int; void *sival_ptr; } \end{lstlisting} \end{minipage} \normalsize - \caption{La struttura \structd{sigval}, usata dai segnali real time per - restituire dati al gestore.} + \caption{La struttura \structd{sigval\_t}, una \ctyp{union} usata dai + segnali real-time e dai meccanismi di notifica per restituire dati al + gestore, (in alcune definizione essa viene identificata anche come + \code{union sigval}).} \label{fig:sig_sigval} \end{figure} -A causa di queste loro caratteristiche, la funzione \func{kill} non è adatta -ad inviare un segnale real time, in quanto non è in grado di fornire alcun -valore per \struct{sigval}; per questo motivo lo standard ha previsto una -nuova funzione, \funcd{sigqueue}, il cui prototipo è: +A causa delle loro caratteristiche, la funzione \func{kill} non è adatta ad +inviare segnali real-time, poichè non è in grado di fornire alcun valore +per \struct{sigval\_t}; per questo motivo lo standard ha previsto una nuova +funzione, \funcd{sigqueue}, il cui prototipo è: \begin{prototype}{signal.h} - {int sigqueue(pid\_t pid, int signo, const union sigval value)} + {int sigqueue(pid\_t pid, int signo, const sigval\_t value)} Invia il segnale \param{signo} al processo \param{pid}, restituendo al gestore il valore \param{value}. @@ -2506,16 +2521,17 @@ di errore senza inviare nessun segnale. Se il segnale è bloccato la funzione ritorna immediatamente, se si è installato un gestore con \const{SA\_SIGINFO} e ci sono risorse disponibili, -vale a dire che c'è posto nella coda\footnote{la profondità della coda è - indicata dalla costante \const{SIGQUEUE\_MAX}, una della tante costanti di - sistema definite dallo standard POSIX, che non abbiamo riportato - esplicitamente in \secref{sec:sys_limits}. Il suo valore minimo secondo lo - standard, \const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32.}, esso viene inserito -e diventa pendente; una volta consegnato riporterà nel campo \var{si\_code} di -\struct{siginfo} il valore \const{SI\_QUEUE} e il campo \var{si\_value} -riceverà quanto inviato con \param{value}. Se invece si è installato un -gestore nella forma classica il segnale sarà generato, ma tutte le -caratteristiche tipiche dei segnali real-time (priorità e coda) saranno perse. +(vale a dire che c'è posto\footnote{la profondità della coda è indicata dalla + costante \const{SIGQUEUE\_MAX}, una della tante costanti di sistema definite + dallo standard POSIX, che non abbiamo riportato esplicitamente in + \secref{sec:sys_limits}. Il suo valore minimo secondo lo standard, + \const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32.} nella coda) esso viene +inserito e diventa pendente; una volta consegnato riporterà nel campo +\var{si\_code} di \struct{siginfo} il valore \const{SI\_QUEUE} e il campo +\var{si\_value} riceverà quanto inviato con \param{value}. Se invece si è +installato un gestore nella forma classica il segnale sarà generato, ma tutte +le caratteristiche tipiche dei segnali real-time (priorità e coda) saranno +perse. Lo standard POSIX.1b definisce inoltre delle nuove funzioni che permettono di gestire l'attesa di segnali specifici su una coda, esse servono in particolar @@ -2596,7 +2612,6 @@ di timeout nullo, e non ci sono segnali pendenti la funzione ritorner immediatamente; in questo modo si può eliminare un segnale dalla coda senza dover essere bloccati qualora esso non sia presente. - L'uso di queste funzioni è principalmente associato alla gestione dei segnali com i thread. In genere esse vengono chiamate dal thread incaricato della gestione, che al ritorno della funzione esegue il codice che usualmente @@ -2607,6 +2622,7 @@ che, per evitare che venga eseguita l'azione predefinita, i segnali gestiti in questa maniera devono essere mascherati per tutti i thread, compreso quello dedicato alla gestione, che potrebbe riceverlo fra due chiamate successive. + %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" -- 2.30.2