From aa6e7fc3085168384700494a4bd22208f71e089e Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Tue, 18 Feb 2003 23:06:08 +0000 Subject: [PATCH 1/1] Finita parte sulle code di messaggi POSIX, iniziato a scrivere qualcosa sui futex --- ipc.tex | 107 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/ipc.tex b/ipc.tex index 5f3b5af..9676970 100644 --- a/ipc.tex +++ b/ipc.tex @@ -4199,11 +4199,11 @@ 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. +superare in parte 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 è: +Una caratteristica specifica delle code di messaggi POSIX è 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} {int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)} @@ -4221,49 +4221,69 @@ Attiva il meccanismo di notifica per la coda \param{mqdes}. Il meccanismo di notifica permette di segnalare in maniera asincrona ad un processo la presenza di dati sulla coda, in modo da evitare la necessità di bloccarsi nell'attesa. Per far questo un processo deve registrarsi con la -funzione \func{mq\_notify}, il meccanismo è disponibile per un solo processo -alla volta per ogni coda. +funzione \func{mq\_notify}, ed il meccanismo è disponibile per un solo +processo alla volta per ciascuna coda. Il comportamento di \func{mq\_notify} dipende dal valore dell'argomento -\param{notification}, che è un puntatore ad una struttura \struct{sigevent} -(la cui definizione è in \figref{fig:file_sigevent}) che abbiamo già -incontrato in \secref{sec:file_asyncronous_io}. Attraverso questa struttura -si possono impostare le modalità con cui viene effettuata la notifica; in -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. 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. +\param{notification}, che è un puntatore ad una apposita struttura +\struct{sigevent}, (definita in \figref{fig:file_sigevent}) introdotta dallo +standard POSIX.1b per gestire la notifica di eventi; per altri dettagli si può +vedere quanto detto in \secref{sec:file_asyncronous_io} a proposito dell'uso +della stessa struttura per l'invio dei segnali usati per l'I/O asincrono. + +Attraverso questa struttura si possono impostare le modalità con cui viene +effettuata la notifica; in 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. Inoltre il campo \var{sigev\_value} è il +puntatore ad una struttura \struct{sigval\_t} (definita in +\figref{fig:sig_sigval}) che permette di restituire al gestore del segnale un +valore numerico o un indirizzo,\footnote{per il suo uso si riveda la + trattazione fatta in \secref{sec:sig_real_time} a proposito dei segnali + real-time.} posto che questo sia installato nella forma estesa vista in +\secref{sec:sig_sigaction}. 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. 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 -\code{notification->sigev\_signo} viene inviato al processo che si era -registrato, e la coda diventa disponibile per una ulteriore registrazione. Si -tenga presente però che la presenza di un processo bloccato in una chiamata a -\func{mq\_receive} ha la precedenza sulla notifica; in tal caso infatti un -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}). +presente inoltre che alla chiusura del descrittore associato alla coda (e +quindi anche all'uscita del processo) ogni eventuale registrazione di notifica +presente viene cancellata. + +La notifica del segnale avviene all'arrivo di un messaggio in una coda vuota +(cioè solo se sulla coda non ci sono messaggi) e se non c'è nessun processo +bloccato in una chiamata a \func{mq\_receive}, in questo caso infatti il +processo bloccato ha la precedenza ed il messaggio gli viene immediatamente +inviato, mentre per il meccanismo di notifica tutto funziona come se la coda +fosse rimasta vuota. + +Quando un messaggio arriva su una coda vuota al processo che si era registrato +viene inviato il segnale specificato da \code{notification->sigev\_signo}, e +la coda diventa disponibile per una ulteriore registrazione. Questo comporta +che se si vuole mantenere il meccanismo di notifica occorre ripetere la +registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore +del segnale di notifica. A differenza della situazione simile che si aveva con +i segnali non affidabili,\footnote{l'argomento è stato affrontato in + \ref{sec:sig_semantics}.} questa caratteristica non configura una +race-condition perché l'invio di un segnale avviene solo se la coda è vuota; +pertanto se si vuole evitare di correre il rischio di perdere eventuali +ulteriori segnali inviati nel lasso di tempo che occorre per ripetere la +richiesta di notifica basta avere cura di eseguire questa operazione prima di +estrarre i messaggi presenti dalla coda. + +L'invio del segnale di notifica avvalora alcuni campi di informazione +restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in +\figref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al +valore del \acr{pid} del processo che ha emesso il segnale, \var{si\_uid} +all'userid effettivo, \var{si\_code} a \const{SI\_MESGQ}, e \var{si\_errno} a +0. Questo ci dice che, se si effettua la ricezione dei messaggi 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\footnote{di nuovo si faccia riferimento a quanto detto al + proposito in \secref{sec:sig_sigaction} e \secref{sec:sig_real_time}.} @@ -4281,6 +4301,15 @@ i semafori di SysV IPC, e che non vale comunque la pena di usare visto che i problemi sottolineati in \secref{sec:ipc_sysv_sem} rimangono, anche se mascherati. +In realtà a partire dal kernel 2.5.7 è stato introdotto un meccanismo di +sincronizzazione completamente nuovo, basato sui cosiddetti +\textit{futex}\footnote{la sigla sta per \textit{faxt user mode mutex}.}, con +il quale dovrebbe essere possibile implementare una versione nativa dei +semafori; esso è già stato usato con successo per reimplementare in maniera +più efficiente tutte le direttive di sincronizzazione previste per i thread +POSIX. L'interfaccia corrente è stata stabilizzata a partire dal kernel +2.5.40. + -- 2.30.2