From bd30f25c8d511de4ffa7227a93272a71499cebc8 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Mon, 5 Feb 2007 12:47:56 +0000 Subject: [PATCH] Posix Semaphores --- ipc.tex | 475 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 327 insertions(+), 148 deletions(-) diff --git a/ipc.tex b/ipc.tex index e18dbbc..b7ccdd8 100644 --- a/ipc.tex +++ b/ipc.tex @@ -749,9 +749,9 @@ entrambe le direzioni. Il prototipo della funzione \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EAFNOSUPPORT}] I socket locali non sono supportati. - \item[\errcode{EPROTONOSUPPORT}] Il protocollo specificato non è supportato. - \item[\errcode{EOPNOTSUPP}] Il protocollo specificato non supporta la + \item[\errcode{EAFNOSUPPORT}] i socket locali non sono supportati. + \item[\errcode{EPROTONOSUPPORT}] il protocollo specificato non è supportato. + \item[\errcode{EOPNOTSUPP}] il protocollo specificato non supporta la creazione di coppie di socket. \end{errlist} ed inoltre \errval{EMFILE}, \errval{EFAULT}. @@ -1101,15 +1101,15 @@ di messaggi esistente (o di crearne una se questa non esiste) \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] Il processo chiamante non ha i privilegi per accedere + \item[\errcode{EACCES}] il processo chiamante non ha i privilegi per accedere alla coda richiesta. - \item[\errcode{EEXIST}] Si è richiesta la creazione di una coda che già + \item[\errcode{EEXIST}] si è richiesta la creazione di una coda che già esiste, ma erano specificati sia \const{IPC\_CREAT} che \const{IPC\_EXCL}. - \item[\errcode{EIDRM}] La coda richiesta è marcata per essere cancellata. - \item[\errcode{ENOENT}] Si è cercato di ottenere l'identificatore di una coda + \item[\errcode{EIDRM}] la coda richiesta è marcata per essere cancellata. + \item[\errcode{ENOENT}] si è cercato di ottenere l'identificatore di una coda di messaggi specificando una chiave che non esiste e \const{IPC\_CREAT} non era specificato. - \item[\errcode{ENOSPC}] Si è cercato di creare una coda di messaggi quando è + \item[\errcode{ENOSPC}] si è cercato di creare una coda di messaggi quando è stato superato il limite massimo di code (\const{MSGMNI}). \end{errlist} ed inoltre \errval{ENOMEM}. @@ -1269,10 +1269,10 @@ prototipo \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma processo + \item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma processo chiamante non ha i privilegi di lettura sulla coda. - \item[\errcode{EIDRM}] La coda richiesta è stata cancellata. - \item[\errcode{EPERM}] Si è richiesto \const{IPC\_SET} o \const{IPC\_RMID} ma + \item[\errcode{EIDRM}] la coda richiesta è stata cancellata. + \item[\errcode{EPERM}] si è richiesto \const{IPC\_SET} o \const{IPC\_RMID} ma il processo non ha i privilegi, o si è richiesto di aumentare il valore di \var{msg\_qbytes} oltre il limite \const{MSGMNB} senza essere amministratore. @@ -1324,13 +1324,13 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] Non si hanno i privilegi di accesso sulla coda. - \item[\errcode{EIDRM}] La coda è stata cancellata. - \item[\errcode{EAGAIN}] Il messaggio non può essere inviato perché si è + \item[\errcode{EACCES}] non si hanno i privilegi di accesso sulla coda. + \item[\errcode{EIDRM}] la coda è stata cancellata. + \item[\errcode{EAGAIN}] il messaggio non può essere inviato perché si è superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti sulla coda, e si è richiesto \const{IPC\_NOWAIT} in \param{flag}. - \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale. - \item[\errcode{EINVAL}] Si è specificato un \param{msgid} invalido, o un + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. + \item[\errcode{EINVAL}] si è specificato un \param{msgid} invalido, o un valore non positivo per \param{mtype}, o un valore di \param{msgsz} maggiore di \const{MSGMAX}. \end{errlist} @@ -1432,13 +1432,13 @@ La funzione che viene utilizzata per estrarre un messaggio da una coda successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] Non si hanno i privilegi di accesso sulla coda. - \item[\errcode{EIDRM}] La coda è stata cancellata. - \item[\errcode{E2BIG}] Il testo del messaggio è più lungo di \param{msgsz} e + \item[\errcode{EACCES}] non si hanno i privilegi di accesso sulla coda. + \item[\errcode{EIDRM}] la coda è stata cancellata. + \item[\errcode{E2BIG}] il testo del messaggio è più lungo di \param{msgsz} e non si è specificato \const{MSG\_NOERROR} in \param{msgflg}. - \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale mentre + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale mentre era in attesa di ricevere un messaggio. - \item[\errcode{EINVAL}] Si è specificato un \param{msgid} invalido o un + \item[\errcode{EINVAL}] si è specificato un \param{msgid} invalido o un valore di \param{msgsz} negativo. \end{errlist} ed inoltre \errval{EFAULT}. @@ -1724,7 +1724,7 @@ pertanto una realizzazione di un oggetto di questo tipo demandata al kernel. La forma più semplice di semaforo è quella del \textsl{semaforo binario}, o \textit{mutex}, in cui un valore diverso da zero (normalmente 1) indica la libertà di accesso, e un valore nullo l'occupazione -della risorsa; in generale però si possono usare semafori con valori interi, +della risorsa. In generale però si possono usare semafori con valori interi, utilizzando il valore del contatore come indicatore del ``numero di risorse'' ancora disponibili. @@ -1745,15 +1745,15 @@ permette di creare o ottenere l'identificatore di un insieme di semafori \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1 in caso di errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{ENOSPC}] Si è cercato di creare una insieme di semafori + \item[\errcode{ENOSPC}] si è cercato di creare una insieme di semafori quando è stato superato o il limite per il numero totale di semafori (\const{SEMMNS}) o quello per il numero totale degli insiemi (\const{SEMMNI}) nel sistema. - \item[\errcode{EINVAL}] L'argomento \param{nsems} è minore di zero o + \item[\errcode{EINVAL}] l'argomento \param{nsems} è minore di zero o maggiore del limite sul numero di semafori per ciascun insieme (\const{SEMMSL}), o se l'insieme già esiste, maggiore del numero di semafori che contiene. - \item[\errcode{ENOMEM}] Il sistema non ha abbastanza memoria per poter + \item[\errcode{ENOMEM}] il sistema non ha abbastanza memoria per poter contenere le strutture per un nuovo insieme di semafori. \end{errlist} ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST}, @@ -1788,7 +1788,6 @@ del sistema. Come vedremo esistono delle modalit diventa necessario indicare esplicitamente che si vuole il ripristino del semaforo all'uscita del processo. - \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} @@ -1819,7 +1818,6 @@ quanto riguarda gli altri campi invece: effettuata, viene inizializzato a zero. \end{itemize*} - Ciascun semaforo dell'insieme è realizzato come una struttura di tipo \struct{sem} che ne contiene i dati essenziali, la sua definizione\footnote{si è riportata la definizione originaria del kernel 1.0, che contiene la prima @@ -1904,12 +1902,12 @@ loro inizializzazione) quattro. In caso di errore restituisce -1, ed \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] Il processo non ha i privilegi per eseguire + \item[\errcode{EACCES}] il processo non ha i privilegi per eseguire l'operazione richiesta. - \item[\errcode{EIDRM}] L'insieme di semafori è stato cancellato. - \item[\errcode{EPERM}] Si è richiesto \const{IPC\_SET} o \const{IPC\_RMID} + \item[\errcode{EIDRM}] l'insieme di semafori è stato cancellato. + \item[\errcode{EPERM}] si è richiesto \const{IPC\_SET} o \const{IPC\_RMID} ma il processo non ha privilegi sufficienti ad eseguire l'operazione. - \item[\errcode{ERANGE}] Si è richiesto \const{SETALL} \const{SETVAL} ma il + \item[\errcode{ERANGE}] si è richiesto \const{SETALL} \const{SETVAL} ma il valore a cui si vuole impostare il semaforo è minore di zero o maggiore di \const{SEMVMX}. \end{errlist} @@ -2042,18 +2040,18 @@ vengono effettuate con la funzione \funcd{semop}, il cui prototipo \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] Il processo non ha i privilegi per eseguire + \item[\errcode{EACCES}] il processo non ha i privilegi per eseguire l'operazione richiesta. - \item[\errcode{EIDRM}] L'insieme di semafori è stato cancellato. - \item[\errcode{ENOMEM}] Si è richiesto un \const{SEM\_UNDO} ma il sistema + \item[\errcode{EIDRM}] l'insieme di semafori è stato cancellato. + \item[\errcode{ENOMEM}] si è richiesto un \const{SEM\_UNDO} ma il sistema non ha le risorse per allocare la struttura di ripristino. - \item[\errcode{EAGAIN}] Un'operazione comporterebbe il blocco del processo, + \item[\errcode{EAGAIN}] un'operazione comporterebbe il blocco del processo, ma si è specificato \const{IPC\_NOWAIT} in \var{sem\_flg}. - \item[\errcode{EINTR}] La funzione, bloccata in attesa dell'esecuzione + \item[\errcode{EINTR}] la funzione, bloccata in attesa dell'esecuzione dell'operazione, viene interrotta da un segnale. - \item[\errcode{E2BIG}] L'argomento \param{nsops} è maggiore del numero + \item[\errcode{E2BIG}] l'argomento \param{nsops} è maggiore del numero massimo di operazioni \const{SEMOPM}. - \item[\errcode{ERANGE}] Per alcune operazioni il valore risultante del + \item[\errcode{ERANGE}] per alcune operazioni il valore risultante del semaforo viene a superare il limite massimo \const{SEMVMX}. \end{errlist} ed inoltre \errval{EFAULT} ed \errval{EINVAL}. @@ -2336,14 +2334,14 @@ ed il suo prototipo \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1 in caso di errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{ENOSPC}] Si è superato il limite (\const{SHMMNI}) sul numero + \item[\errcode{ENOSPC}] si è superato il limite (\const{SHMMNI}) sul numero di segmenti di memoria nel sistema, o cercato di allocare un segmento le cui dimensioni fanno superare il limite di sistema (\const{SHMALL}) per la memoria ad essi riservata. - \item[\errcode{EINVAL}] Si è richiesta una dimensione per un nuovo segmento + \item[\errcode{EINVAL}] si è richiesta una dimensione per un nuovo segmento maggiore di \const{SHMMAX} o minore di \const{SHMMIN}, o se il segmento già esiste \param{size} è maggiore delle sue dimensioni. - \item[\errcode{ENOMEM}] Il sistema non ha abbastanza memoria per poter + \item[\errcode{ENOMEM}] il sistema non ha abbastanza memoria per poter contenere le strutture per un nuovo segmento di memoria condivisa. \end{errlist} ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST}, @@ -2470,18 +2468,18 @@ un segmento di memoria condivisa \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma i permessi non + \item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma i permessi non consentono l'accesso in lettura al segmento. \item[\errcode{EINVAL}] O \param{shmid} non è un identificatore valido o \param{cmd} non è un comando valido. - \item[\errcode{EIDRM}] L'argomento \param{shmid} fa riferimento ad un + \item[\errcode{EIDRM}] l'argomento \param{shmid} fa riferimento ad un segmento che è stato cancellato. - \item[\errcode{EPERM}] Si è specificato un comando con \const{IPC\_SET} o + \item[\errcode{EPERM}] si è specificato un comando con \const{IPC\_SET} o \const{IPC\_RMID} senza i permessi necessari. - \item[\errcode{EOVERFLOW}] Si è tentato il comando \const{IPC\_STAT} ma il + \item[\errcode{EOVERFLOW}] si è tentato il comando \const{IPC\_STAT} ma il valore del group-ID o dell'user-ID è troppo grande per essere memorizzato nella struttura puntata da \param{buf}. - \item[\errcode{EFAULT}] L'indirizzo specificato con \param{buf} non è + \item[\errcode{EFAULT}] l'indirizzo specificato con \param{buf} non è valido. \end{errlist} } @@ -2542,9 +2540,9 @@ il suo prototipo successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{EACCES}] Il processo non ha i privilegi per accedere al + \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al segmento nella modalità richiesta. - \item[\errcode{EINVAL}] Si è specificato un identificatore invalido per + \item[\errcode{EINVAL}] si è specificato un identificatore invalido per \param{shmid}, o un indirizzo non allineato sul confine di una pagina per \param{shmaddr}. \end{errlist} @@ -3258,7 +3256,7 @@ le code di messaggi sono supportate a partire dal kernel 2.6.6. La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso degli identificatori e delle chiavi visti nel SysV IPC, per passare ai -\textit{POSIX IPC names}\itindex{POSIX~IPC~names}, che sono sostanzialmente +\itindex{POSIX~IPC~names} \textit{POSIX IPC names}, che sono sostanzialmente equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC POSIX prendono come primo argomento una stringa che indica uno di questi nomi; lo standard è molto generico riguardo l'implementazione, ed i nomi stessi @@ -3266,7 +3264,7 @@ possono avere o meno una corrispondenza sul filesystem; tutto quello che richiesto è che: \begin{itemize} \item i nomi devono essere conformi alle regole che caratterizzano i - \itindex{pathname}\textit{pathname}, in particolare non essere più lunghi di + \itindex{pathname} \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX} byte e terminati da un carattere nullo. \item se il nome inizia per una \texttt{/} chiamate differenti allo stesso nome fanno riferimento allo stesso oggetto, altrimenti l'interpretazione del @@ -3286,28 +3284,28 @@ directory (rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si faccia riferimento a sez.~\ref{sec:ipc_posix_shm}, sez.~\ref{sec:ipc_posix_sem} e sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni sono considerati come un -\itindsub{pathname}{assoluto}\textit{pathname} assoluto (comprendente +\itindsub{pathname}{assoluto} \textit{pathname} assoluto (comprendente eventuali sottodirectory) rispetto a queste radici. Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti nell'albero dei file, e possono essere maneggiati con le usuali funzioni e comandi di accesso ai file,\footnote{questo è vero nel caso di Linux, che usa una implementazione che lo consente, non è detto che altrettanto valga per - altri kernel; in particolare sia la memoria condivisa che per le code di - messaggi, come si può facilmente evincere con uno \cmd{strace}, le system - call utilizzate sono le stesse, in quanto detti oggetti sono realizzati con - dei file in speciali filesystem.} che funzionano come su dei file normali. + altri kernel; in particolare, come si può facilmente verificare con uno + \cmd{strace}, sia per la memoria condivisa che per le code di messaggi le + system call utilizzate da Linux sono le stesse di quelle dei file, essendo + detti oggetti realizzati come tali in appositi filesystem.} che funzionano +come su dei file normali. In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai -permessi dei file, e il controllo di accesso segue esattamente la stessa -semantica (quella illustrata in sez.~\ref{sec:file_access_control}), invece di +permessi dei file, ed il controllo di accesso segue esattamente la stessa +semantica (quella illustrata in sez.~\ref{sec:file_access_control}), e non quella particolare (si ricordi quanto visto in -sez.~\ref{sec:ipc_sysv_access_control}) usata per gli oggetti del SysV IPC. -Per quanto riguarda l'attribuzione dell'utente e del gruppo proprietari -dell'oggetto alla creazione di quest'ultimo essa viene effettuata secondo la -semantica SysV; essi corrispondono cioè a userid e groupid effettivi del -processo che esegue la creazione. - +sez.~\ref{sec:ipc_sysv_access_control}) che viene usata per gli oggetti del +SysV IPC. Per quanto riguarda l'attribuzione dell'utente e del gruppo +proprietari dell'oggetto alla creazione di quest'ultimo essa viene effettuata +secondo la semantica SysV: corrispondono cioè a user-ID e group-ID effettivi +del processo che esegue la creazione. \subsection{Code di messaggi} @@ -3324,17 +3322,16 @@ che in casi pi mutex (o semafori) e memoria condivisa con tutta la flessibilità che occorre. Per poter utilizzare le code di messaggi, oltre ad utilizzare un kernel -superiore al 2.6.6 (o precedente, purché cui siano stati opportunamente -applicati i relativi patch) occorre utilizzare la libreria -\file{libmqueue}\footnote{i programmi che usano le code di messaggi cioè - devono essere compilati aggiungendo l'opzione \code{-lmqueue} al comando - \cmd{gcc}, dato che le funzioni non fanno parte della libreria standard, in - corrispondenza all'inclusione del supporto nel kernel ufficiale, anche le - relative funzioni sono state inserite nelle \acr{glibc}, e presenti a - partire dalla versione 2.3.4 delle medesime.} che contiene le funzioni -dell'interfaccia POSIX.\footnote{in realtà l'implementazione è realizzata - tramite delle speciali chiamate ad \func{ioctl} sui file del filesystem - speciale su cui vengono mantenuti questi oggetti di IPC.} +superiore al 2.6.6 (o precedente, se sono stati opportunamente applicati i +relativi patch) occorre utilizzare la libreria \file{libmqueue}\footnote{i + programmi che usano le code di messaggi cioè devono essere compilati + aggiungendo l'opzione \code{-lmqueue} al comando \cmd{gcc}; in + corrispondenza all'inclusione del supporto nel kernel ufficiale anche + \file{libmqueue} è stata inserita nelle \acr{glibc}, a partire dalla + versione 2.3.4 delle medesime.} che contiene le funzioni dell'interfaccia +POSIX.\footnote{in realtà l'implementazione è realizzata tramite delle + opportune chiamate ad \func{ioctl} sui file del filesystem speciale su cui + vengono mantenuti questi oggetti di IPC.} La libreria inoltre richiede la presenza dell'apposito filesystem di tipo \texttt{mqueue} montato su \file{/dev/mqueue}; questo può essere fatto @@ -3365,15 +3362,15 @@ di messaggi POSIX di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{EACCES}] Il processo non ha i privilegi per accedere al + \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al alla memoria secondo quanto specificato da \param{oflag}. - \item[\errcode{EEXIST}] Si è specificato \const{O\_CREAT} e + \item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e \const{O\_EXCL} ma la coda già esiste. - \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale. - \item[\errcode{EINVAL}] Il file non supporta la funzione, o si è + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. + \item[\errcode{EINVAL}] il file non supporta la funzione, o si è specificato \const{O\_CREAT} con una valore non nullo di \param{attr} e valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}. - \item[\errcode{ENOENT}] Non si è specificato \const{O\_CREAT} ma la coda + \item[\errcode{ENOENT}] non si è specificato \const{O\_CREAT} ma la coda non esiste. \end{errlist} ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT}, @@ -3439,7 +3436,7 @@ fig.~\ref{fig:ipc_mq_attr}. \label{fig:ipc_mq_attr} \end{figure} -Per ls creazione della coda i campi della struttura che devono essere +Per la creazione della coda i campi della struttura che devono essere specificati sono \var{mq\_msgsize} e \var{mq\_maxmsg}, che indicano rispettivamente la dimensione massima di un messaggio ed il numero massimo di messaggi che essa può contenere. Il valore dovrà essere positivo e minore dei @@ -3556,16 +3553,16 @@ Per inserire messaggi su di una coda sono previste due funzioni, \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{EAGAIN}] Si è aperta la coda con \const{O\_NONBLOCK}, e la + \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la coda è piena. - \item[\errcode{EMSGSIZE}] La lunghezza del messaggio \param{msg\_len} + \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len} eccede il limite impostato per la coda. - \item[\errcode{ENOMEM}] Il kernel non ha memoria sufficiente. Questo + \item[\errcode{ENOMEM}] il kernel non ha memoria sufficiente. Questo errore può avvenire quando l'inserimento del messaggio - \item[\errcode{EINVAL}] Si è specificato un valore nullo per + \item[\errcode{EINVAL}] si è specificato un valore nullo per \param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o un valore non valido per \param{abs\_timeout}. - \item[\errcode{ETIMEDOUT}] L'inserimento del messaggio non è stato + \item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato effettuato entro il tempo stabilito. \end{errlist} ed inoltre \errval{EBADF} ed \errval{EINTR}.} @@ -3614,13 +3611,13 @@ prototipi sono: di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{EAGAIN}] Si è aperta la coda con \const{O\_NONBLOCK}, e la + \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la coda è vuota. - \item[\errcode{EMSGSIZE}] La lunghezza del messaggio sulla coda eccede il + \item[\errcode{EMSGSIZE}] la lunghezza del messaggio sulla coda eccede il valore \param{msg\_len} specificato per la ricezione. - \item[\errcode{EINVAL}] Si è specificato un valore nullo per + \item[\errcode{EINVAL}] si è specificato un valore nullo per \param{msg\_ptr}, o un valore non valido per \param{abs\_timeout}. - \item[\errcode{ETIMEDOUT}] La ricezione del messaggio non è stata + \item[\errcode{ETIMEDOUT}] la ricezione del messaggio non è stata effettuata entro il tempo stabilito. \end{errlist} ed inoltre \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o @@ -3630,7 +3627,7 @@ prototipi sono: 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 viene tolto dalla coda e la sua dimensione viene restituita come valore di -ritorno.\footnote{si tenga presente che 0 è una dimensione valida la +ritorno.\footnote{si tenga presente che 0 è una dimensione valida e che la condizione di errore è restituita dal valore -1; Stevens in \cite{UNP2} fa notare che questo è uno dei casi in cui vale ciò che lo standard \textsl{non} dice, una dimensione nulla infatti, pur non essendo citata, non @@ -3684,8 +3681,8 @@ Attiva il meccanismo di notifica per la coda \param{mqdes}. \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{EBUSY}] C'è già un processo registrato per la notifica. - \item[\errcode{EBADF}] Il descrittore non fa riferimento ad una coda di + \item[\errcode{EBUSY}] c'è già un processo registrato per la notifica. + \item[\errcode{EBADF}] il descrittore non fa riferimento ad una coda di messaggi. \end{errlist}} \end{prototype} @@ -3759,61 +3756,6 @@ forma estesa.\footnote{di nuovo si faccia riferimento a quanto detto al -\subsection{Semafori} -\label{sec:ipc_posix_sem} - -Fino alla serie 2.4.x del kernel esistevano due implementazioni dei semafori -POSIX; una parziale che li realizzava solo a livello di thread e non di -processi,\footnote{questo significava che i semafori erano visibili solo - all'interno dei thread creati da un singolo processo, e non potevano essere - usati come meccanismo di sincronizzazione fra processi diversi.} presente -nella sezione delle estensioni \textit{real-time} delle -\acr{glibc},\footnote{quelle che si accedono collegandosi alla libreria - \texttt{librt}.} ed una che realizzava l'interfaccia POSIX usando le -funzioni dei semafori di SysV IPC (mantenendo così tutti i problemi -sottolineati in sez.~\ref{sec:ipc_sysv_sem}). - -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{fast user mode mutex}.} con -il quale è stato possibile implementare una versione nativa dei semafori -POSIX. Grazie a questo con i kernel della serie 2.6 e le nuove versioni delle -\acr{glibc} che usano questa nuova infrastruttura per quella che viene quella -che viene chiamata \textit{New Posix Thread Library}, sono state implementate -anche tutte le funzioni dell'interfaccia dei semafori POSIX. - -Anche in questo caso è necessario appoggiarsi alla libreria per le estensioni -\textit{real-time} \texttt{librt}, questo significa che se si vuole utilizzare -questa interfaccia, oltre ad utilizzare gli opportuni file di definizione, -occorrerà compilare i programmi con l'opzione \texttt{-lrt}. - -% TODO trattare l'argomento a partire da man sem_overview. - - - - -\begin{functions} - \headdecl{semaphore.h} - - \funcdecl{sem\_t *sem_open(const char *name, int oflag)} - - \funcdecl{sem\_t *sem_open(const char *name, int oflag,, mode_t mode, - unsigned int value)} - - Crea un semaforo o ne apre uno esistente. - - \bodydesc{Le funzioni restituiscono il numero di byte del messaggio in caso - di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i - valori: - \begin{errlist} - \item[\errcode{EAGAIN}] Si è aperta la coda con \const{O\_NONBLOCK}, e la - coda è vuota. - \end{errlist} - ed inoltre \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o - \errval{EINVAL}.} -\end{functions} - - \subsection{Memoria condivisa} \label{sec:ipc_posix_shm} @@ -3991,6 +3933,241 @@ fare (\texttt{\small 44}) in questo caso restituendo al chiamante il valore di ritorno. + + +\subsection{Semafori} +\label{sec:ipc_posix_sem} + +Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale +dei semafori POSIX che li realizzava solo a livello di thread e non di +processi,\footnote{questo significava che i semafori erano visibili solo + all'interno dei thread creati da un singolo processo, e non potevano essere + usati come meccanismo di sincronizzazione fra processi diversi.} fornita +attraverso la sezione delle estensioni \textit{real-time} delle +\acr{glibc}.\footnote{quelle che si accedono collegandosi alla libreria + \texttt{librt}.} Esisteva inoltre una libreria che realizzava (parzialmente) +l'interfaccia POSIX usando le funzioni dei semafori di SysV IPC (mantenendo +così tutti i problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem}). + +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{fast user mode mutex}.} con +il quale è stato possibile implementare una versione nativa dei semafori +POSIX. Grazie a questo con i kernel della serie 2.6 e le nuove versioni delle +\acr{glibc} che usano questa nuova infrastruttura per quella che viene quella +che viene chiamata \textit{New Posix Thread Library}, sono state implementate +anche tutte le funzioni dell'interfaccia dei semafori POSIX. + +Anche in questo caso è necessario appoggiarsi alla libreria per le estensioni +\textit{real-time} \texttt{librt}, questo significa che se si vuole utilizzare +questa interfaccia, oltre ad utilizzare gli opportuni file di definizione, +occorrerà compilare i programmi con l'opzione \texttt{-lrt}. + +% TODO trattare l'argomento a partire da man sem_overview. + +La funzione che permette di creare un nuovo semaforo POSIX, creando il +relativo file, o di accedere ad uno esistente, è \funcd{sem\_open}, questa +prevede due forme diverse a seconda che sia utilizzata per aprire un semaforo +esistente o per crearne uno nuovi, i relativi prototipi sono: +\begin{functions} + \headdecl{semaphore.h} + + \funcdecl{sem\_t *sem\_open(const char *name, int oflag)} + + \funcdecl{sem\_t *sem\_open(const char *name, int oflag, mode\_t mode, + unsigned int value)} + + Crea un semaforo o ne apre uno esistente. + + \bodydesc{La funzione restituisce l'indirizzo del semaforo in caso di + successo e \const{SEM\_FAILED} in caso di errore; nel quel caso + \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EACCESS}] il semaforo esiste ma non si hanno permessi + sufficienti per accedervi. + \item[\errcode{EEXIST}] si sono specificati \const{O\_CREAT} e + \const{O\_EXCL} ma il semaforo esiste. + \item[\errcode{EINVAL}] il valore di \param{value} eccede + \const{SEM\_VALUE\_MAX}. + \item[\errcode{ENAMETOOLONG}] si è utilizzato un nome troppo lungo. + \item[\errcode{ENOENT}] non si è usato \const{O\_CREAT} ed il nome + specificato non esiste. + \end{errlist} + ed inoltre \errval{ENFILE} ed \errval{ENOMEM}.} +\end{functions} + +L'argomento \param{name} definisce il nome del semaforo che si vuole +utilizzare, ed è quello che permette a processi diversi di accedere allo +stesso semaforo. Questo deve essere specificato con un pathname nella forma +\texttt{/qualchenome}, che non ha una corrispondenza diretta con un pathname +reale; con Linux infatti i file associati ai semafori sono mantenuti nel +filesystem virtuale \texttt{/dev/shm}, e gli viene assegnato automaticamente +un nome nella forma \texttt{sem.qualchenome}.\footnote{si ha cioè una + corrispondenza per cui \texttt{/qualchenome} viene rimappato, nella + creazione tramite \func{sem\_open}, su \texttt{/dev/shm/sem.qualchenome}.} + +L'argomento \param{oflag} è quello che controlla le modalità con cui opera la +funzione, ed è passato come maschera binaria; i bit corrispondono a quelli +utilizzati per l'analogo argomento di \func{open}, anche se dei possibili +valori visti in sez.~\ref{sec:file_open} sono utilizzati soltanto +\const{O\_CREAT} e \const{O\_EXCL}. + +Se si usa \const{O\_CREAT} si richiede la creazione del semaforo qualora +questo non esista, ed in tal caso occorre utilizzare la seconda forma della +funzione, in cui si devono specificare sia un valore iniziale con l'argomento +\param{value},\footnote{e si noti come così diventa possibile, differenza di + quanto avviene per i semafori del \textit{SysV IPC}, effettuare in maniera + atomica creazione ed inizializzazione di un semaforo usando una unica + funzione.} che una maschera dei permessi con l'argomento +\param{mode};\footnote{anche questo argomento prende gli stessi valori + utilizzati per l'analogo di \func{open}, che si sono illustrati in dettaglio + sez.~\ref{sec:file_perm_overview}.} questi verranno assegnati al semaforo +appena creato. Se il semaforo esiste già i suddetti valori saranno invece +ignorati. Usando il flag \const{O\_EXCL} si richiede invece la verifica che il +semaforo non esiste, usandolo insieme ad \const{O\_CREAT} la funzione fallisce +qualora un semaforo con lo stesso nome sia già presente. + +La funzione restituisce in caso di successo un puntatore all'indirizzo del +semaforo con un valore di tipo \ctyp{sem\_t *}, è questo valore che dovrà +essere passato alle altre funzioni per operare sul semaforo stesso. Si tenga +presente che, come accennato in sez.~\ref{sec:ipc_posix_generic}, i semafori +usano la semantica standard dei file per quanto riguarda i controlli di +accesso. + +Questo significa che un nuovo semaforo viene sempre creato con l'user-ID ed il +group-ID effettivo del processo chiamante, e che i permessi indicati con +\param{mode} vengono filtrati dal valore della \textit{umask} del processo. +Inoltre per poter aprire un semaforo è necessario avere su di esso sia il +permesso di lettura che quello di scrittura. + +Una volta che si sia ottenuto l'indirizzo di un semaforo, sarà possibile +utilizzarlo; se si ricorda quanto detto all'inizio di +sez.~\ref{sec:ipc_sysv_sem}, dove si sono introdotti i concetti generali +relativi ai semafori, le operazioni principali sono due, quella che richiede +l'uso di una risorsa bloccando il semaforo e quella che rilascia la risorsa +liberando il semaforo. La prima operazione è effettuata dalla funzione +\funcd{sem\_wait}, il cui prototipo è: +\begin{functions} + \headdecl{semaphore.h} + + \funcdecl{int sem\_wait(sem\_t *sem)} + + Blocca il semaforo \param{sem}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore; nel quel caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. + \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste. + \end{errlist} +} +\end{functions} + +La funzione cerca di decrementare il valore del semaforo indicato dal +puntatore \param{sem}, se questo ha un valore positivo, cosa che significa che +la risorsa è disponibile, la funzione ha successo, il valore del semaforo +viene diminuito di 1 ed essa ritorna immediatamente; se il valore è nullo la +funzione si blocca fintanto che il valore del semaforo non torni +positivo\footnote{ovviamente per opera di altro processo che lo rilascia + chiamando \func{sem\_post}.} così che poi essa possa decrementarlo con +successo e proseguire. + +Si tenga presente che la funzione può sempre essere interrotta da un segnale +(nel qual caso si avrà un errore di \const{EINTR}) e che questo avverrà +comunque, anche se si è installato il relativo gestore con \const{SA\_RESTART} +(vedi sez.~\ref{sec:sig_sigaction}) per riavviare le system call interrotte. + +Della funzione \func{sem\_wait} esistono due varianti che consentono di +gestire diversamente le modalità di attesa in caso di risorsa occupata, la +prima di queste è \funcd{sem\_trywait} che serve ad effettuare un tentativo di +acquisizione senza bloccarsi; il suo prototipo è: +\begin{functions} + \headdecl{semaphore.h} + + \funcdecl{int sem\_trywait(sem\_t *sem)} + + Tenta di bloccare il semaforo \param{sem}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore; nel quel caso \var{errno} assumerà gli stessi valori: + \begin{errlist} + \item[\errcode{EAGAIN}] il semaforo non può essere acquisito senza + bloccarsi. + \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste. + \end{errlist} +} +\end{functions} + +La funzione è identica a \func{sem\_wait} ed ha lo stesso effetto (vale a dire +che in caso di risorsa disponibile questa viene immediatamente acquisita), la +differenza è che nel caso in cui il semaforo è occupato essa non si blocca e +ritorna invece immediatamente, con un errore di \errval{EAGAIN}. + +La seconda variante è una estensione che può essere utilizzata soltanto se si +definisce la macro \macro{\_XOPEN\_SOURCE} ad un valore di 600 prima di +includere \texttt{semaphore.h}, è \func{sem\_timedwait}, il cui prototipo è: +\begin{functions} + \headdecl{semaphore.h} + + \funcdecl{int sem\_timedwait(sem\_t *sem, const struct timespec + *abs\_timeout)} + + Blocca il semaforo \param{sem}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore; nel quel caso \var{errno} assumerà gli stessi valori: + \begin{errlist} + \item[\errcode{ETIMEDOUT}] è scaduto il tempo massimo di attesa. + \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste. + \end{errlist} +} +\end{functions} + +Anche in questo caso il comportamento della funzione è identico a quello di +\func{sem\_wait}, solo che in questo caso è possibile impostare, con +l'argomento \param{abs\_timeout}, un tempo limite scaduto il quale la funzione +ritorna comunque anche se non è possibile acquisire il semaforo, riportando un +errore di \errval{ETIMEDOUT}. + +La seconda funzione di gestione dei semafori è \funcd{sem\_post}, che viene +utilizzata per rilasciare un semaforo occupato; il suo prototipo è: +\begin{functions} + \headdecl{semaphore.h} + + \funcdecl{int sem\_post(sem\_t *sem)} + + Rilascia il semaforo \param{sem}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore; nel quel caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste. + \end{errlist} +} +\end{functions} + +La funzione incrementa il valore del semaforo puntato dall'argomento +\param{sem}, se questo era nullo la relativa risorsa risulterà sbloccata, +cosicché un altro processo (o thread) bloccato in una \func{sem\_wait} sul +suddetto semaforo potrà essere svegliato e rimesso in esecuzione. Si tenga +presente che la funzione è è sicura per l'uso all'interno di un gestore di +segnali. + + + + +Una delle caratteristiche peculiari dei semafori POSIX è che questi possono +anche essere utilizzati in forma anonima. In questo caso si dovrà porre la +variabile che contiene l'indirizzo del semaforo in un tratto di memoria che +sia accessibile a tutti i processi in gioco. Questo può essere una variabile +globale nel caso si usino i thread (nel qual caso si parla di +\textit{thread-shared semaphore}), o un tratto di memoria condivisa nel caso +si usino o processo (nel qual caso si parla di \textit{process-shared + semaphore}). + + + + % LocalWords: like fifo System POSIX RPC Calls Common Object Request Brocker % LocalWords: Architecture descriptor kernel unistd int filedes errno EMFILE % LocalWords: ENFILE EFAULT BUF sez fig fork Stevens siblings EOF read SIGPIPE @@ -4039,7 +4216,9 @@ restituendo al chiamante il valore di ritorno. % LocalWords: EBUSY sigev SIGNAL signo value sigval siginfo all'userid MESGQ % LocalWords: Konstantin Knizhnik futex tmpfs ramfs cache shared swap CONFIG % LocalWords: lrt blocks PAGECACHE TRUNC CLOEXEC mmap ftruncate munmap FindShm -% LocalWords: CreateShm RemoveShm LIBRARY Library +% LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS +% LocalWords: ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait +% LocalWords: process %%% Local Variables: -- 2.30.2