quest'ultimo possa essere visualizzato correttamente da un browser.
Una volta create le \textit{pipe}, il programma può creare (\texttt{\small
- 13-17}) il primo processo figlio, che si incaricherà (\texttt{\small
+ 13--17}) il primo processo figlio, che si incaricherà (\texttt{\small
19--25}) di eseguire \cmd{barcode}. Quest'ultimo legge dallo standard input
una stringa di caratteri, la converte nell'immagine PostScript del codice a
barre ad essa corrispondente, e poi scrive il risultato direttamente sullo
esistenza della \textit{fifo}).
Una volta che si è certi che la \textit{fifo} di ascolto esiste la procedura
-di inizializzazione è completata. A questo punto si può chiamare
-(\texttt{\small 23}) la funzione \func{daemon} per far proseguire l'esecuzione
-del programma in background come demone. Si può quindi procedere
-(\texttt{\small 24--33}) alla apertura della \textit{fifo}: si noti che questo
-viene fatto due volte, prima in lettura e poi in scrittura, per evitare di
-dover gestire all'interno del ciclo principale il caso in cui il server è in
-ascolto ma non ci sono client che effettuano richieste. Si ricordi infatti
-che quando una \textit{fifo} è aperta solo dal capo in lettura, l'esecuzione di
-\func{read} ritorna con zero byte (si ha cioè una condizione di end-of-file).
+di inizializzazione è completata. A questo punto (\texttt{\small 23}) si può
+chiamare la funzione \func{daemon} per far proseguire l'esecuzione del
+programma in background come demone. Si può quindi procedere (\texttt{\small
+ 24--33}) alla apertura della \textit{fifo}: si noti che questo viene fatto
+due volte, prima in lettura e poi in scrittura, per evitare di dover gestire
+all'interno del ciclo principale il caso in cui il server è in ascolto ma non
+ci sono client che effettuano richieste. Si ricordi infatti che quando una
+\textit{fifo} è aperta solo dal capo in lettura, l'esecuzione di \func{read}
+ritorna con zero byte (si ha cioè una condizione di end-of-file).
Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque
-client non apre a sua volta la \textit{fifo} nota in scrittura per effettuare la sua
-richiesta. Pertanto all'inizio non ci sono problemi, il client però, una volta
-ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la
-\textit{fifo}. A questo punto il server resta (se non ci sono altri client
-che stanno effettuando richieste) con la \textit{fifo} chiusa sul lato in
-lettura, ed in questo stato la funzione \func{read} non si bloccherà in attesa
-di dati in ingresso, ma ritornerà in continuazione, restituendo una condizione
-di \textit{end-of-file}.
+client non apre a sua volta la \textit{fifo} nota in scrittura per effettuare
+la sua richiesta. Pertanto all'inizio non ci sono problemi, il client però,
+una volta ricevuta la risposta, uscirà, chiudendo tutti i file aperti,
+compresa la \textit{fifo}. A questo punto il server resta (se non ci sono
+altri client che stanno effettuando richieste) con la \textit{fifo} chiusa sul
+lato in lettura, ed in questo stato la funzione \func{read} non si bloccherà
+in attesa di dati in ingresso, ma ritornerà in continuazione, restituendo una
+condizione di \textit{end-of-file}.
Si è usata questa tecnica per compatibilità, Linux infatti supporta l'apertura
delle \textit{fifo} in lettura/scrittura, per cui si sarebbe potuto effettuare
La prima istruzione (\texttt{\small 12}) compone il nome della \textit{fifo}
che dovrà essere utilizzata per ricevere la risposta dal server. Si usa il
\ids{PID} del processo per essere sicuri di avere un nome univoco; dopo di che
-(\texttt{\small 13-18}) si procede alla creazione del relativo file, uscendo
+(\texttt{\small 13--18}) si procede alla creazione del relativo file, uscendo
in caso di errore (a meno che il file non sia già presente sul filesystem).
A questo punto il client può effettuare l'interrogazione del server, per
si scrive (\texttt{\small 24}) la stringa composta in precedenza, che contiene
il nome della \textit{fifo} da utilizzare per la risposta. Infine si richiude
la \textit{fifo} del server che a questo punto non serve più (\texttt{\small
- 25}).
+ 25}).
Inoltrata la richiesta si può passare alla lettura della risposta; anzitutto
si apre (\texttt{\small 26--30}) la \textit{fifo} appena creata, da cui si
I valori di default sono per l'uso delle code di messaggi e per 5 ripetizioni
del ciclo. Per questo motivo se non si utilizzano opzioni verrà eseguito per
-cinque volte il ciclo (\texttt{\small 7-11}), in cui si crea una coda di
+cinque volte il ciclo (\texttt{\small 7--11}), in cui si crea una coda di
messaggi (\texttt{\small 8}), se ne stampa l'identificativo (\texttt{\small
9}) e la si rimuove (\texttt{\small 10}). Non stiamo ad approfondire adesso
il significato delle funzioni utilizzate, che verranno esaminate nelle
-prossime sezioni.
+prossime sezioni.
Quello che ci interessa infatti è verificare l'allocazione degli
identificativi associati agli oggetti; lanciando il comando si otterrà
puntatori), è invece relativamente lenta nell'accesso casuale e nella
ricerca.} I nuovi messaggi vengono inseriti in coda alla lista e vengono
letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si è riportato uno schema
-semplificato con cui queste strutture vengono mantenute dal
-kernel.\footnote{lo schema illustrato è in realtà una semplificazione di
- quello usato fino ai kernel della serie 2.2, a partire della serie 2.4 la
- gestione delle code di messaggi è effettuata in maniera diversa, ma abbiamo
- mantenuto lo schema precedente dato che illustra in maniera più che adeguata
- i principi di funzionamento delle code di messaggi.}
+semplificato con cui queste strutture vengono mantenute dal kernel. Lo schema
+illustrato in realta è una semplificazione di quello usato fino ai kernel
+della serie 2.2. A partire della serie 2.4 la gestione delle code di messaggi
+è effettuata in maniera diversa (e non esiste una struttura \struct{msqid\_ds}
+nel kernel), ma abbiamo mantenuto lo schema precedente dato che illustra in
+maniera più che adeguata i principi di funzionamento delle code di messaggi.
\begin{figure}[!htb]
\centering \includegraphics[width=13cm]{img/mqstruct}
A ciascuna coda è associata una struttura \struct{msqid\_ds} la cui
-definizione è riportata in fig.~\ref{fig:ipc_msqid_ds}. In questa struttura il
-kernel mantiene le principali informazioni riguardo lo stato corrente della
-coda.\footnote{come accennato questo vale fino ai kernel della serie 2.2, essa
- viene usata nei kernel della serie 2.4 solo per compatibilità in quanto è
- quella restituita dalle funzioni dell'interfaccia; si noti come ci sia una
- differenza con i campi mostrati nello schema di fig.~\ref{fig:ipc_mq_schema}
- che sono presi dalla definizione di \file{include/linux/msg.h}, e fanno
- riferimento alla definizione della omonima struttura usata nel kernel.} In
-fig.~\ref{fig:ipc_msqid_ds} sono elencati i campi significativi definiti in
-\headfile{sys/msg.h}, a cui si sono aggiunti gli ultimi tre campi che sono
-previsti dalla implementazione originale di System V, ma non dallo standard
-Unix98.
+definizione è riportata in fig.~\ref{fig:ipc_msqid_ds} ed a cui si accede
+includendo \headfile{sys/msg.h};
+%
+% INFO: sotto materiale obsoleto e non interessante
+% In questa struttura il
+% kernel mantiene le principali informazioni riguardo lo stato corrente della
+% coda. Come accennato questo vale fino ai kernel della serie 2.2, essa viene
+% usata nei kernel della serie 2.4 solo per compatibilità in quanto è quella
+% restituita dalle funzioni dell'interfaccia; si noti come ci sia una differenza
+% con i campi mostrati nello schema di fig.~\ref{fig:ipc_mq_schema} che sono
+% presi dalla definizione di \file{include/linux/msg.h}, e fanno riferimento
+% alla definizione della omonima struttura usata nel kernel.
+%In fig.~\ref{fig:ipc_msqid_ds} sono elencati i campi definiti in
+%\headfile{sys/msg.h};
+si tenga presente che il campo \var{\_\_msg\_cbytes} non è previsto dallo
+standard POSIX.1-2001 e che alcuni campi fino al kernel 2.2 erano definiti
+come \ctyp{short}.
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{.90\textwidth}
\includestruct{listati/msqid_ds.h}
\end{minipage}
\normalsize
\end{figure}
Quando si crea una nuova coda con \func{msgget} questa struttura viene
-inizializzata, in particolare il campo \var{msg\_perm} viene inizializzato
-come illustrato in sez.~\ref{sec:ipc_sysv_access_control}, per quanto riguarda
-gli altri campi invece:
+inizializzata,\footnote{in realtà viene inizializzata una struttura interna al
+ kernel, ma i dati citati sono gli stessi.} in particolare il campo
+\var{msg\_perm} che esprime i permessi di accesso viene inizializzato nella
+modalità illustrata in sez.~\ref{sec:ipc_sysv_access_control}. Per quanto
+riguarda gli altri campi invece:
\begin{itemize*}
\item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
sulla coda, viene inizializzato a 0.
\item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
messaggio sulla coda, sono inizializzati a 0.
-\item il campo \var{msg\_ctime}, che esprime il tempo di creazione della coda,
- viene inizializzato al tempo corrente.
-\item il campo \var{msg\_qbytes} che esprime la dimensione massima del
+\item il campo \var{msg\_ctime}, che esprime il tempo di ultima modifica della
+ coda, viene inizializzato al tempo corrente.
+\item il campo \var{msg\_qbytes}, che esprime la dimensione massima del
contenuto della coda (in byte) viene inizializzato al valore preimpostato
del sistema (\const{MSGMNB}).
-\item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
- primo e ultimo messaggio sono inizializzati a \val{NULL} e
- \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
- inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
- e non devono essere utilizzati da programmi in user space).
+\item il campo \var{\_\_msg\_cbytes}, che esprime la dimensione in byte dei
+ messaggi presenti sulla coda, viene inizializzato a zero.
+% i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
+% primo e ultimo messaggio sono inizializzati a \val{NULL} e
+% \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
+% inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
+% e non devono essere utilizzati da programmi in user space).
\end{itemize*}
Una volta creata una coda di messaggi le operazioni di controllo vengono
generico.}
\end{funcproto}
-
-La funzione permette di accedere ai valori della struttura \struct{msqid\_ds},
-mantenuta all'indirizzo \param{buf}, per la coda specificata
-dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
-valore dell'argomento \param{cmd}, che specifica il tipo di azione da
-eseguire; i valori possibili sono:
-\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+La funzione permette di eseguire una operazione di controllo per la coda
+specificata dall'identificatore \param{msqid}, utilizzando i valori della
+struttura \struct{msqid\_ds}, mantenuta all'indirizzo \param{buf}. Il
+comportamento della funzione dipende dal valore dell'argomento \param{cmd},
+che specifica il tipo di azione da eseguire. I valori possibili
+per \param{cmd} sono:
+\begin{basedescript}{\desclabelwidth{1.6cm}\desclabelstyle{\nextlinelabel}}
\item[\const{IPC\_STAT}] Legge le informazioni riguardo la coda nella
- struttura indicata da \param{buf}. Occorre avere il permesso di lettura
- sulla coda.
+ struttura \struct{msqid\_ds} indicata da \param{buf}. Occorre avere il
+ permesso di lettura sulla coda.
\item[\const{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
effetto immediato. Tutti i processi che cercheranno di accedere alla coda
riceveranno un errore di \errcode{EIDRM}, e tutti processi in attesa su
\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in
essa contenuti (\var{msg\_qbytes}). I valori devono essere passati in una
- struttura \struct{msqid\_ds} puntata da \param{buf}. Per modificare i valori
- di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
- essere il proprietario o il creatore della coda, oppure l'amministratore; lo
- stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di
- incrementarne il valore a limiti superiori a \const{MSGMNB}.
+ struttura \struct{msqid\_ds} puntata da \param{buf}. Per modificare i
+ valori di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid}
+ occorre essere il proprietario o il creatore della coda, oppure
+ l'amministratore e lo stesso vale per \var{msg\_qbytes}. Infine solo
+ l'amministratore (più precisamente un processo con la capacità
+ \itindex{capability} \const{CAP\_IPC\_RESOURCE}) ha la facoltà di
+ incrementarne il valore a limiti superiori a \const{MSGMNB}. Se eseguita con
+ successo la funzione aggiorna anche il campo \var{msg\_ctime}.
\end{basedescript}
+A questi tre valori, che sono quelli previsti dallo standard, su Linux se ne
+affiancano altri tre (\const{IPC\_INFO}, \const{MSG\_STAT} e
+\const{MSG\_INFO}) introdotti ad uso del programma \cmd{icps} per ottenere le
+informazioni generali relative alle risorse usate dalle code di
+messaggi. Questi potranno essere modificati o rimossi in favore dell'uso di
+\texttt{/proc}, per cui non devono essere usati e non li tratteremo.
Una volta che si abbia a disposizione l'identificatore, per inviare un
-messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo
-è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/ipc.h}
- \headdecl{sys/msg.h}
-
- \funcdecl{int msgsnd(int msqid, struct msgbuf *msgp, size\_t msgsz, int
- msgflg)}
+messaggio su una coda si utilizza la funzione di sistema \funcd{msgsnd}, il
+cui prototipo è:
- Invia un messaggio sulla coda \param{msqid}.
-
- \bodydesc{La funzione restituisce 0, e $-1$ in caso di errore, nel qual caso
- \var{errno} assumerà uno dei valori:
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/msg.h}
+\fdecl{int msgsnd(int msqid, struct msgbuf *msgp, size\_t msgsz, int msgflg)}
+\fdesc{Invia un messaggio su una coda.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un 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 è
- superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti
- sulla coda, e si è richiesto \const{IPC\_NOWAIT} in \param{flag}.
+ 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{EIDRM}] la coda è stata cancellata.
\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}
- ed inoltre \errval{EFAULT}, \errval{EINTR} ed \errval{ENOMEM}. }
-\end{functions}
+ ed inoltre \errval{EFAULT}, \errval{EINTR} e \errval{ENOMEM} nel loro
+ significato generico.}
+\end{funcproto}
La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso il
messaggio. La dimensione massima per il testo di un messaggio non può
comunque superare il limite \const{MSGMAX}.
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.8\textwidth}
+ \includestruct{listati/msgbuf.h}
+ \end{minipage}
+ \normalsize
+ \caption{Schema della struttura \structd{msgbuf}, da utilizzare come
+ argomento per inviare/ricevere messaggi.}
+ \label{fig:ipc_msbuf}
+\end{figure}
+
La struttura di fig.~\ref{fig:ipc_msbuf} è comunque solo un modello, tanto che
la definizione contenuta in \headfile{sys/msg.h} usa esplicitamente per il
secondo campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini
consideriamo il caso dell'esempio in fig.~\ref{fig:ipc_msbuf}, \param{msgsz}
dovrà essere pari a \const{LENGTH}).
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{\textwidth}
- \includestruct{listati/msgbuf.h}
- \end{minipage}
- \normalsize
- \caption{Schema della struttura \structd{msgbuf}, da utilizzare come
- argomento per inviare/ricevere messaggi.}
- \label{fig:ipc_msbuf}
-\end{figure}
-
Per capire meglio il funzionamento della funzione riprendiamo in
considerazione la struttura della coda illustrata in
fig.~\ref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
della funzione. Di norma, quando si specifica un valore nullo, la funzione
ritorna immediatamente a meno che si sia ecceduto il valore di
\var{msg\_qbytes}, o il limite di sistema sul numero di messaggi, nel qual
-caso si blocca mandando il processo in stato di \textit{sleep}. Se si
-specifica per \param{flag} il valore \const{IPC\_NOWAIT} la funzione opera in
-modalità non bloccante, ed in questi casi ritorna immediatamente con un errore
-di \errcode{EAGAIN}.
+caso si blocca. Se si specifica per \param{flag} il valore
+\const{IPC\_NOWAIT} la funzione opera in modalità non-bloccante, ed in questi
+casi ritorna immediatamente con un errore di \errcode{EAGAIN}.
Se non si specifica \const{IPC\_NOWAIT} la funzione resterà bloccata fintanto
che non si liberano risorse sufficienti per poter inserire nella coda il
-messaggio, nel qual caso ritornerà normalmente. La funzione può ritornare, con
+messaggio, nel qual caso ritornerà normalmente. La funzione può ritornare con
una condizione di errore anche in due altri casi: quando la coda viene rimossa
(nel qual caso si ha un errore di \errcode{EIDRM}) o quando la funzione viene
interrotta da un segnale (nel qual caso si ha un errore di \errcode{EINTR}).
\item Il valore \var{msg\_stime}, che viene impostato al tempo corrente.
\end{itemize*}
-La funzione che viene utilizzata per estrarre un messaggio da una coda è
-\funcd{msgrcv}; il suo prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/ipc.h}
- \headdecl{sys/msg.h}
+La funzione di sistema che viene utilizzata per estrarre un messaggio da una
+coda è \funcd{msgrcv}, ed il suo prototipo è:
- \funcdecl{ssize\_t msgrcv(int msqid, struct msgbuf *msgp, size\_t msgsz,
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/msg.h}
+\fdecl{ssize\_t msgrcv(int msqid, struct msgbuf *msgp, size\_t msgsz,
long msgtyp, int msgflg)}
-
- Legge un messaggio dalla coda \param{msqid}.
-
- \bodydesc{La funzione restituisce il numero di byte letti in caso di
- successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno
- dei valori:
+\fdesc{Legge un messaggio da una coda.}
+}
+
+{La funzione ritorna il numero di byte letti in caso di successo e $-1$ per un
+ 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
non si è specificato \const{MSG\_NOERROR} in \param{msgflg}.
+ \item[\errcode{EACCES}] non si hanno i privilegi di accesso sulla coda.
+ \item[\errcode{EIDRM}] la coda è stata cancellata.
\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
valore di \param{msgsz} negativo.
\end{errlist}
- ed inoltre \errval{EFAULT}.
-}
-\end{functions}
+ ed inoltre \errval{EFAULT} nel suo significato generico.}
+\end{funcproto}
-La funzione legge un messaggio dalla coda specificata, scrivendolo sulla
-struttura puntata da \param{msgp}, che dovrà avere un formato analogo a quello
-di fig.~\ref{fig:ipc_msbuf}. Una volta estratto, il messaggio sarà rimosso
-dalla coda. L'argomento \param{msgsz} indica la lunghezza massima del testo
-del messaggio (equivalente al valore del parametro \const{LENGTH} nell'esempio
-di fig.~\ref{fig:ipc_msbuf}).
+La funzione legge un messaggio dalla coda specificata da \param{msqid},
+scrivendolo sulla struttura puntata da \param{msgp}, che dovrà avere un
+formato analogo a quello di fig.~\ref{fig:ipc_msbuf}. Una volta estratto, il
+messaggio sarà rimosso dalla coda. L'argomento \param{msgsz} indica la
+lunghezza massima del testo del messaggio (equivalente al valore del parametro
+\const{LENGTH} nell'esempio di fig.~\ref{fig:ipc_msbuf}).
Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a
restituendo il primo messaggio incontrato che corrisponde ai criteri
specificati (che quindi, visto come i messaggi vengono sempre inseriti dalla
coda, è quello meno recente); in particolare:
-\begin{itemize}
+\begin{itemize*}
\item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
quello fra i presenti che è stato inserito per primo.
\item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
\item se \param{msgtyp} è negativo viene estratto il primo fra i messaggi con
il valore più basso del tipo, fra tutti quelli il cui tipo ha un valore
inferiore al valore assoluto di \param{msgtyp}.
-\end{itemize}
+\end{itemize*}
Il valore di \param{msgflg} permette di controllare il comportamento della
funzione, esso può essere nullo o una maschera binaria composta da uno o più
ci sono messaggi sulla coda.
Il comportamento usuale della funzione infatti, se non ci sono messaggi
-disponibili per la lettura, è di bloccare il processo in stato di
-\textit{sleep}. Nel caso però si sia specificato \const{IPC\_NOWAIT} la
-funzione ritorna immediatamente con un errore \errcode{ENOMSG}. Altrimenti la
-funzione ritorna normalmente non appena viene inserito un messaggio del tipo
-desiderato, oppure ritorna con errore qualora la coda sia rimossa (con
-\var{errno} impostata a \errcode{EIDRM}) o se il processo viene interrotto da
-un segnale (con \var{errno} impostata a \errcode{EINTR}).
+disponibili per la lettura, è di bloccare il processo. Nel caso però si sia
+specificato \const{IPC\_NOWAIT} la funzione ritorna immediatamente con un
+errore \errcode{ENOMSG}. Altrimenti la funzione ritorna normalmente non appena
+viene inserito un messaggio del tipo desiderato, oppure ritorna con errore
+qualora la coda sia rimossa (con \var{errno} impostata a \errcode{EIDRM}) o se
+il processo viene interrotto da un segnale (con \var{errno} impostata a
+\errcode{EINTR}).
Una volta completata con successo l'estrazione del messaggio dalla coda, la
funzione aggiorna i dati mantenuti in \struct{msqid\_ds}, in particolare
\end{itemize*}
Le code di messaggi presentano il solito problema di tutti gli oggetti del
-SysV-IPC; essendo questi permanenti restano nel sistema occupando risorse
-anche quando un processo è terminato, al contrario delle \textit{pipe} per le
-quali tutte le risorse occupate vengono rilasciate quanto l'ultimo processo
-che le utilizzava termina. Questo comporta che in caso di errori si può
-saturare il sistema, e che devono comunque essere esplicitamente previste
+\textit{SysV-IPC} che essendo questi permanenti restano nel sistema occupando
+risorse anche quando un processo è terminato, al contrario delle \textit{pipe}
+per le quali tutte le risorse occupate vengono rilasciate quanto l'ultimo
+processo che le utilizzava termina. Questo comporta che in caso di errori si
+può saturare il sistema, e che devono comunque essere esplicitamente previste
delle funzioni di rimozione in caso di interruzioni o uscite dal programma
(come vedremo in fig.~\ref{fig:ipc_mq_fortune_server}).
-L'altro problema è non facendo uso di file descriptor le tecniche di
+L'altro problema è che non facendo uso di file descriptor le tecniche di
\textit{I/O multiplexing} descritte in sez.~\ref{sec:file_multiplexing} non
possono essere utilizzate, e non si ha a disposizione niente di analogo alle
funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di
Il programma, oltre alle solite variabili per il nome del file da cui leggere
le \textit{fortunes} e per il vettore di stringhe che contiene le frasi,
definisce due strutture appositamente per la comunicazione; con
-\var{msgbuf\_read} (\texttt{\small 8--11}) vengono passate le richieste mentre
-con \var{msgbuf\_write} (\texttt{\small 12--15}) vengono restituite le frasi.
+\var{msgbuf\_read} vengono passate (\texttt{\small 8--11}) le richieste mentre
+con \var{msgbuf\_write} vengono restituite (\texttt{\small 12--15}) le frasi.
La gestione delle opzioni si è al solito omessa, essa si curerà di impostare
-in \var{n} il numero di frasi da leggere specificato a linea di comando ed in
-\var{fortunefilename} il file da cui leggerle; dopo aver installato
-(\texttt{\small 19--21}) i gestori dei segnali per trattare l'uscita dal
-server, viene prima controllato (\texttt{\small 22}) il numero di frasi
-richieste abbia senso (cioè sia maggiore di zero), le quali poi
-(\texttt{\small 23}) vengono lette nel vettore in memoria con la stessa
-funzione \code{FortuneParse} usata anche per il server basato sulle
-\textit{fifo}.
+nella variabile \var{n} il numero di frasi da leggere specificato a linea di
+comando ed in \var{fortunefilename} il file da cui leggerle. Dopo aver
+installato (\texttt{\small 19--21}) i gestori dei segnali per trattare
+l'uscita dal server, viene prima controllato (\texttt{\small 22}) il numero di
+frasi richieste abbia senso (cioè sia maggiore di zero), le quali poi vengono
+lette (\texttt{\small 23}) nel vettore in memoria con la stessa funzione
+\code{FortuneParse} usata anche per il server basato sulle \textit{fifo}.
Una volta inizializzato il vettore di stringhe coi messaggi presi dal file
delle \textit{fortune} si procede (\texttt{\small 25}) con la generazione di
la funzione \func{daemon} per andare in background e poi esegue in permanenza
il ciclo principale (\texttt{\small 33--40}). Questo inizia (\texttt{\small
34}) con il porsi in attesa di un messaggio di richiesta da parte di un
-client; si noti infatti come \func{msgrcv} richieda un messaggio con
-\var{mtype} uguale a 1: questo è il valore usato per le richieste dato che
+client. Si noti infatti come \func{msgrcv} richieda un messaggio con
+\var{mtype} uguale a 1, questo è il valore usato per le richieste dato che
corrisponde al \ids{PID} di \cmd{init}, che non può essere un client. L'uso
del flag \const{MSG\_NOERROR} è solo per sicurezza, dato che i messaggi di
richiesta sono di dimensione fissa (e contengono solo il \ids{PID} del
preesistente. In caso di errore (ad esempio se il server non è stato avviato)
il programma termina immediatamente.
-Una volta acquisito l'identificatore della coda il client compone il
-messaggio di richiesta (\texttt{\small 12--13}) in \var{msg\_read}, usando 1
-per il tipo ed inserendo il proprio \ids{PID} come dato da passare al server.
-Calcolata (\texttt{\small 14}) la dimensione, provvede (\texttt{\small 15}) ad
-immettere la richiesta sulla coda.
-
-A questo punto non resta che (\texttt{\small 16}) rileggere dalla coda la
-risposta del server richiedendo a \func{msgrcv} di selezionare i messaggi di
-tipo corrispondente al valore del \ids{PID} inviato nella richiesta. L'ultimo
-passo (\texttt{\small 17}) prima di uscire è quello di stampare a video il
-messaggio ricevuto.
+Una volta acquisito l'identificatore della coda il client compone
+(\texttt{\small 12--13}) il messaggio di richiesta in \var{msg\_read}, usando
+1 per il tipo ed inserendo il proprio \ids{PID} come dato da passare al
+server. Calcolata (\texttt{\small 14}) la dimensione, provvede
+(\texttt{\small 15}) ad immettere la richiesta sulla coda.
+
+A questo punto non resta che rileggere la risposta (\texttt{\small 16}) dalla
+coda del server richiedendo a \func{msgrcv} di selezionare i messaggi di tipo
+corrispondente al valore del \ids{PID} inviato nella richiesta. L'ultimo passo
+(\texttt{\small 17}) prima di uscire è quello di stampare a video il messaggio
+ricevuto.
Proviamo allora il nostro nuovo sistema, al solito occorre definire
-\code{LD\_LIBRARY\_PATH} per accedere alla libreria \file{libgapil.so}, dopo di
-che, in maniera del tutto analoga a quanto fatto con il programma che usa le
-fifo, potremo far partire il server con:
-\begin{verbatim}
-[piccardi@gont sources]$ ./mqfortuned -n10
-\end{verbatim}%$
+\code{LD\_LIBRARY\_PATH} per accedere alla libreria \file{libgapil.so}, dopo
+di che, in maniera del tutto analoga a quanto fatto con il programma che usa
+le \textit{fifo}, potremo far partire il server con:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./mqfortuned -n10}
+\end{Console}
+%$
come nel caso precedente, avendo eseguito il server in background, il comando
ritornerà immediatamente; potremo però verificare con \cmd{ps} che il
programma è effettivamente in esecuzione, e che ha creato una coda di
messaggi:
-\begin{verbatim}
-[piccardi@gont sources]$ ipcs
+\begin{Console}
+[piccardi@gont sources]$ \textbf{ipcs}
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
------ Message Queues --------
key msqid owner perms used-bytes messages
0x0102dc6a 0 piccardi 666 0 0
-\end{verbatim}
+\end{Console}
+%$
a questo punto potremo usare il client per ottenere le nostre frasi:
-\begin{verbatim}
-[piccardi@gont sources]$ ./mqfortune
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./mqfortune}
Linux ext2fs has been stable for a long time, now it's time to break it
-- Linuxkongreß '95 in Berlin
-[piccardi@gont sources]$ ./mqfortune
+[piccardi@gont sources]$ \textbf{./mqfortune}
Let's call it an accidental feature.
--Larry Wall
-\end{verbatim}
+\end{Console}
con un risultato del tutto equivalente al precedente. Infine potremo chiudere
il server inviando il segnale di terminazione con il comando \code{killall
- mqfortuned} verificando che effettivamente la coda di messaggi viene rimossa.
+ mqfortuned}, verificando che effettivamente la coda di messaggi venga
+rimossa.
Benché funzionante questa architettura risente dello stesso inconveniente
visto anche nel caso del precedente server basato sulle \textit{fifo}; se il
\textit{fifo} si aveva il problema delle \textit{fifo} che restavano nel
filesystem). In questo caso però il problemi sono maggiori, sia perché è molto
più facile esaurire la memoria dedicata ad una coda di messaggi che gli
-\itindex{inode} inode di un filesystem, sia perché, con il riutilizzo dei
-\ids{PID} da parte dei processi, un client eseguito in un momento successivo
-potrebbe ricevere un messaggio non indirizzato a lui.
+\itindex{inode} \textit{inode} di un filesystem, sia perché, con il riutilizzo
+dei \ids{PID} da parte dei processi, un client eseguito in un momento
+successivo potrebbe ricevere un messaggio non indirizzato a lui.
-\subsection{Semafori}
+\subsection{I semafori}
\label{sec:ipc_sysv_sem}
-I semafori non sono meccanismi di intercomunicazione diretta come quelli
-(\textit{pipe}, \textit{fifo} e code di messaggi) visti finora, e non
-consentono di scambiare dati fra processi, ma servono piuttosto come
-meccanismi di sincronizzazione o di protezione per le \index{sezione~critica}
+I semafori non sono propriamente meccanismi di intercomunicazione come
+\textit{pipe}, \textit{fifo} e code di messaggi, poiché non consentono di
+scambiare dati fra processi, ma servono piuttosto come meccanismi di
+sincronizzazione o di protezione per le \index{sezione~critica}
\textsl{sezioni critiche} del codice (si ricordi quanto detto in
-sez.~\ref{sec:proc_race_cond}).
-
-Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a
-seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione
-di un programma. In questo modo l'accesso ad una risorsa condivisa da più
-processi può essere controllato, associando ad essa un semaforo che consente
-di assicurare che non più di un processo alla volta possa usarla.
+sez.~\ref{sec:proc_race_cond}). Un semaforo infatti non è altro che un
+contatore mantenuto nel kernel che determina se consentire o meno la
+prosecuzione dell'esecuzione di un programma. In questo modo si può
+controllare l'accesso ad una risorsa condivisa da più processi, associandovi
+un semaforo che assicuri che non possa essere usata da più di un processo alla
+volta.
Il concetto di semaforo è uno dei concetti base nella programmazione ed è
assolutamente generico, così come del tutto generali sono modalità con cui lo
-si utilizza. Un processo che deve accedere ad una risorsa eseguirà un
-controllo del semaforo: se questo è positivo il suo valore sarà decrementato,
-indicando che si è consumato una unità della risorsa, ed il processo potrà
-proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta
-completate le operazioni volute, reincrementando il semaforo.
-
-Se al momento del controllo il valore del semaforo è nullo, siamo invece in
-una situazione in cui la risorsa non è disponibile, ed il processo si
-bloccherà in stato di \textit{sleep} fin quando chi la sta utilizzando non la
-rilascerà, incrementando il valore del semaforo. Non appena il semaforo torna
-positivo, indicando che la risorsa è disponibile, il processo sarà svegliato,
-e si potrà operare come nel caso precedente (decremento del semaforo, accesso
-alla risorsa, incremento del semaforo).
+si utilizza. Un processo che deve accedere ad una risorsa condivisa eseguirà
+un controllo del semaforo: se questo è positivo il suo valore sarà
+decrementato, indicando che si è consumato una unità della risorsa, ed il
+processo potrà proseguire nell'utilizzo di quest'ultima, provvedendo a
+rilasciarla, una volta completate le operazioni volute, reincrementando il
+semaforo.
+
+Se al momento del controllo il valore del semaforo è nullo la risorsa viene
+considerata non disponibile, ed il processo si bloccherà fin quando chi la sta
+utilizzando non la rilascerà, incrementando il valore del semaforo. Non appena
+il semaforo diventa positivo, indicando che la risorsa è tornata disponibile,
+il processo bloccato in attesa riprenderà l'esecuzione, e potrà operare come
+nel caso precedente (decremento del semaforo, accesso alla risorsa, incremento
+del semaforo).
Per poter implementare questo tipo di logica le operazioni di controllo e
decremento del contatore associato al semaforo devono essere atomiche,
utilizzando il valore del contatore come indicatore del ``numero di risorse''
ancora disponibili.
-Il sistema di comunicazione inter-processo di \textit{SysV-IPC} prevede anche i
-semafori, ma gli oggetti utilizzati non sono semafori singoli, ma gruppi di
-semafori detti \textsl{insiemi} (o \textit{semaphore set}); la funzione che
-permette di creare o ottenere l'identificatore di un insieme di semafori è
-\funcd{semget}, ed il suo prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/ipc.h}
- \headdecl{sys/sem.h}
-
- \funcdecl{int semget(key\_t key, int nsems, int flag)}
-
- Restituisce 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
- 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
- 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
- contenere le strutture per un nuovo insieme di semafori.
- \end{errlist}
- ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST},
- \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.}
-\end{functions}
+Il sistema di intercomunicazione di \textit{SysV-IPC} prevede anche una
+implementazione dei semafori, ma gli oggetti utilizzati sono tuttavia non
+semafori singoli, ma gruppi (più propriamente \textsl{insiemi}) di semafori
+detti ``\textit{semaphore set}''. La funzione di sistema che permette di
+creare o ottenere l'identificatore di un insieme di semafori è \funcd{semget},
+ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/sem.h}
+\fdecl{int semget(key\_t key, int nsems, int flag)}
+\fdesc{Restituisce l'identificatore di un insieme di semafori.}
+}
+
+{La funzione ritorna l'identificatore (un intero positivo) in caso di successo
+ e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{ENOSPC}] si è superato il limite di sistema per il numero
+ totale di semafori (\const{SEMMNS}) o di insiemi (\const{SEMMNI}).
+ \item[\errcode{EINVAL}] \param{nsems} è minore di zero o maggiore del limite
+ sul numero di semafori di un 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
+ contenere le strutture per un nuovo insieme di semafori.
+ \end{errlist}
+ ed inoltre \errval{EACCES}, \errval{EEXIST}, \errval{EIDRM} e
+ \errval{ENOENT} con lo stesso significato che hanno per \func{msgget}.}
+\end{funcproto}
La funzione è del tutto analoga a \func{msgget}, solo che in questo caso
restituisce l'identificatore di un insieme di semafori, in particolare è
Purtroppo questa implementazione complica inutilmente lo schema elementare che
abbiamo descritto, dato che non è possibile definire un singolo semaforo, ma
se ne deve creare per forza un insieme. Ma questa in definitiva è solo una
-complicazione inutile, il problema è che i semafori del \textit{SysV-IPC}
-soffrono di altri due, ben più gravi, difetti.
+complicazione inutile dell'interfaccia, il problema è che i semafori forniti
+dal \textit{SysV-IPC} soffrono di altri due difetti progettuali molto più
+gravi.
Il primo difetto è che non esiste una funzione che permetta di creare ed
inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme
dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si
-perde così ogni possibilità di eseguire l'operazione atomicamente.
+perde così ogni possibilità di eseguire l'operazione atomicamente. Eventuali
+accessi che possono avvenire fra la creazione e l'inizializzazione potranno
+avere effetti imprevisti.
Il secondo difetto deriva dalla caratteristica generale degli oggetti del
\textit{SysV-IPC} di essere risorse globali di sistema, che non vengono
-cancellate quando nessuno le usa più; ci si così a trova a dover affrontare
-esplicitamente il caso in cui un processo termina per un qualche errore,
-lasciando un semaforo occupato, che resterà tale fino al successivo riavvio
-del sistema. Come vedremo esistono delle modalità per evitare tutto ciò, ma
-diventa necessario indicare esplicitamente che si vuole il ripristino del
-semaforo all'uscita del processo.
+cancellate quando nessuno le usa più. In questo caso il problema è più grave
+perché ci si a trova a dover affrontare esplicitamente il caso in cui un
+processo termina per un qualche errore lasciando un semaforo occupato, che
+resterà tale fino al successivo riavvio del sistema. Come vedremo esistono
+delle modalità per evitare tutto ciò, ma diventa necessario indicare
+esplicitamente che si vuole il ripristino del semaforo all'uscita del
+processo, e la gestione diventa più complicata.
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{.80\textwidth}
\includestruct{listati/semid_ds.h}
\end{minipage}
\normalsize
\end{figure}
A ciascun insieme di semafori è associata una struttura \struct{semid\_ds},
-riportata in fig.~\ref{fig:ipc_semid_ds}.\footnote{non si sono riportati i
- campi ad uso interno del kernel, che vedremo in
- fig.~\ref{fig:ipc_sem_schema}, che dipendono dall'implementazione.} Come nel
-caso delle code di messaggi quando si crea un nuovo insieme di semafori con
-\func{semget} questa struttura viene inizializzata, in particolare il campo
-\var{sem\_perm} viene inizializzato come illustrato in
+riportata in fig.~\ref{fig:ipc_semid_ds}.\footnote{anche in questo caso in
+ realtà il kernel usa una sua specifica struttura interna, ma i dati
+ significativi sono sempre quelli citati.} Come nel caso delle code di
+messaggi quando si crea un nuovo insieme di semafori con \func{semget} questa
+struttura viene inizializzata. In particolare il campo \var{sem\_perm}, che
+esprime i permessi di accesso, viene inizializzato come illustrato in
sez.~\ref{sec:ipc_sysv_access_control} (si ricordi che in questo caso il
permesso di scrittura è in realtà permesso di alterare il semaforo), per
quanto riguarda gli altri campi invece:
\begin{itemize*}
\item il campo \var{sem\_nsems}, che esprime il numero di semafori
nell'insieme, viene inizializzato al valore di \param{nsems}.
-\item il campo \var{sem\_ctime}, che esprime il tempo di creazione
+\item il campo \var{sem\_ctime}, che esprime il tempo di ultimo cambiamento
dell'insieme, viene inizializzato al tempo corrente.
\item il campo \var{sem\_otime}, che esprime il tempo dell'ultima operazione
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
- realizzazione del \textit{SysV-IPC} in Linux. In realtà questa struttura
- ormai è ridotta ai soli due primi membri, e gli altri vengono calcolati
- dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i
- valori associati ad un semaforo, restituiti dalle funzioni di controllo, e
- citati dalle pagine di manuale.} è riportata in fig.~\ref{fig:ipc_sem}.
-Questa struttura, non è accessibile in user space, ma i valori in essa
-specificati possono essere letti in maniera indiretta, attraverso l'uso delle
-funzioni di controllo.
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{.80\textwidth}
\includestruct{listati/sem.h}
\end{minipage}
\normalsize
\label{fig:ipc_sem}
\end{figure}
-I dati mantenuti nella struttura, ed elencati in fig.~\ref{fig:ipc_sem},
-indicano rispettivamente:
-\begin{description*}
+Ciascun semaforo dell'insieme è realizzato come una struttura di tipo
+\struct{sem} che ne contiene i dati essenziali, la cui definizione è riportata
+in fig.~\ref{fig:ipc_sem}.\footnote{in realtà in fig~\ref{fig:ipc_sem} si è
+ riportata la definizione originaria del kernel 1.0, che contiene la prima
+ realizzazione del \textit{SysV-IPC} in Linux; ormai questa struttura è
+ ridotta ai soli due primi membri, e gli altri vengono calcolati
+ dinamicamente, la si è usata solo a scopo di esempio, perché indica tutti i
+ valori associati ad un semaforo, restituiti dalle funzioni di controllo, e
+ citati dalle pagine di manuale.} Questa struttura non è accessibile
+direttamente dallo \textit{user space}, ma i valori in essa specificati
+possono essere letti in maniera indiretta, attraverso l'uso delle opportune
+funzioni di controllo. I dati mantenuti nella struttura, ed elencati in
+fig.~\ref{fig:ipc_sem}, indicano rispettivamente:
+\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
\item[\var{semval}] il valore numerico del semaforo.
\item[\var{sempid}] il \ids{PID} dell'ultimo processo che ha eseguito una
operazione sul semaforo.
\item[\var{semncnt}] il numero di processi in attesa che esso venga
incrementato.
\item[\var{semzcnt}] il numero di processi in attesa che esso si annulli.
-\end{description*}
+\end{basedescript}
+
+Come per le code di messaggi anche per gli insiemi di semafori esistono una
+serie di limiti, i cui valori sono associati ad altrettante costanti, che si
+sono riportate in tab.~\ref{tab:ipc_sem_limits}. Alcuni di questi limiti sono
+al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo
+direttamente nel file \sysctlfile{kernel/sem}.
\begin{table}[htb]
\footnotesize
\label{tab:ipc_sem_limits}
\end{table}
-Come per le code di messaggi anche per gli insiemi di semafori esistono una
-serie di limiti, i cui valori sono associati ad altrettante costanti, che si
-sono riportate in tab.~\ref{tab:ipc_sem_limits}. Alcuni di questi limiti sono
-al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo
-direttamente nel file \sysctlfile{kernel/sem}.
-La funzione che permette di effettuare le varie operazioni di controllo sui
-semafori (fra le quali, come accennato, è impropriamente compresa anche la
-loro inizializzazione) è \funcd{semctl}; il suo prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/ipc.h}
- \headdecl{sys/sem.h}
-
- \funcdecl{int semctl(int semid, int semnum, int cmd)}
- \funcdecl{int semctl(int semid, int semnum, int cmd, union semun arg)}
-
- Esegue le operazioni di controllo su un semaforo o un insieme di semafori.
-
- \bodydesc{La funzione restituisce in caso di successo un valore positivo
- quanto usata con tre argomenti ed un valore nullo quando usata con
- 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
+La funzione di sistema che permette di effettuare le varie operazioni di
+controllo sui semafori fra le quali, come accennato, è impropriamente compresa
+anche la loro inizializzazione, è \funcd{semctl}; il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/sem.h}
+\fdecl{int semctl(int semid, int semnum, int cmd)}
+\fdecl{int semctl(int semid, int semnum, int cmd, union semun arg)}
+\fdesc{Esegue le operazioni di controllo su un semaforo o un insieme di
+ semafori.}
+}
+
+{La funzione ritorna in caso di successo un valore positivo quanto usata con
+ tre argomenti ed un valore nullo quando usata con quattro e $-1$ per un
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] i permessi assegnati al semaforo non consentono
l'operazione richiesta.
\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.
+ ma il processo non è né il creatore né il proprietario del semaforo e
+ non ha i privilegi di amministratore.
\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}
- ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
-}
-\end{functions}
+ \end{errlist}
+ ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato
+ generico.}
+\end{funcproto}
La funzione può avere tre o quattro argomenti, a seconda dell'operazione
specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
\param{semid} o sul singolo semaforo di un insieme, specificato da
\param{semnum}.
+
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{.80\textwidth}
\includestruct{listati/semun.h}
\end{minipage}
\normalsize
Qualora la funzione operi con quattro argomenti \param{arg} è un argomento
generico, che conterrà un dato diverso a seconda dell'azione richiesta; per
-unificare l'argomento esso deve essere passato come una \struct{semun}, la cui
-definizione, con i possibili valori che può assumere, è riportata in
-fig.~\ref{fig:ipc_semun}.
+unificare detto argomento esso deve essere passato come una unione
+\struct{semun}, la cui definizione, con i possibili valori che può assumere, è
+riportata in fig.~\ref{fig:ipc_semun}.
+
+Nelle versioni più vecchie delle \acr{glibc} questa unione veniva definita in
+\file{sys/sem.h}, ma nelle versioni più recenti questo non avviene più in
+quanto lo standard POSIX.1-2001 richiede che sia sempre definita a cura del
+chiamante. In questa seconda evenienza le \acr{glibc} definiscono però la
+macro \macro{\_SEM\_SEMUN\_UNDEFINED} che può essere usata per controllare la
+situazione.
Come già accennato sia il comportamento della funzione che il numero di
argomenti con cui deve essere invocata dipendono dal valore dell'argomento
-\param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
-cioè non causano un errore di \errcode{EINVAL}) per questo argomento sono i
+\param{cmd}, che specifica l'azione da intraprendere. I valori validi, che
+cioè non causano un errore di \errcode{EINVAL}, per questo argomento sono i
seguenti:
-\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
-\item[\const{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il
- contenuto della relativa struttura \struct{semid\_ds} all'indirizzo
- specificato con \var{arg.buf}. Occorre avere il permesso di lettura.
+\begin{basedescript}{\desclabelwidth{1.6cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiandone i
+ valori nella struttura \struct{semid\_ds} posta all'indirizzo specificato
+ con \var{arg.buf}. Occorre avere il permesso di lettura.
L'argomento \param{semnum} viene ignorato.
\item[\const{IPC\_RMID}] Rimuove l'insieme di semafori e le relative strutture
- dati, con effetto immediato. Tutti i processi che erano stato di
- \textit{sleep} vengono svegliati, ritornando con un errore di
- \errcode{EIDRM}. L'\ids{UID} effettivo del processo deve corrispondere o al
- creatore o al proprietario dell'insieme, o all'amministratore. L'argomento
+ dati, con effetto immediato. Tutti i processi che erano bloccati in attesa
+ vengono svegliati, ritornando con un errore di \errcode{EIDRM}. L'\ids{UID}
+ effettivo del processo deve corrispondere o al creatore o al proprietario
+ dell'insieme, o all'amministratore. L'argomento
\param{semnum} viene ignorato.
\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
dell'insieme. I valori devono essere passati in una struttura
- \struct{semid\_ds} puntata da \param{arg.buf} di cui saranno usati soltanto i
- campi \var{sem\_perm.uid}, \var{sem\_perm.gid} e i nove bit meno
- significativi di \var{sem\_perm.mode}. L'\ids{UID} effettivo del processo deve
- corrispondere o al creatore o al proprietario dell'insieme, o
- all'amministratore. L'argomento \param{semnum} viene ignorato.
+ \struct{semid\_ds} puntata da \param{arg.buf} di cui saranno usati soltanto
+ i campi \var{sem\_perm.uid}, \var{sem\_perm.gid} e i nove bit meno
+ significativi di \var{sem\_perm.mode}. La funziona aggiorna anche il campo
+ \var{sem\_ctime}. L'\ids{UID} effettivo del processo deve corrispondere o
+ al creatore o al proprietario dell'insieme, o all'amministratore.
+ L'argomento \param{semnum} viene ignorato.
\item[\const{GETALL}] Restituisce il valore corrente di ciascun semaforo
dell'insieme (corrispondente al campo \var{semval} di \struct{sem}) nel
vettore indicato da \param{arg.array}. Occorre avere il permesso di lettura.
\struct{semid\_ds}. Si devono avere i privilegi di scrittura sul semaforo.
\end{basedescript}
+Come per \func{msgctl} esistono tre ulteriori valori, \const{IPC\_INFO},
+\const{SEM\_STAT} e \const{SEM\_INFO}, specifici di Linux e fuori da ogni
+standard, creati specificamente ad uso del comando \cmd{ipcs}. Dato che anche
+questi potranno essere modificati o rimossi, non devono essere utilizzati e
+pertanto non li tratteremo.
+
Quando si imposta il valore di un semaforo (sia che lo si faccia per tutto
l'insieme con \const{SETALL}, che per un solo semaforo con \const{SETVAL}), i
processi in attesa su di esso reagiscono di conseguenza al cambiamento di