\end{funcproto}
La funzione crea una \textit{pipe}, esegue una \func{fork} creando un nuovo
-processe nel quale invoca il programma \param{command} attraverso la shell (in
+processo nel quale invoca il programma \param{command} attraverso la shell (in
sostanza esegue \file{/bin/sh} con il flag \code{-c}).
L'argomento \param{type} deve essere una delle due stringhe \verb|"w"| o
\verb|"r"|, per richiedere che la \textit{pipe} restituita come valore di
tutte le volte che non ci sono richieste). Dopo di che, una volta terminata la
stringa (\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero
casuale per ricavare la frase da inviare, si procederà (\texttt{\small
- 42--46}) all'apertura della \textit{fifo} per la risposta, che poi
-\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si chiude
-la \textit{fifo} di risposta che non serve più.
+ 42--46}) all'apertura della \textit{fifo} per la risposta, che poi
+(\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si
+chiude la \textit{fifo} di risposta che non serve più.
Il codice del client è invece riportato in fig.~\ref{fig:ipc_fifo_client},
anche in questo caso si è omessa la gestione delle opzioni e la funzione che
identificare un oggetto, come sarebbe stato se lo si fosse associato ad in
file, e tutta l'interfaccia è inutilmente complessa. Per questo se ne
sconsiglia assolutamente l'uso nei nuovi programmi, considerato che è ormai
-disponibile una revisione completa dei meccamismi di IPC fatta secondo quanto
+disponibile una revisione completa dei meccanismi di IPC fatta secondo quanto
indicato dallo standard POSIX.1b, che presenta una realizzazione più sicura ed
una interfaccia più semplice, che tratteremo in sez.~\ref{sec:ipc_posix}.
l'identificatore assuma tutti i valori possibili.
In fig.~\ref{fig:ipc_sysv_idtest} è riportato il codice di un semplice
-programma di test che si limita a creare un oggetto di ICP (specificato con
+programma di test che si limita a creare un oggetto di IPC (specificato con
una opzione a riga di comando), stamparne il numero di identificatore, e
cancellarlo, il tutto un numero di volte specificato tramite una seconda
opzione. La figura non riporta il codice di selezione delle opzioni, che
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. Lo schema
-illustrato in realta è una semplificazione di quello usato fino ai kernel
+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 (e non esiste una struttura \struct{msqid\_ds}
nel kernel), ma abbiamo mantenuto lo schema precedente dato che illustra in
\var{msg\_qbytes} oltre il limite \const{MSGMNB} senza essere
amministratore.
\end{errlist}
- ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato
+ ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato
generico.}
\end{funcproto}
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
+\const{MSG\_INFO}) introdotti ad uso del programma \cmd{ipcs} 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.
successivo potrebbe ricevere un messaggio non indirizzato a lui.
-
\subsection{I semafori}
\label{sec:ipc_sysv_sem}
effettuata, viene inizializzato a zero.
\end{itemize*}
-
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{.80\textwidth}
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{EACCES}] i permessi assegnati al semaforo non consentono
+ l'operazione di lettura o scrittura richiesta e non si hanno i privilegi
+ di amministratore.
\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 è né il creatore né il proprietario del semaforo e
\param{semid} o sul singolo semaforo di un insieme, specificato da
\param{semnum}.
-
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{.80\textwidth}
+ \begin{minipage}[c]{0.80\textwidth}
\includestruct{listati/semun.h}
\end{minipage}
\normalsize
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
-seguenti:
+\param{cmd}, che specifica l'azione da intraprendere. Per questo argomento i
+valori validi, quelli cioè che non causano un errore di \errcode{EINVAL}, sono
+i seguenti:
\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
\item[\const{GETNCNT}] Restituisce come valore di ritorno della funzione il
numero di processi in attesa che il semaforo \param{semnum} dell'insieme
\param{semid} venga incrementato (corrispondente al campo \var{semncnt} di
- \struct{sem}); va invocata con tre argomenti. Occorre avere il permesso di
+ \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di
lettura.
\item[\const{GETPID}] Restituisce come valore di ritorno della funzione il
\ids{PID} dell'ultimo processo che ha compiuto una operazione sul semaforo
\param{semnum} dell'insieme \param{semid} (corrispondente al campo
- \var{sempid} di \struct{sem}); va invocata con tre argomenti. Occorre avere
+ \var{sempid} di \struct{sem}). Va invocata con tre argomenti. Occorre avere
il permesso di lettura.
\item[\const{GETVAL}] Restituisce come valore di ritorno della funzione il il
valore corrente del semaforo \param{semnum} dell'insieme \param{semid}
- (corrispondente al campo \var{semval} di \struct{sem}); va invocata con tre
+ (corrispondente al campo \var{semval} di \struct{sem}). Va invocata con tre
argomenti. Occorre avere il permesso di lettura.
\item[\const{GETZCNT}] Restituisce come valore di ritorno della funzione il
numero di processi in attesa che il valore del semaforo \param{semnum}
dell'insieme \param{semid} diventi nullo (corrispondente al campo
- \var{semncnt} di \struct{sem}); va invocata con tre argomenti. Occorre avere
- il permesso di lettura.
+ \var{semncnt} di \struct{sem}). Va invocata con tre argomenti. Occorre
+ avere il permesso di lettura.
\item[\const{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
aggiornando il campo \var{sem\_ctime} di \struct{semid\_ds}. I valori devono
essere passati nel vettore indicato da \param{arg.array}. Si devono avere i
- privilegi di scrittura sul semaforo. L'argomento \param{semnum} viene
- ignorato.
+ privilegi di scrittura. L'argomento \param{semnum} viene ignorato.
\item[\const{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato
dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di
- \struct{semid\_ds}. Si devono avere i privilegi di scrittura sul semaforo.
+ \struct{semid\_ds}. Si devono avere i privilegi di scrittura.
\end{basedescript}
Come per \func{msgctl} esistono tre ulteriori valori, \const{IPC\_INFO},
Le operazioni ordinarie sui semafori, come l'acquisizione o il rilascio degli
stessi (in sostanza tutte quelle non comprese nell'uso di \func{semctl})
-vengono effettuate con la funzione \funcd{semop}, il cui prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/ipc.h}
- \headdecl{sys/sem.h}
-
- \funcdecl{int semop(int semid, struct sembuf *sops, unsigned nsops)}
-
- Esegue le operazioni ordinarie su un semaforo o un insieme di semafori.
-
- \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
- l'operazione richiesta.
- \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.
+vengono effettuate con la funzione di sistema \funcd{semop}, il cui prototipo
+è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/sem.h}
+\fdecl{int semop(int semid, struct sembuf *sops, unsigned nsops)}
+\fdesc{Esegue operazioni ordinarie su un semaforo o un insieme di semafori.}
+}
+
+{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{E2BIG}] l'argomento \param{nsops} è maggiore del numero
+ massimo di operazioni \const{SEMOPM}.
+ \item[\errcode{EACCES}] il processo non ha i permessi per eseguire
+ l'operazione richiesta e non ha i privilegi di amministratore.
\item[\errcode{EAGAIN}] un'operazione comporterebbe il blocco del processo,
ma si è specificato \const{IPC\_NOWAIT} in \var{sem\_flg}.
+ \item[\errcode{EFBIG}] il valore del campo \var{sem\_num} è negativo o
+ maggiore o uguale al numero di semafori dell'insieme.
+ \item[\errcode{EIDRM}] l'insieme di semafori è stato cancellato.
\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
- massimo di operazioni \const{SEMOPM}.
+ \item[\errcode{ENOMEM}] si è richiesto un \const{SEM\_UNDO} ma il sistema
+ non ha le risorse per allocare la struttura di ripristino.
\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}.
-}
-\end{functions}
-
-
-%TODO manca semtimedop, trattare qui, referenziata in
-%sez.~\ref{sec:sig_gen_beha}.
+ ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato
+ generico.}
+\end{funcproto}
La funzione permette di eseguire operazioni multiple sui singoli semafori di
un insieme. La funzione richiede come primo argomento l'identificatore
-\param{semid} dell'insieme su cui si vuole operare. Il numero di operazioni da
+\param{semid} dell'insieme su cui si vuole operare, il numero di operazioni da
effettuare viene specificato con l'argomento \param{nsop}, mentre il loro
contenuto viene passato con un puntatore ad un vettore di strutture
\struct{sembuf} nell'argomento \param{sops}. Le operazioni richieste vengono
-effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante.
+effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante,
+ed in tal caso vengono eseguite nella sequenza passata nel
+vettore \param{sops}.
+
+Con lo standard POSIX.1-2001 è stata introdotta una variante di \func{semop}
+che consente di specificare anche un tempo massimo di attesa. La nuova
+funzione di sistema, disponibile a partire dal kernel 2.4.22 e dalle
+\acr{glibc} 2.3.3, ed utilizzabile solo dopo aver definito la macro
+\macro{\_GNU\_SOURCE}, è \funcd{semtimedop}, ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/sem.h}
+\fdecl{int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
+ struct timespec *timeout)}
+\fdesc{Esegue operazioni ordinarie su un semaforo o un insieme di semafori.}
+}
+
+{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{EAGAIN}] l'operazione comporterebbe il blocco del processo,
+ ma si è specificato \const{IPC\_NOWAIT} in \var{sem\_flg} oppure si è
+ atteso oltre quanto indicato da \param{timeout}.
+ \end{errlist}
+ e gli altri valori già visti per \func{semop}, con lo stesso significato.}
+\end{funcproto}
+
+Rispetto a \func{semop} la funzione consente di specificare un tempo massimo
+di attesa, indicato con una struttura \struct{timespec} (vedi
+fig.~\ref{fig:sys_timespec_struct}), per le operazioni che verrebbero
+bloccate. Alla scadenza di detto tempo la funzione ritorna comunque con un
+errore di \errval{EAGAIN} senza che nessuna delle operazioni richieste venga
+eseguita.
+
+Si tenga presente che la precisione della temporizzazione è comunque limitata
+dalla risoluzione dell'orologio di sistema, per cui il tempo di attesa verrà
+arrotondato per eccesso. In caso si passi un valore \val{NULL}
+per \param{timeout} il comportamento di \func{semtimedop} è identico a quello
+di \func{semop}.
+
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{.80\textwidth}
\includestruct{listati/sembuf.h}
\end{minipage}
\normalsize
\label{fig:ipc_sembuf}
\end{figure}
-Il contenuto di ciascuna operazione deve essere specificato attraverso una
-opportuna struttura \struct{sembuf} (la cui definizione è riportata in
+Come indicato il contenuto di ciascuna operazione deve essere specificato
+attraverso una struttura \struct{sembuf} (la cui definizione è riportata in
fig.~\ref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di
allocare in un opportuno vettore. La struttura permette di indicare il
-semaforo su cui operare, il tipo di operazione, ed un flag di controllo.
+semaforo su cui operare, il tipo di operazione, ed un flag di controllo.
+
Il campo \var{sem\_num} serve per indicare a quale semaforo dell'insieme fa
-riferimento l'operazione; si ricordi che i semafori sono numerati come in un
-vettore, per cui il primo semaforo corrisponde ad un valore nullo di
-\var{sem\_num}.
+riferimento l'operazione. Si ricordi che i semafori sono numerati come gli
+elementi di un vettore, per cui il primo semaforo di un insieme corrisponde ad
+un valore nullo di \var{sem\_num}.
Il campo \var{sem\_flg} è un flag, mantenuto come maschera binaria, per il
quale possono essere impostati i due valori \const{IPC\_NOWAIT} e
-\const{SEM\_UNDO}. Impostando \const{IPC\_NOWAIT} si fa si che, invece di
-bloccarsi (in tutti quei casi in cui l'esecuzione di una operazione richiede
-che il processo vada in stato di \textit{sleep}), \func{semop} ritorni
-immediatamente con un errore di \errcode{EAGAIN}. Impostando \const{SEM\_UNDO}
-si richiede invece che l'operazione venga registrata in modo che il valore del
-semaforo possa essere ripristinato all'uscita del processo.
-
-Infine \var{sem\_op} è il campo che controlla l'operazione che viene eseguita
-e determina il comportamento della chiamata a \func{semop}; tre sono i casi
-possibili:
-\begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\var{sem\_op}$>0$] In questo caso il valore di \var{sem\_op} viene
- aggiunto al valore corrente di \var{semval}. La funzione ritorna
- immediatamente (con un errore di \errcode{ERANGE} qualora si sia superato il
- limite \const{SEMVMX}) ed il processo non viene bloccato in nessun caso.
- Specificando \const{SEM\_UNDO} si aggiorna il contatore per il ripristino
- del valore del semaforo. Al processo chiamante è richiesto il privilegio di
- alterazione (scrittura) sull'insieme di semafori.
+\const{SEM\_UNDO}. Impostando \const{IPC\_NOWAIT} si fa si che in tutti quei
+casi in cui l'esecuzione di una operazione richiederebbe di porre il processo
+vada nello stato di \textit{sleep}, invece di bloccarsi \func{semop} ritorni
+immediatamente (abortendo così le eventuali operazioni restanti) con un errore
+di \errcode{EAGAIN}. Impostando \const{SEM\_UNDO} si richiede invece che
+l'operazione in questione venga registrata, in modo che il valore del semaforo
+possa essere ripristinato all'uscita del processo.
+
+Infine \var{sem\_op} è il campo che controlla qual'è l'operazione che viene
+eseguita e determina in generale il comportamento della chiamata a
+\func{semop}. I casi possibili per il valore di questo campo sono tre:
+\begin{basedescript}{\desclabelwidth{1.8cm}}
+\item[\var{sem\_op} $>0$] In questo caso il valore viene aggiunto al valore
+ corrente di \var{semval} per il semaforo indicato. Questa operazione non
+ causa mai un blocco del processo, ed eventualmente \func{semop} ritorna
+ immediatamente con un errore di \errcode{ERANGE} qualora si sia superato il
+ limite \const{SEMVMX}. Se l'operazione ha successo si passa immediatamente
+ alla successiva. Specificando \const{SEM\_UNDO} si aggiorna il contatore
+ per il ripristino del valore del semaforo. Al processo chiamante è richiesto
+ il privilegio di alterazione (scrittura) sull'insieme di semafori.
-\item[\var{sem\_op}$=0$] Nel caso \var{semval} sia zero l'esecuzione procede
- immediatamente. Se \var{semval} è diverso da zero il comportamento è
- controllato da \var{sem\_flg}, se è stato impostato \const{IPC\_NOWAIT} la
- funzione ritorna con un errore di \errcode{EAGAIN}, altrimenti viene
- incrementato \var{semzcnt} di uno ed il processo resta in stato di
- \textit{sleep} fintanto che non si ha una delle condizioni seguenti:
+\item[\var{sem\_op} $=0$] Nel caso \var{semval} sia zero l'operazione ha
+ successo immediato, e o si passa alla successiva o \func{semop} ritorna con
+ successo se questa era l'ultima. Se \var{semval} è diverso da zero il
+ comportamento è controllato da \var{sem\_flg}, se è stato impostato
+ \const{IPC\_NOWAIT} \func{semop} ritorna immediatamente abortendo tutte le
+ operazioni con un errore di \errcode{EAGAIN}, altrimenti viene incrementato
+ \var{semzcnt} di uno ed il processo viene bloccato fintanto che non si
+ verifica una delle condizioni seguenti:
\begin{itemize*}
\item \var{semval} diventa zero, nel qual caso \var{semzcnt} viene
- decrementato di uno.
- \item l'insieme di semafori viene rimosso, nel qual caso \func{semop} ritorna
- un errore di \errcode{EIDRM}.
+ decrementato di uno, l'operazione ha successo e si passa alla successiva,
+ oppure \func{semop} ritorna con successo se questa era l'ultima.
+ \item l'insieme di semafori viene rimosso, nel qual caso \func{semop}
+ ritorna abortendo tutte le operazioni con un errore di \errcode{EIDRM}.
\item il processo chiamante riceve un segnale, nel qual caso \var{semzcnt}
- viene decrementato di uno e \func{semop} ritorna un errore di
- \errcode{EINTR}.
+ viene decrementato di uno e \func{semop} ritorna abortendo tutte le
+ operazioni con un errore di \errcode{EINTR}.
\end{itemize*}
- Al processo chiamante è richiesto il privilegio di lettura dell'insieme dei
- semafori.
+ Al processo chiamante è richiesto soltanto il privilegio di lettura
+ dell'insieme dei semafori.
-\item[\var{sem\_op}$<0$] Nel caso in cui \var{semval} è maggiore o uguale del
+\item[\var{sem\_op} $<0$] Nel caso in cui \var{semval} è maggiore o uguale del
valore assoluto di \var{sem\_op} (se cioè la somma dei due valori resta
- positiva o nulla) i valori vengono sommati e la funzione ritorna
- immediatamente; qualora si sia impostato \const{SEM\_UNDO} viene anche
+ positiva o nulla) i valori vengono sommati e l'operazione ha successo e si
+ passa alla successiva, oppure \func{semop} ritorna con successo se questa
+ era l'ultima. Qualora si sia impostato \const{SEM\_UNDO} viene anche
aggiornato il contatore per il ripristino del valore del semaforo. In caso
contrario (quando cioè la somma darebbe luogo ad un valore di \var{semval}
- negativo) se si è impostato \const{IPC\_NOWAIT} la funzione ritorna con un
- errore di \errcode{EAGAIN}, altrimenti viene incrementato di uno
- \var{semncnt} ed il processo resta in stato di \textit{sleep} fintanto che
- non si ha una delle condizioni seguenti:
+ negativo) se si è impostato \const{IPC\_NOWAIT} \func{semop} ritorna
+ immediatamente abortendo tutte le operazioni con un errore di
+ \errcode{EAGAIN}, altrimenti viene incrementato di uno \var{semncnt} ed il
+ processo resta in stato di \textit{sleep} fintanto che non si ha una delle
+ condizioni seguenti:
\begin{itemize*}
\item \var{semval} diventa maggiore o uguale del valore assoluto di
\var{sem\_op}, nel qual caso \var{semncnt} viene decrementato di uno, il
impostato \const{SEM\_UNDO} viene aggiornato il contatore per il
ripristino del valore del semaforo.
\item l'insieme di semafori viene rimosso, nel qual caso \func{semop}
- ritorna un errore di \errcode{EIDRM}.
+ ritorna abortendo tutte le operazioni con un errore di \errcode{EIDRM}.
\item il processo chiamante riceve un segnale, nel qual caso \var{semncnt}
- viene decrementato di uno e \func{semop} ritorna un errore di
- \errcode{EINTR}.
+ viene decrementato di uno e \func{semop} ritorna abortendo tutte le
+ operazioni con un errore di \errcode{EINTR}.
\end{itemize*}
Al processo chiamante è richiesto il privilegio di alterazione (scrittura)
sull'insieme di semafori.
\end{basedescript}
-In caso di successo della funzione viene aggiornato il campo \var{sempid} per
-ogni semaforo modificato al valore del \ids{PID} del processo chiamante;
-inoltre vengono pure aggiornati al tempo corrente i campi \var{sem\_otime} e
-\var{sem\_ctime}.
+Qualora si sia usato \func{semtimedop} alle condizioni di errore precedenti si
+aggiunge anche quella di scadenza del tempo di attesa indicato
+con \param{timeout} che farà abortire la funzione, qualora resti bloccata
+troppo a lungo nell'esecuzione delle operazioni richieste, con un errore di
+\errcode{EAGAIN}.
+
+In caso di successo (sia per \func{semop} che per \func{semtimedop}) per ogni
+semaforo modificato verrà aggiornato il campo \var{sempid} al valore del
+\ids{PID} del processo chiamante; inoltre verranno pure aggiornati al tempo
+corrente i campi \var{sem\_otime} e \var{sem\_ctime}.
Dato che, come già accennato in precedenza, in caso di uscita inaspettata i
-semafori possono restare occupati, abbiamo visto come \func{semop} permetta di
-attivare un meccanismo di ripristino attraverso l'uso del flag
-\const{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura
-\kstruct{sem\_undo}, associata ad ogni processo per ciascun semaforo che esso
-ha modificato; all'uscita i semafori modificati vengono ripristinati, e le
-strutture disallocate. Per mantenere coerente il comportamento queste
-strutture non vengono ereditate attraverso una \func{fork} (altrimenti si
-avrebbe un doppio ripristino), mentre passano inalterate nell'esecuzione di
-una \func{exec} (altrimenti non si avrebbe ripristino).
+semafori possono restare occupati, abbiamo visto come \func{semop} (e
+\func{semtimedop}) permetta di attivare un meccanismo di ripristino attraverso
+l'uso del flag \const{SEM\_UNDO}. Il meccanismo è implementato tramite una
+apposita struttura \kstruct{sem\_undo}, associata ad ogni processo per ciascun
+semaforo che esso ha modificato; all'uscita i semafori modificati vengono
+ripristinati, e le strutture disallocate. Per mantenere coerente il
+comportamento queste strutture non vengono ereditate attraverso una
+\func{fork} (altrimenti si avrebbe un doppio ripristino), mentre passano
+inalterate nell'esecuzione di una \func{exec} (altrimenti non si avrebbe
+ripristino).
Tutto questo però ha un problema di fondo. Per capire di cosa si tratta
occorre fare riferimento all'implementazione usata in Linux, che è riportata
in maniera semplificata nello schema di fig.~\ref{fig:ipc_sem_schema}. Si è
presa come riferimento l'architettura usata fino al kernel 2.2.x che è più
-semplice (ed illustrata in dettaglio in \cite{tlk}); nel kernel 2.4.x la
+semplice (ed illustrata in dettaglio in \cite{tlk}). Nel kernel 2.4.x la
struttura del \textit{SysV-IPC} è stata modificata, ma le definizioni relative
-a queste strutture restano per compatibilità.\footnote{in particolare con le
- vecchie versioni delle librerie del C, come le libc5.}
+a queste strutture restano per compatibilità (in particolare con le vecchie
+versioni delle librerie del C, come le \acr{libc5}).
\begin{figure}[!htb]
- \centering \includegraphics[width=13cm]{img/semtruct}
+ \centering \includegraphics[width=12cm]{img/semtruct}
\caption{Schema della struttura di un insieme di semafori.}
\label{fig:ipc_sem_schema}
\end{figure}
\struct{semid\_ds} ed il relativo vettore di strutture \struct{sem}. Quando si
richiede una operazione viene anzitutto verificato che tutte le operazioni
possono avere successo; se una di esse comporta il blocco del processo il
-kernel crea una struttura \kstruct{sem\_queue} che viene aggiunta in fondo alla
-coda di attesa associata a ciascun insieme di semafori\footnote{che viene
- referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last}
- di \struct{semid\_ds}.}.
-
-Nella struttura viene memorizzato il riferimento alle operazioni richieste
-(nel campo \var{sops}, che è un puntatore ad una struttura \struct{sembuf}) e
-al processo corrente (nel campo \var{sleeper}) poi quest'ultimo viene messo
-stato di attesa e viene invocato lo \itindex{scheduler} scheduler per passare
-all'esecuzione di un altro processo.
+kernel crea una struttura \kstruct{sem\_queue} che viene aggiunta in fondo
+alla coda di attesa associata a ciascun insieme di semafori, che viene
+referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last} di
+\struct{semid\_ds}. Nella struttura viene memorizzato il riferimento alle
+operazioni richieste (nel campo \var{sops}, che è un puntatore ad una
+struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper})
+poi quest'ultimo viene messo stato di attesa e viene invocato lo
+\itindex{scheduler} \textit{scheduler} per passare all'esecuzione di un altro
+processo.
Se invece tutte le operazioni possono avere successo queste vengono eseguite
immediatamente, dopo di che il kernel esegue una scansione della coda di
aggiustamento per ogni semaforo cui viene sommato l'opposto del valore usato
per l'operazione.
-%TODO verificare queste strutture \kstruct{sem\_queue} e \kstruct{sem\_undo}
-
-Queste strutture sono mantenute in due liste,\footnote{rispettivamente
- attraverso i due campi \var{id\_next} e \var{proc\_next}.} una associata
-all'insieme di cui fa parte il semaforo, che viene usata per invalidare le
-strutture se questo viene cancellato o per azzerarle se si è eseguita una
-operazione con \func{semctl}; l'altra associata al processo che ha eseguito
-l'operazione;\footnote{attraverso il campo \var{semundo} di
- \kstruct{task\_struct}, come mostrato in \ref{fig:ipc_sem_schema}.} quando un
-processo termina, la lista ad esso associata viene scandita e le operazioni
-applicate al semaforo. Siccome un processo può accumulare delle richieste di
-ripristino per semafori differenti chiamate attraverso diverse chiamate a
-\func{semop}, si pone il problema di come eseguire il ripristino dei semafori
-all'uscita del processo, ed in particolare se questo può essere fatto
-atomicamente.
+Queste strutture sono mantenute in due liste (rispettivamente attraverso i due
+campi \var{id\_next} e \var{proc\_next}) una associata all'insieme di cui fa
+parte il semaforo, che viene usata per invalidare le strutture se questo viene
+cancellato o per azzerarle se si è eseguita una operazione con \func{semctl},
+l'altra associata al processo che ha eseguito l'operazione, attraverso il
+campo \var{semundo} di \kstruct{task\_struct}, come mostrato in
+\ref{fig:ipc_sem_schema}. Quando un processo termina, la lista ad esso
+associata viene scandita e le operazioni applicate al semaforo. Siccome un
+processo può accumulare delle richieste di ripristino per semafori differenti
+attraverso diverse chiamate a \func{semop}, si pone il problema di come
+eseguire il ripristino dei semafori all'uscita del processo, ed in particolare
+se questo può essere fatto atomicamente.
Il punto è cosa succede quando una delle operazioni previste per il ripristino
non può essere eseguita immediatamente perché ad esempio il semaforo è
\label{sec:ipc_sysv_shm}
Il terzo oggetto introdotto dal \textit{SysV-IPC} è quello dei segmenti di
-memoria condivisa. La funzione che permette di ottenerne uno è \funcd{shmget},
-ed il suo prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/ipc.h}
- \headdecl{sys/shm.h}
-
- \funcdecl{int shmget(key\_t key, int size, int flag)}
-
- Restituisce l'identificatore di una memoria condivisa.
-
- \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}
+memoria condivisa. La funzione di sistema che permette di ottenerne uno è
+\funcd{shmget}, ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/shm.h}
+\fdecl{int shmget(key\_t key, int size, int flag)}
+\fdesc{Ottiene o crea una memoria condivisa.}
+}
+
+{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 (\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
già esiste \param{size} è maggiore delle sue dimensioni.
\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},
- \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.}
-\end{functions}
+ \item[\errcode{ENOMEM}] si è specificato \const{IPC\_HUGETLB} ma non si
+ hanno i privilegi di amministratore.
+ \end{errlist}
+ ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST},
+ \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.}
+\end{funcproto}
-La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed
-identico è l'uso degli argomenti \param{key} e \param{flag} per cui non
-ripeteremo quanto detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. L'argomento
-\param{size} specifica invece la dimensione, in byte, del segmento, che viene
-comunque arrotondata al multiplo superiore di \const{PAGE\_SIZE}.
-% TODO aggiungere l'uso di SHM_HUGETLB introdotto con il kernel 2.6.0
+La funzione, come \func{semget}, è analoga a \func{msgget}, ed identico è
+l'uso degli argomenti \param{key} e \param{flag} per cui non ripeteremo quanto
+detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. A partire dal kernel 2.6
+però sono stati introdotti degli ulteriori bit di controllo per
+l'argomento \param{flag}, specifici di \func{shmget}, attinenti alle modalità
+di gestione del segmento di memoria condivisa in relazione al sistema della
+memoria virtuale.
+
+Il primo dei due flag è \const{SHM\_HUGETLB} che consente di richiedere la
+creazione del segmento usando una \itindex{huge~page} \textit{huge page}, le
+pagine di memoria di grandi dimensioni introdotte con il kernel 2.6 per
+ottimizzare le prestazioni nei sistemi più recenti che hanno grandi quantità
+di memoria. L'operazione è privilegiata e richiede che il processo abbia la
+\itindex{capability} \textit{capability} \const{CAP\_IPC\_LOCK}. Questa
+funzionalità è specifica di Linux e non è portabile.
+
+Il secondo flag aggiuntivo, introdotto a partire dal kernel 2.6.15, è
+\const{SHM\_NORESERVE}, ed ha lo stesso scopo del flag \const{MAP\_NORESERVE}
+di \func{mmap} (vedi sez.~\ref{sec:file_memory_map}): non vengono riservate
+delle pagine di swap ad uso del meccanismo del \textit{copy on write}
+\itindex{copy~on~write} per mantenere le modifiche fatte sul segmento. Questo
+significa che caso di scrittura sul segmento quando non c'è più memoria
+disponibile, si avrà l'emissione di un \signal{SIGSEGV}.
+
+% TODO verificare i privilegi necessari per SHM_HUGETLB
+
+Infine l'argomento \param{size} specifica la dimensione del segmento di
+memoria condivisa; il valore deve essere specificato in byte, ma verrà
+comunque arrotondato al multiplo superiore di \const{PAGE\_SIZE}. Il valore
+deve essere specificato quando si crea un nuovo segmento di memoria con
+\const{IPC\_CREAT} o \const{IPC\_PRIVATE}, se invece si accede ad un segmento
+di memoria condivisa esistente non può essere maggiore del valore con cui esso
+è stato creato.
La memoria condivisa è la forma più veloce di comunicazione fra due processi,
in quanto permette agli stessi di vedere nel loro spazio di indirizzi una
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{0.80\textwidth}
\includestruct{listati/shmid_ds.h}
\end{minipage}
\normalsize
sez.~\ref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte
relativamente ai permessi di accesso; per quanto riguarda gli altri campi
invece:
-\begin{itemize}
+\begin{itemize*}
\item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene
inizializzato al valore di \param{size}.
\item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
creato il segmento, viene inizializzato al \ids{PID} del processo chiamante.
\item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati
al segmento viene inizializzato a zero.
-\end{itemize}
+\end{itemize*}
Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
di memoria condivisa esistono una serie di limiti imposti dal sistema. Alcuni
pagina di memoria).\\
\const{SHMSEG}& --- & --- & Numero massimo di segmenti di
memoria condivisa per ciascun
- processo.\\
+ processo (l'implementazione non
+ prevede l'esistenza di questo
+ limite).\\
\hline
\label{tab:ipc_shm_limits}
\end{table}
-Al solito la funzione che permette di effettuare le operazioni di controllo su
-un segmento di memoria condivisa è \funcd{shmctl}; il suo prototipo è:
-\begin{functions}
- \headdecl{sys/ipc.h}
- \headdecl{sys/shm.h}
-
- \funcdecl{int shmctl(int shmid, int cmd, struct shmid\_ds *buf)}
-
- Esegue le operazioni di controllo su 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}
+Al solito la funzione di sistema che permette di effettuare le operazioni di
+controllo su un segmento di memoria condivisa è \funcd{shmctl}; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/ipc.h}
+\fhead{sys/shm.h}
+\fdecl{int shmctl(int shmid, int cmd, struct shmid\_ds *buf)}
+
+\fdesc{Esegue le operazioni di controllo su un segmento di memoria condivisa.}
+}
+
+{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}] 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{EFAULT}] l'indirizzo specificato con \param{buf} non è
+ valido.
\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
- \const{IPC\_RMID} senza i permessi necessari.
+ \item[\errcode{EINVAL}] o \param{shmid} non è un identificatore valido o
+ \param{cmd} non è un comando valido.
+ \item[\errcode{ENOMEM}] si è richiesto un \textit{memory lock} di
+ dimensioni superiori al massimo consentito.
\item[\errcode{EOVERFLOW}] si è tentato il comando \const{IPC\_STAT} ma il
valore del \ids{GID} o dell'\ids{UID} è troppo grande per essere
memorizzato nella struttura puntata da \param{buf}.
- \item[\errcode{EFAULT}] l'indirizzo specificato con \param{buf} non è
- valido.
- \end{errlist}
-}
-\end{functions}
+ \item[\errcode{EPERM}] si è specificato un comando con \const{IPC\_SET} o
+ \const{IPC\_RMID} senza i permessi necessari.
+ \end{errlist}
+}
+\end{funcproto}
Il comando specificato attraverso l'argomento \param{cmd} determina i diversi
-effetti della funzione; i possibili valori che esso può assumere, ed il
-corrispondente comportamento della funzione, sono i seguenti:
+effetti della funzione. Nello standard POSIX.1-2001 i valori che esso può
+assumere, ed il corrispondente comportamento della funzione, sono i seguenti:
\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
\item[\const{IPC\_STAT}] Legge le informazioni riguardo il segmento di memoria
\var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
il creatore del segmento, oppure l'amministratore. Compiuta l'operazione
aggiorna anche il valore del campo \var{shm\_ctime}.
+\end{basedescript}
+
+Oltre ai precedenti su Linux sono definiti anche degli ulteriori comandi, che
+consentono di estendere le funzionalità, ovviamente non devono essere usati se
+si ha a cuore la portabilità. Questi comandi aggiuntivi sono:
+
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
\item[\const{SHM\_LOCK}] Abilita il \itindex{memory~locking} \textit{memory
- locking}\footnote{impedisce cioè che la memoria usata per il segmento
- venga salvata su disco dal meccanismo della \index{memoria~virtuale}
- memoria virtuale; si ricordi quanto trattato in
- sez.~\ref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo
- l'amministratore può utilizzare questo comando.
+ locking} sul segmento di memoria condivisa, impedendo che la memoria usata
+ per il segmento venga salvata su disco dal meccanismo della
+ \index{memoria~virtuale} memoria virtuale. Come illustrato in
+ sez.~\ref{sec:proc_mem_lock} fino al kernel 2.6.9 solo l'amministratore
+ poteva utilizzare questa capacità,\footnote{che richiedeva la
+ \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal dal kernel
+ 2.6.10 anche gli utenti normali possono farlo fina al limite massimo
+ determinato da \const{RLIMIT\_MEMLOCK} (vedi
+ sez.~\ref{sec:sys_resource_limit}).
\item[\const{SHM\_UNLOCK}] Disabilita il \itindex{memory~locking}
- \textit{memory locking} sul segmento di memoria condivisa. Solo
- l'amministratore può utilizzare questo comando.
+ \textit{memory locking} sul segmento di memoria condivisa. Fino al kernel
+ 2.6.9 solo l'amministratore poteva utilizzare questo comando in
+ corrispondenza di un segmento da lui bloccato.
\end{basedescript}
-i primi tre comandi sono gli stessi già visti anche per le code di messaggi e
-gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche
-previste da Linux, che permettono di abilitare e disabilitare il meccanismo
-della \index{memoria~virtuale} memoria virtuale per il segmento.
+
+A questi due, come per \func{msgctl} e \func{semctl}, si aggiungono tre
+ulteriori valori, \const{IPC\_INFO}, \const{MSG\_STAT} e \const{MSG\_INFO},
+introdotti ad uso del programma \cmd{ipcs} per ottenere le informazioni
+generali relative alle risorse usate dai segmenti di memoria condivisa. Dato
+che potranno essere modificati o rimossi in favore dell'uso di \texttt{/proc},
+non devono essere usati e non li tratteremo.
L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT}
e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura
queste serve ad agganciare un segmento al processo chiamante, in modo che
quest'ultimo possa inserirlo nel suo spazio di indirizzi per potervi accedere;
il suo prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/shm.h}
-
- \funcdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)}
- Aggancia al processo un segmento di memoria condivisa.
-
- \bodydesc{La funzione restituisce l'indirizzo del segmento in caso di
- successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà i
- valori:
- \begin{errlist}
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/shm.h}
+\fdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)}
+
+\fdesc{Aggancia un segmento di memoria condivisa al processo chiamante.}
+}
+
+{La funzione ritorna l'indirizzo del segmento in caso di successo e $-1$ (in
+ un cast a \type{void *}) per un errore, nel qual caso \var{errno} assumerà
+ uno dei valori:
+ \begin{errlist}
\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
\param{shmid}, o un indirizzo non allineato sul confine di una pagina
- per \param{shmaddr}.
- \end{errlist}
- ed inoltre \errval{ENOMEM}.}
-\end{functions}
+ per \param{shmaddr} o il valore \val{NULL} indicando \const{SHM\_REMAP}.
+ \end{errlist}
+ ed inoltre \errval{ENOMEM} nel suo significato generico.
+}
+\end{funcproto}
La funzione inserisce un segmento di memoria condivisa all'interno dello
spazio di indirizzi del processo, in modo che questo possa accedervi
come il valore di ritorno della funzione; in Linux è stato così con le
\acr{libc4} e le \acr{libc5}, con il passaggio alla \acr{glibc} il tipo di
\param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di
- ritorno un \ctyp{void *}.} deve essere associato il segmento, se il valore
-specificato è \val{NULL} è il sistema a scegliere opportunamente un'area di
-memoria libera (questo è il modo più portabile e sicuro di usare la funzione).
-Altrimenti il kernel aggancia il segmento all'indirizzo specificato da
-\param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il
-limite di una pagina, cioè se è un multiplo esatto del parametro di sistema
-\const{SHMLBA}, che in Linux è sempre uguale \const{PAGE\_SIZE}.
+ ritorno un \ctyp{void *} seguendo POSIX.1-2001.} deve essere associato il
+segmento, se il valore specificato è \val{NULL} è il sistema a scegliere
+opportunamente un'area di memoria libera (questo è il modo più portabile e
+sicuro di usare la funzione). Altrimenti il kernel aggancia il segmento
+all'indirizzo specificato da \param{shmaddr}; questo però può avvenire solo se
+l'indirizzo coincide con il limite di una pagina, cioè se è un multiplo esatto
+del parametro di sistema \const{SHMLBA}, che in Linux è sempre uguale
+\const{PAGE\_SIZE}.
Si tenga presente però che quando si usa \val{NULL} come valore di
\param{shmaddr}, l'indirizzo restituito da \func{shmat} può cambiare da
riferiti all'indirizzo di partenza del segmento).
L'argomento \param{shmflg} permette di cambiare il comportamento della
-funzione; esso va specificato come maschera binaria, i bit utilizzati sono
-solo due e sono identificati dalle costanti \const{SHM\_RND} e
-\const{SHM\_RDONLY}, che vanno combinate con un OR aritmetico. Specificando
-\const{SHM\_RND} si evita che \func{shmat} ritorni un errore quando
-\param{shmaddr} non è allineato ai confini di una pagina. Si può quindi usare
-un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
-agganciato, ma al più vicino multiplo di \const{SHMLBA} (il nome della
+funzione; esso va specificato come maschera binaria, i bit utilizzati al
+momento sono sono tre e sono identificati dalle costanti \const{SHM\_RND},
+\const{SHM\_RDONLY} e \const{SHM\_REMAP} che vanno combinate con un OR
+aritmetico.
+
+Specificando \const{SHM\_RND} si evita che \func{shmat} ritorni un errore
+quando \param{shmaddr} non è allineato ai confini di una pagina. Si può quindi
+usare un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
+agganciato, ma al più vicino multiplo di \const{SHMLBA}; il nome della
costante sta infatti per \textit{rounded}, e serve per specificare un
-indirizzo come arrotondamento, in Linux è equivalente a \const{PAGE\_SIZE}).
+indirizzo come arrotondamento.
L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola
lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
deve aver questi permessi in \var{shm\_perm}), non è prevista la possibilità
di agganciare un segmento in sola scrittura.
-In caso di successo la funzione aggiorna anche i seguenti campi di
-\struct{shmid\_ds}:
+Infine \const{SHM\_REMAP} è una estensione specifica di Linux (quindi non
+portabile) che indica che la mappatura del segmento deve rimpiazzare ogni
+precedente mappatura esistente nell'intervallo iniziante
+all'indirizzo \param{shmaddr} e di dimensione pari alla lunghezza del
+segmento. In condizioni normali questo tipo di richiesta fallirebbe con un
+errore di \errval{EINVAL}. Ovviamente usando \const{SHM\_REMAP}
+l'argomento \param{shmaddr} non può essere nullo.
+
+In caso di successo la funzione \func{shmat} aggiorna anche i seguenti campi
+della struttura \struct{shmid\_ds}:
\begin{itemize*}
\item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene
impostato al tempo corrente.
segmento viene impostato a quello del processo corrente.
\item il numero \var{shm\_nattch} di processi agganciati al segmento viene
aumentato di uno.
-\end{itemize*}
+\end{itemize*}
Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa
agganciato ad un processo viene ereditato da un figlio attraverso una
Una volta che un segmento di memoria condivisa non serve più, si può
sganciarlo esplicitamente dal processo usando l'altra funzione
dell'interfaccia, \funcd{shmdt}, il cui prototipo è:
-\begin{functions}
- \headdecl{sys/types.h}
- \headdecl{sys/shm.h}
- \funcdecl{int shmdt(const void *shmaddr)}
- Sgancia dal processo un segmento di memoria condivisa.
-
- \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
- errore, la funzione fallisce solo quando non c'è un segmento agganciato
- all'indirizzo \param{shmaddr}, con \var{errno} che assume il valore
- \errval{EINVAL}.}
-\end{functions}
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/shm.h}
+\fdecl{int shmdt(const void *shmaddr)}
+
+\fdesc{Sgancia dal processo un segmento di memoria condivisa.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, la funzione
+ fallisce solo quando non c'è un segmento agganciato
+ all'indirizzo \param{shmaddr}, con \var{errno} che assume il valore
+ \errval{EINVAL}.
+}
+\end{funcproto}
La funzione sgancia dallo spazio degli indirizzi del processo un segmento di
memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr}
immediatamente in caso di errore. Questa funzione serve anche per impostare
la \index{directory~di~lavoro} directory di lavoro del programma nella
directory da tenere sotto controllo, in vista del successivo uso della
-funzione \func{daemon}.\footnote{si noti come si è potuta fare questa scelta,
- nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il
- particolare scopo del programma, che necessita comunque di restare
- all'interno di una directory.} Infine (\texttt{\small 27--29}) si installano
-i gestori per i vari segnali di terminazione che, avendo a che fare con un
-programma che deve essere eseguito come server, sono il solo strumento
-disponibile per concluderne l'esecuzione.
+funzione \func{daemon}. Si noti come si è potuta fare questa scelta,
+nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il
+particolare scopo del programma, che necessita comunque di restare all'interno
+di una directory.
+
+Infine (\texttt{\small 27--29}) si installano i gestori per i vari segnali di
+terminazione che, avendo a che fare con un programma che deve essere eseguito
+come server, sono il solo strumento disponibile per concluderne l'esecuzione.
Il passo successivo (\texttt{\small 30--39}) è quello di creare gli oggetti di
intercomunicazione necessari. Si inizia costruendo (\texttt{\small 30}) la
con l'esecuzione in background come si conviene ad un programma demone; si
noti che si è mantenuta, usando un valore non nullo del primo argomento, la
\index{directory~di~lavoro} directory di lavoro corrente. Una volta che il
-programma è andato in background l'esecuzione prosegue (\texttt{\small
- 42--48}) all'interno di un ciclo infinito: si inizia (\texttt{\small 43})
-bloccando il mutex con \func{MutexLock} per poter accedere alla memoria
-condivisa (la funzione si bloccherà automaticamente se qualche client sta
-leggendo), poi (\texttt{\small 44}) si cancellano i valori precedentemente
-immagazzinati nella memoria condivisa con \func{memset}, e si esegue
-(\texttt{\small 45}) un nuovo calcolo degli stessi utilizzando la funzione
-\myfunc{dir\_scan}; infine (\texttt{\small 46}) si sblocca il mutex con
-\func{MutexUnlock}, e si attende (\texttt{\small 47}) per il periodo di tempo
-specificato a riga di comando con l'opzione \code{-p} con una \func{sleep}.
+programma è andato in background l'esecuzione prosegue all'interno di un ciclo
+infinito (\texttt{\small 42--48}).
+
+Si inizia (\texttt{\small 43}) bloccando il mutex con \func{MutexLock} per
+poter accedere alla memoria condivisa (la funzione si bloccherà
+automaticamente se qualche client sta leggendo), poi (\texttt{\small 44}) si
+cancellano i valori precedentemente immagazzinati nella memoria condivisa con
+\func{memset}, e si esegue (\texttt{\small 45}) un nuovo calcolo degli stessi
+utilizzando la funzione \myfunc{dir\_scan}; infine (\texttt{\small 46}) si
+sblocca il mutex con \func{MutexUnlock}, e si attende (\texttt{\small 47}) per
+il periodo di tempo specificato a riga di comando con l'opzione \code{-p}
+usando una \func{sleep}.
Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si
sia usata ancora una volta la funzione \myfunc{dir\_scan}, già utilizzata (e
Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando
le funzioni di libreria occorre definire opportunamente
\code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con:
-\begin{Verbatim}
-[piccardi@gont sources]$ ./dirmonitor ./
-\end{Verbatim}
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./dirmonitor ./}
+\end{Console}
%$
ed avendo usato \func{daemon} il comando ritornerà immediatamente. Una volta
che il server è in esecuzione, possiamo passare ad invocare il client per
verificarne i risultati, in tal caso otterremo:
-\begin{Verbatim}
-[piccardi@gont sources]$ ./readmon
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./readmon}
Ci sono 68 file dati
Ci sono 3 directory
Ci sono 0 link
Ci sono 0 device a caratteri
Ci sono 0 device a blocchi
Totale 71 file, per 489831 byte
-\end{Verbatim}
+\end{Console}
%$
ed un rapido calcolo (ad esempio con \code{ls -a | wc} per contare i file) ci
permette di verificare che il totale dei file è giusto. Un controllo con
\cmd{ipcs} ci permette inoltre di verificare la presenza di un segmento di
memoria condivisa e di un semaforo:
-\begin{Verbatim}
-[piccardi@gont sources]$ ipcs
+\begin{Console}
+[piccardi@gont sources]$ \textbf{ipcs}
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0xffffffff 54067205 piccardi 666 4096 1
------ Message Queues --------
key msqid owner perms used-bytes messages
-\end{Verbatim}
+\end{Console}
%$
Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova},
potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o
l'eventuale altro intervallo impostato per la rilettura dei dati) avremo:
-\begin{Verbatim}
-[piccardi@gont sources]$ ./readmon
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./readmon}
Ci sono 69 file dati
Ci sono 3 directory
Ci sono 0 link
Ci sono 0 device a caratteri
Ci sono 0 device a blocchi
Totale 72 file, per 489887 byte
-\end{Verbatim}
+\end{Console}
%$
A questo punto possiamo far uscire il server inviandogli un segnale di
\signal{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto
ripetendo la lettura, otterremo un errore:
-\begin{Verbatim}
-[piccardi@gont sources]$ ./readmon
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./readmon}
Cannot find shared memory: No such file or directory
-\end{Verbatim}
+\end{Console}
%$
e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione
visti in precedenza sono stati regolarmente cancellati:
-\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
-\end{Verbatim}
+\end{Console}
%$
sincronizzazione, per cui alla fine l'uso delle code di messaggi classiche è
relativamente poco diffuso.
-% TODO: trattare qui, se non ssis trova posto migliore, copy_from_process e
+% TODO: trattare qui, se non si trova posto migliore, copy_from_process e
% copy_to_process, introdotte con il kernel 3.2. Vedi
% http://lwn.net/Articles/405346/ e
% http://ozlabs.org/~cyeoh/cma/process_vm_readv.txt
alternativi.
La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare
-dei \textsl{file di lock} (per i quali esiste anche una opportuna directory,
-\file{/var/lock}, nel filesystem standard). Per questo si usa la
-caratteristica della funzione \func{open} (illustrata in
-sez.~\ref{sec:file_open_close}) che prevede\footnote{questo è quanto dettato dallo
- standard POSIX.1, ciò non toglie che in alcune implementazioni questa
- tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si
- è comunque soggetti alla possibilità di una \itindex{race~condition}
- \textit{race condition}.} che essa ritorni un errore quando usata con i
-flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la creazione di un
-\textsl{file di lock} può essere eseguita atomicamente, il processo che crea
-il file con successo si può considerare come titolare del lock (e della
-risorsa ad esso associata) mentre il rilascio si può eseguire con una chiamata
-ad \func{unlink}.
+dei \textsl{file di lock} (per i quali è stata anche riservata una opportuna
+directory, \file{/var/lock}, nella standardizzazione del \textit{Filesystem
+ Hyerarchy Standard}). Per questo si usa la caratteristica della funzione
+\func{open} (illustrata in sez.~\ref{sec:file_open_close}) che
+prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non
+ toglie che in alcune implementazioni questa tecnica possa non funzionare; in
+ particolare per Linux, nel caso di NFS, si è comunque soggetti alla
+ possibilità di una \itindex{race~condition} \textit{race condition}.} che
+essa ritorni un errore quando usata con i flag di \const{O\_CREAT} e
+\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può
+essere eseguita atomicamente, il processo che crea il file con successo si può
+considerare come titolare del lock (e della risorsa ad esso associata) mentre
+il rilascio si può eseguire con una chiamata ad \func{unlink}.
Un esempio dell'uso di questa funzione è mostrato dalle funzioni
\func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock}
\label{sec:ipc_mmap_anonymous}
\itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono
-\textsl{correlati}\footnote{se cioè hanno almeno un progenitore comune.} l'uso
-delle \textit{pipe} può costituire una valida alternativa alle code di
-messaggi; nella stessa situazione si può evitare l'uso di una memoria
-condivisa facendo ricorso al cosiddetto \textit{memory mapping} anonimo.
+\textsl{correlati}, se cioè hanno almeno un progenitore comune, l'uso delle
+\textit{pipe} può costituire una valida alternativa alle code di messaggi;
+nella stessa situazione si può evitare l'uso di una memoria condivisa facendo
+ricorso al cosiddetto \textit{memory mapping} anonimo.
In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il
contenuto di un file nella memoria di un processo, e che, quando viene usato
il flag \const{MAP\_SHARED}, le modifiche effettuate al contenuto del file
vengono viste da tutti i processi che lo hanno mappato. Utilizzare questa
tecnica per creare una memoria condivisa fra processi diversi è estremamente
-inefficiente, in quanto occorre passare attraverso il disco. Però abbiamo
-visto anche che se si esegue la mappatura con il flag \const{MAP\_ANONYMOUS}
-la regione mappata non viene associata a nessun file, anche se quanto scritto
-rimane in memoria e può essere riletto; allora, dato che un processo figlio
-mantiene nel suo spazio degli indirizzi anche le regioni mappate, esso sarà
-anche in grado di accedere a quanto in esse è contenuto.
+inefficiente, in quanto occorre passare attraverso il disco.
+
+Però abbiamo visto anche che se si esegue la mappatura con il flag
+\const{MAP\_ANONYMOUS} la regione mappata non viene associata a nessun file,
+anche se quanto scritto rimane in memoria e può essere riletto; allora, dato
+che un processo figlio mantiene nel suo spazio degli indirizzi anche le
+regioni mappate, esso sarà anche in grado di accedere a quanto in esse è
+contenuto.
In questo modo diventa possibile creare una memoria condivisa fra processi
diversi, purché questi abbiano almeno un progenitore comune che ha effettuato
lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
possono avere o meno una corrispondenza sul filesystem; tutto quello che è
richiesto è che:
-\begin{itemize*}
+\begin{itemize}
\item i nomi devono essere conformi alle regole che caratterizzano i
\textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX}
byte e terminati da un carattere nullo.
nome dipende dall'implementazione.
\item l'interpretazione di ulteriori \texttt{/} presenti nel nome dipende
dall'implementazione.
-\end{itemize*}
+\end{itemize}
Data la assoluta genericità delle specifiche, il comportamento delle funzioni
-è subordinato in maniera quasi completa alla relativa
-implementazione.\footnote{tanto che Stevens in \cite{UNP2} cita questo caso
- come un esempio della maniera standard usata dallo standard POSIX per
- consentire implementazioni non standardizzabili.} Nel caso di Linux, sia per
-quanto riguarda la memoria condivisa ed i semafori, che per quanto riguarda le
-code di messaggi, tutto viene creato usando come radici delle opportune
-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
-eventuali sottodirectory) rispetto a queste radici.
+è subordinato in maniera quasi completa alla relativa implementazione, tanto
+che Stevens in \cite{UNP2} cita questo caso come un esempio della maniera
+standard usata dallo standard POSIX per consentire implementazioni non
+standardizzabili.
+
+Nel caso di Linux, sia per quanto riguarda la memoria condivisa ed i semafori,
+che per quanto riguarda le code di messaggi, tutto viene creato usando come
+radici delle opportune 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 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, 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.
+comandi di accesso ai file, che funzionano come su dei file normali; questo
+però è vero nel caso di Linux, che usa una implementazione che lo consente,
+non è detto che altrettanto valga per 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.
In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai
permessi dei file, ed il controllo di accesso segue esattamente la stessa
corrispondenza all'inclusione del supporto nel kernel ufficiale anche
\file{libmqueue} è stata inserita nella \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.}
+POSIX (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
aggiungendo ad \conffile{/etc/fstab} una riga come:
-\begin{verbatim}
+\begin{Example}
mqueue /dev/mqueue mqueue defaults 0 0
-\end{verbatim}
+\end{Example}
ed esso sarà utilizzato come radice sulla quale vengono risolti i nomi delle
code di messaggi che iniziano con una ``\texttt{/}''. Le opzioni di mount
accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono
La funzione che permette di aprire (e crearla se non esiste ancora) una coda
di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è:
-\begin{functions}
- \headdecl{mqueue.h}
-
- \funcdecl{mqd\_t mq\_open(const char *name, int oflag)}
-
- \funcdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode,
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{mqd\_t mq\_open(const char *name, int oflag)}
+\fdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode,
struct mq\_attr *attr)}
-
- Apre una coda di messaggi POSIX impostandone le caratteristiche.
-
- \bodydesc{La funzione restituisce il descrittore associato alla coda in caso
- di successo e -1 per un errore; nel quel caso \var{errno} assumerà i
- valori:
- \begin{errlist}
+
+\fdesc{Apre una coda di messaggi POSIX impostandone le caratteristiche.}
+}
+
+{La funzione ritorna il descrittore associato alla coda in caso di successo e
+ $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\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
valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}.
\item[\errcode{ENOENT}] non si è specificato \const{O\_CREAT} ma la coda
non esiste.
- \end{errlist}
- ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
- \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE}.
-}
-\end{functions}
+ \end{errlist}
+ ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
+ \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE} nel loro significato
+ generico.
+}
+\end{funcproto}
La funzione apre la coda di messaggi identificata dall'argomento \param{name}
restituendo il descrittore ad essa associato, del tutto analogo ad un file
descriptor, con l'unica differenza che lo standard prevede un apposito tipo
-\type{mqd\_t}.\footnote{nel caso di Linux si tratta in effetti proprio di un
- normale file descriptor; pertanto, anche se questo comportamento non è
- portabile, lo si può tenere sotto osservazione con le funzioni dell'I/O
- multiplexing (vedi sez.~\ref{sec:file_multiplexing}) come possibile
- alternativa all'uso dell'interfaccia di notifica di \func{mq\_notify} (che
- vedremo a breve).} Se la coda esiste già il descrittore farà riferimento
-allo stesso oggetto, consentendo così la comunicazione fra due processi
-diversi.
+\type{mqd\_t}. Nel caso di Linux si tratta in effetti proprio di un normale
+file descriptor; pertanto, anche se questo comportamento non è portabile, lo
+si può tenere sotto osservazione con le funzioni dell'I/O multiplexing (vedi
+sez.~\ref{sec:file_multiplexing}) come possibile alternativa all'uso
+dell'interfaccia di notifica di \func{mq\_notify} (che vedremo a breve). Se la
+coda esiste già il descrittore farà riferimento allo stesso oggetto,
+consentendo così la comunicazione fra due processi diversi.
La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
possono essere specificati per \param{oflag}, che deve essere specificato come
\begin{figure}[!htb]
\footnotesize \centering
- \begin{minipage}[c]{\textwidth}
+ \begin{minipage}[c]{0.90\textwidth}
\includestruct{listati/mq_attr.h}
\end{minipage}
\normalsize
Quando l'accesso alla coda non è più necessario si può chiudere il relativo
descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
-\begin{prototype}{mqueue.h}
-{int mq\_close(mqd\_t mqdes)}
-Chiude la coda \param{mqdes}.
-
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore;
- nel quel caso \var{errno} assumerà i valori \errval{EBADF} o
- \errval{EINTR}.}
-\end{prototype}
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_close(mqd\_t mqdes)}
+
+\fdesc{Chiude una coda di messaggi.}
+}
-La funzione è analoga a \func{close},\footnote{in Linux, dove le code sono
- implementate come file su un filesystem dedicato, è esattamente la stessa
- funzione.} dopo la sua esecuzione il processo non sarà più in grado di usare
-il descrittore della coda, ma quest'ultima continuerà ad esistere nel sistema
-e potrà essere acceduta con un'altra chiamata a \func{mq\_open}. All'uscita di
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori \errval{EBADF} o \errval{EINTR} nel
+ loro significato generico.
+}
+\end{funcproto}
+
+La funzione è analoga a \func{close} (e in Linux, dove le code sono
+implementate come file su un filesystem dedicato, è esattamente la stessa
+funzione) dopo la sua esecuzione il processo non sarà più in grado di usare il
+descrittore della coda, ma quest'ultima continuerà ad esistere nel sistema e
+potrà essere acceduta con un'altra chiamata a \func{mq\_open}. All'uscita di
un processo tutte le code aperte, così come i file, vengono chiuse
automaticamente. Inoltre se il processo aveva agganciato una richiesta di
notifica sul descrittore che viene chiuso, questa sarà rilasciata e potrà
essere richiesta da qualche altro processo.
-
Quando si vuole effettivamente rimuovere una coda dal sistema occorre usare la
funzione \funcd{mq\_unlink}, il cui prototipo è:
-\begin{prototype}{mqueue.h}
-{int mq\_unlink(const char *name)}
-Rimuove una coda di messaggi.
-
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore; nel quel caso \var{errno} assumerà gli stessi valori riportati da
- \func{unlink}.}
-\end{prototype}
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_unlink(const char *name)}
+
+\fdesc{Rimuove una coda di messaggi.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà gli stessi valori riportati da \func{unlink}.
+}
+\end{funcproto}
Anche in questo caso il comportamento della funzione è analogo a quello di
-\func{unlink} per i file,\footnote{di nuovo l'implementazione di Linux usa
- direttamente \func{unlink}.} la funzione rimuove la coda \param{name}, così
-che una successiva chiamata a \func{mq\_open} fallisce o crea una coda
-diversa.
+\func{unlink} per i file, (e di nuovo l'implementazione di Linux usa
+direttamente \func{unlink}) la funzione rimuove la coda \param{name}, così che
+una successiva chiamata a \func{mq\_open} fallisce o crea una coda diversa.
Come per i file ogni coda di messaggi ha un contatore di riferimenti, per cui
la coda non viene effettivamente rimossa dal sistema fin quando questo non si
Come accennato ad ogni coda di messaggi è associata una struttura
\struct{mq\_attr}, che può essere letta e modificata attraverso le due
funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono:
-\begin{functions}
- \headdecl{mqueue.h}
-
- \funcdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)}
- Legge gli attributi di una coda di messaggi POSIX.
-
- \funcdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat,
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)}
+\fdesc{Legge gli attributi di una coda di messaggi POSIX.}
+\fdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat,
struct mq\_attr *omqstat)}
- Modifica gli attributi di una coda di messaggi POSIX.
-
- \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in
- caso di errore; nel quel caso \var{errno} assumerà i valori \errval{EBADF}
- o \errval{EINVAL}.}
-\end{functions}
+\fdesc{Modifica gli attributi di una coda di messaggi POSIX.}
+}
+
+{Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ per un errore,
+ nel qual caso \var{errno} assumerà i valori \errval{EBADF}
+ o \errval{EINVAL} nel loro significato generico.
+}
+\end{funcproto}
La funzione \func{mq\_getattr} legge i valori correnti degli attributi della
coda nella struttura puntata da \param{mqstat}; di questi l'unico relativo
Per inserire messaggi su di una coda sono previste due funzioni,
\funcd{mq\_send} e \funcd{mq\_timedsend}, i cui prototipi sono:
-\begin{functions}
- \headdecl{mqueue.h}
-
- \funcdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len,
- unsigned int msg\_prio)}
- Esegue l'inserimento di un messaggio su una coda.
-
- \funcdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
- msg\_len, unsigned msg\_prio, const struct timespec *abs\_timeout)}
- Esegue l'inserimento di un messaggio su una coda entro il tempo
- \param{abs\_timeout}.
-
- \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ per un
- errore; nel quel caso \var{errno} assumerà i valori:
- \begin{errlist}
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len,
+ unsigned int msg\_prio)}
+\fdesc{Esegue l'inserimento di un messaggio su una coda.}
+\fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
+ msg\_len, unsigned msg\_prio, const struct timespec *abs\_timeout)}
+\fdesc{Esegue l'inserimento di un messaggio su una coda entro un tempo
+ specificato}
+}
+
+{Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ per un errore,
+ nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\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}
un valore non valido per \param{abs\_timeout}.
\item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato
effettuato entro il tempo stabilito.
- \end{errlist}
- ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR}.}
-\end{functions}
+ \end{errlist}
+ ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR} nel loro
+ significato generico.
+}
+\end{funcproto}
Entrambe le funzioni richiedono un puntatore al testo del messaggio
nell'argomento \param{msg\_ptr} e la relativa lunghezza in \param{msg\_len}.
\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 della
-\acr{glibc} che usano questa nuova infrastruttura per quella che viene quella
-che viene chiamata \textit{New Posix Thread Library}, sono state implementate
+\acr{glibc} che usano questa nuova infrastruttura per quella che viene 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
% LocalWords: FortuneServer FortuneParse FortuneClient pid libgapil LD librt
% LocalWords: PATH linker pathname ps tmp killall fortuned crash socket domain
% LocalWords: socketpair BSD sys protocol sv EAFNOSUPPORT EPROTONOSUPPORT AF
-% LocalWords: EOPNOTSUPP SOCK Process Comunication ipc perm key exec
+% LocalWords: EOPNOTSUPP SOCK Process Comunication ipc perm key exec pipefd SZ
% LocalWords: header ftok proj stat libc SunOS glibc XPG dell'inode number uid
% LocalWords: cuid cgid gid tab MSG shift group umask seq MSGMNI SEMMNI SHMMNI
% LocalWords: shmmni msgmni sem sysctl IPCMNI IPCTestId msgget EACCES EEXIST
% LocalWords: dtime lpid cpid nattac shmall shmmax SHMLBA SHMSEG EOVERFLOW brk
% LocalWords: memory shmat shmdt void shmaddr shmflg SVID RND RDONLY rounded
% LocalWords: SIGSEGV nattch exit SharedMem ShmCreate memset fill ShmFind home
-% LocalWords: ShmRemove DirMonitor DirProp chdir GaPiL shmptr ipcs NFS
+% LocalWords: ShmRemove DirMonitor DirProp chdir GaPiL shmptr ipcs NFS SETPIPE
% LocalWords: ComputeValues ReadMonitor touch SIGTERM dirmonitor unlink fcntl
% LocalWords: LockFile UnlockFile CreateMutex FindMutex LockMutex SETLKW GETLK
% LocalWords: UnlockMutex RemoveMutex ReadMutex UNLCK WRLCK RDLCK mapping MAP
% 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 libmqueue FAILED has
+% LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED has fclose
% LocalWords: ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait
% LocalWords: process getvalue sval execve pshared ENOSYS heap PAGE destroy it
% LocalWords: xffffffff Arrays owner perms Queues used bytes messages device
% LocalWords: Cannot find such Segments getter Signal MSGMAXSIZE been stable
% LocalWords: for now it's break Berlin sources Let's an accidental feature
% LocalWords: Larry Wall Escape the Hell William ipctestid Identifier segment
-% LocalWords: violation dell'I SIGINT setter Fri Dec Sleeping seconds
+% LocalWords: violation dell'I SIGINT setter Fri Dec Sleeping seconds ECHILD
+% LocalWords: SysV capability short RESOURCE INFO UNDEFINED EFBIG semtimedop
+% LocalWords: scan
%%% Local Variables: