%% ipc.tex
%%
-%% Copyright (C) 2000-2015 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2016 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato
intermedio su un file temporaneo. Questo però non tiene conto del fatto che un
\textit{CGI} può essere eseguito più volte in contemporanea, e si avrebbe una
-evidente \itindex{race~condition} \textit{race condition} in caso di accesso
-simultaneo a detto file da istanze diverse. Il problema potrebbe essere
-superato utilizzando un sempre diverso per il file temporaneo, che verrebbe
-creato all'avvio di ogni istanza, utilizzato dai sottoprocessi, e cancellato
-alla fine della sua esecuzione; ma a questo punto le cose non sarebbero più
-tanto semplici. L'uso di una \textit{pipe} invece permette di risolvere il
-problema in maniera semplice ed elegante, oltre ad essere molto più
-efficiente, dato che non si deve scrivere su disco.
+evidente \textit{race condition} in caso di accesso simultaneo a detto file da
+istanze diverse. Il problema potrebbe essere superato utilizzando un sempre
+diverso per il file temporaneo, che verrebbe creato all'avvio di ogni istanza,
+utilizzato dai sottoprocessi, e cancellato alla fine della sua esecuzione; ma
+a questo punto le cose non sarebbero più tanto semplici. L'uso di una
+\textit{pipe} invece permette di risolvere il problema in maniera semplice ed
+elegante, oltre ad essere molto più efficiente, dato che non si deve scrivere
+su disco.
Il programma ci servirà anche come esempio dell'uso delle funzioni di
duplicazione dei file descriptor che abbiamo trattato in
Utilizzando una \textit{fifo} tutti i dati passeranno, come per le
\textit{pipe}, attraverso un buffer nel kernel, senza transitare dal
-filesystem. Il fatto che siano associate ad un \itindex{inode}
-\textit{inode} presente sul filesystem serve infatti solo a fornire un punto
-di accesso per i processi, che permetta a questi ultimi di accedere alla
-stessa \textit{fifo} senza avere nessuna relazione, con una semplice
-\func{open}. Il comportamento delle funzioni di lettura e scrittura è identico
-a quello illustrato per le \textit{pipe} in sez.~\ref{sec:ipc_pipes}.
+filesystem. Il fatto che siano associate ad un \textit{inode} presente sul
+filesystem serve infatti solo a fornire un punto di accesso per i processi,
+che permetta a questi ultimi di accedere alla stessa \textit{fifo} senza avere
+nessuna relazione, con una semplice \func{open}. Il comportamento delle
+funzioni di lettura e scrittura è identico a quello illustrato per le
+\textit{pipe} in sez.~\ref{sec:ipc_pipes}.
Abbiamo già trattato in sez.~\ref{sec:file_mknod} le funzioni \func{mknod} e
\func{mkfifo} che permettono di creare una \textit{fifo}. Per utilizzarne una
lettura. Infine è possibile anche usare la \textit{fifo} all'interno di un
solo processo, nel qual caso però occorre stare molto attenti alla possibili
situazioni di stallo: se si cerca di leggere da una \textit{fifo} che non
-contiene dati si avrà infatti un \itindex{deadlock} \textit{deadlock}
-immediato, dato che il processo si blocca e quindi non potrà mai eseguire le
-funzioni di scrittura.
+contiene dati si avrà infatti un \textit{deadlock} immediato, dato che il
+processo si blocca e quindi non potrà mai eseguire le funzioni di scrittura.
Per la loro caratteristica di essere accessibili attraverso il filesystem, è
piuttosto frequente l'utilizzo di una \textit{fifo} come canale di
Verifichiamo allora il comportamento dei nostri programmi, in questo, come in
altri esempi precedenti, si fa uso delle varie funzioni di servizio, che sono
-state raccolte nella libreria \file{libgapil.so}, per poter usare quest'ultima
+state raccolte nella libreria \file{libgapil.so}, e per poterla usare
occorrerà definire la variabile di ambiente \envvar{LD\_LIBRARY\_PATH} in modo
che il linker dinamico possa accedervi.
possono essere specificati sono rispettivamente \const{AF\_UNIX},
\const{SOCK\_STREAM} e \val{0}.
-A partire dal kernel 2.6.27 la funzione supporta anche l'uso dei flag
-\const{SOCK\_NONBLOCK} e \const{SOCK\_CLOEXEC} (trattati in
-sez.~\ref{sec:sock_type}) nell'indicazione del tipo di socket, con effetto
-identico agli analoghi \const{O\_CLOEXEC} e \const{O\_NONBLOCK} di una
-\func{open} (vedi tab.~\ref{tab:open_operation_flag}).
+A partire dal kernel 2.6.27 la funzione supporta nell'indicazione del tipo di
+socket anche i due flag \const{SOCK\_NONBLOCK} e \const{SOCK\_CLOEXEC}
+(trattati in sez.~\ref{sec:sock_type}), con effetto identico agli analoghi
+\const{O\_CLOEXEC} e \const{O\_NONBLOCK} di una \func{open} (vedi
+tab.~\ref{tab:open_operation_flag}).
L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe}
può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei socket
\end{minipage}
\normalsize
\caption{La struttura \structd{ipc\_perm}, come definita in
- \headfile{sys/ipc.h}.}
+ \headfiled{sys/ipc.h}.}
\label{fig:ipc_ipc_perm}
\end{figure}
associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è
come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
sono \textsl{imparentati} la soluzione è relativamente semplice, in tal caso
-infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un
+infatti si può usare il valore speciale \constd{IPC\_PRIVATE} per creare un
nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà
disponibile in tutti i figli, e potrà essere passato come argomento attraverso
una \func{exec}.
Il problema è che anche così non c'è la sicurezza che il valore della chiave
sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
-con i 16 bit meno significativi \itindex{inode} dell'inode del file
-\param{pathname} (che vengono ottenuti attraverso \func{stat}, da cui derivano
-i possibili errori), e gli 8 bit meno significativi del numero del dispositivo
-su cui è il file. Diventa perciò relativamente facile ottenere delle
-collisioni, specie se i file sono su dispositivi con lo stesso
-\itindex{minor~number} \textit{minor number}, come \file{/dev/hda1} e
-\file{/dev/sda1}.
+con i 16 bit meno significativi dell'inode del file \param{pathname} (che
+vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori),
+e gli 8 bit meno significativi del numero del dispositivo su cui è il file.
+Diventa perciò relativamente facile ottenere delle collisioni, specie se i
+file sono su dispositivi con lo stesso \textit{minor number}, come
+\file{/dev/hda1} e \file{/dev/sda1}.
In genere quello che si fa è utilizzare un file comune usato dai programmi che
devono comunicare (ad esempio un header comune, o uno dei programmi che devono
Se però si vogliono usare le costanti simboliche di
tab.~\ref{tab:file_mode_flags} occorrerà includere anche il file
-\headfile{sys/stat.h}; alcuni sistemi definiscono le costanti \const{MSG\_R}
-(il valore ottale \texttt{0400}) e \const{MSG\_W} (il valore ottale
+\headfile{sys/stat.h}; alcuni sistemi definiscono le costanti \constd{MSG\_R}
+(il valore ottale \texttt{0400}) e \constd{MSG\_W} (il valore ottale
\texttt{0200}) per indicare i permessi base di lettura e scrittura per il
proprietario, da utilizzare, con gli opportuni shift, pure per il gruppo e gli
altri. In Linux, visto la loro scarsa utilità, queste costanti non sono
a differenza di quanto avviene per i permessi dei file, fallire in uno dei
passi elencati non comporta il fallimento dell'accesso. Un'ulteriore
differenza rispetto a quanto avviene per i file è che per gli oggetti di IPC
-il valore di \itindex{umask} \textit{umask} (si ricordi quanto esposto in
+il valore di \textit{umask} (si ricordi quanto esposto in
sez.~\ref{sec:file_perm_management}) non ha alcun significato.
relativi al \textit{SysV-IPC}) solo con una ricompilazione del kernel. A
partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo
scrivendo sui file \sysctlrelfile{kernel}{shmmni},
-\sysctlrelfile{kernel}{msgmni} e \sysctlrelfile{kernel}{sem} di
+\sysctlrelfile{kernel}{msgmni} e \sysctlrelfiled{kernel}{sem} di
\file{/proc/sys/kernel} o con l'uso di \func{sysctl}.
\begin{figure}[!htb]
Questo in realtà è quanto avveniva fino ai kernel della serie 2.2, dalla serie
2.4 viene usato lo stesso fattore di moltiplicazione per qualunque tipo di
-oggetto, utilizzando il valore dalla costante \const{IPCMNI} (definita in
+oggetto, utilizzando il valore dalla costante \constd{IPCMNI} (definita in
\file{include/linux/ipc.h}), che indica il limite massimo complessivo per il
numero di tutti gli oggetti presenti nel \textit{SysV-IPC}, ed il cui default
è 32768. Si evita così il riutilizzo degli stessi numeri, e si fa sì che
Se invece si vuole creare una nuova coda di messaggi \param{flag} non può
essere nullo e deve essere fornito come maschera binaria, impostando il bit
-corrispondente al valore \const{IPC\_CREAT}. In questo caso i nove bit meno
+corrispondente al valore \constd{IPC\_CREAT}. In questo caso i nove bit meno
significativi di \param{flag} saranno usati come permessi per il nuovo
oggetto, secondo quanto illustrato in sez.~\ref{sec:ipc_sysv_access_control}.
-Se si imposta anche il bit corrispondente a \const{IPC\_EXCL} la funzione avrà
+Se si imposta anche il bit corrispondente a \constd{IPC\_EXCL} la funzione avrà
successo solo se l'oggetto non esiste già, fallendo con un errore di
\errcode{EEXIST} altrimenti.
& \textbf{Significato} \\
\hline
\hline
- \const{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di
+ \constd{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di
messaggi.\\
- \const{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
+ \constd{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
messaggio.\\
- \const{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di
+ \constd{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di
una coda.\\
\hline
\end{tabular}
definiti staticamente e corrispondenti alle prime tre costanti riportate in
tab.~\ref{tab:ipc_msg_limits}. Come accennato però con tutte le versioni più
recenti del kernel con Linux è possibile modificare questi limiti attraverso
-l'uso di \func{sysctl} o scrivendo nei file \sysctlrelfile{kernel}{msgmax},
-\sysctlrelfile{kernel}{msgmnb} e \sysctlrelfile{kernel}{msgmni} di
+l'uso di \func{sysctl} o scrivendo nei file \sysctlrelfiled{kernel}{msgmax},
+\sysctlrelfiled{kernel}{msgmnb} e \sysctlrelfiled{kernel}{msgmni} di
\file{/proc/sys/kernel/}.
-Una coda di messaggi è costituita da una \itindex{linked~list} \textit{linked
- list}.\footnote{una \itindex{linked~list} \textit{linked list} è una tipica
- struttura di dati, organizzati in una lista in cui ciascun elemento contiene
- un puntatore al successivo. In questo modo la struttura è veloce
- nell'estrazione ed immissione dei dati dalle estremità dalla lista (basta
- aggiungere un elemento in testa o in coda ed aggiornare un puntatore), e
- relativamente veloce da attraversare in ordine sequenziale (seguendo i
- 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. 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 (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.
+\itindbeg{linked~list}
+
+Una coda di messaggi è costituita da una \textit{linked list}.\footnote{una
+ \textit{linked list} è una tipica struttura di dati, organizzati in una
+ lista in cui ciascun elemento contiene un puntatore al successivo. In questo
+ modo la struttura è veloce nell'estrazione ed immissione dei dati dalle
+ estremità dalla lista (basta aggiungere un elemento in testa o in coda ed
+ aggiornare un puntatore), e relativamente veloce da attraversare in ordine
+ sequenziale (seguendo i 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. 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 (e non esiste una
+struttura \kstruct{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.
+
+\itindend{linked~list}
\begin{figure}[!htb]
\centering \includegraphics[width=13cm]{img/mqstruct}
- \caption{Schema della struttura di una coda messaggi.}
+ \caption{Schema delle strutture di una coda di messaggi
+ (\kstructd{msqid\_ds} e \kstructd{msg}).}
\label{fig:ipc_mq_schema}
\end{figure}
-A ciascuna coda è associata una struttura \struct{msqid\_ds} la cui
+A ciascuna coda è associata una struttura \kstruct{msqid\_ds} la cui
definizione è riportata in fig.~\ref{fig:ipc_msqid_ds} ed a cui si accede
-includendo \headfile{sys/msg.h};
+includendo \headfiled{sys/msg.h};
%
% INFO: sotto materiale obsoleto e non interessante
% In questa struttura il
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
+\item[\constd{IPC\_STAT}] Legge le informazioni riguardo la coda nella
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
+\item[\constd{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
funzioni di lettura o di scrittura sulla coda saranno svegliati ricevendo
il medesimo errore. Questo comando può essere eseguito solo da un processo
con \ids{UID} effettivo corrispondente al creatore o al proprietario della
coda, o all'amministratore.
-\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+\item[\constd{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
\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{ipcs} per ottenere le
+affiancano altri tre (\constd{IPC\_INFO}, \constd{MSG\_STAT} e
+\constd{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.
cioè \var{message} è una propria struttura che si passa alla funzione,
\param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se
consideriamo il caso dell'esempio in fig.~\ref{fig:ipc_msbuf}, \param{msgsz}
-dovrà essere pari a \const{LENGTH}).
+dovrà essere pari a \var{LENGTH}).
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
-sarà aggiunto in fondo alla lista inserendo una nuova struttura \struct{msg},
-il puntatore \var{msg\_last} di \struct{msqid\_ds} verrà aggiornato, come pure
-il puntatore al messaggio successivo per quello che era il precedente ultimo
-messaggio; il valore di \var{mtype} verrà mantenuto in \var{msg\_type} ed il
-valore di \param{msgsz} in \var{msg\_ts}; il testo del messaggio sarà copiato
-all'indirizzo specificato da \var{msg\_spot}.
+fig.~\ref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo
+messaggio sarà aggiunto in fondo alla lista inserendo una nuova struttura
+\kstruct{msg}, il puntatore \var{msg\_last} di \kstruct{msqid\_ds} verrà
+aggiornato, come pure il puntatore al messaggio successivo per quello che era
+il precedente ultimo messaggio; il valore di \var{mtype} verrà mantenuto in
+\var{msg\_type} ed il valore di \param{msgsz} in \var{msg\_ts}; il testo del
+messaggio sarà copiato all'indirizzo specificato da \var{msg\_spot}.
Il valore dell'argomento \param{flag} permette di specificare il comportamento
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. Se si specifica per \param{flag} il valore
-\const{IPC\_NOWAIT} la funzione opera in modalità non-bloccante, ed in questi
+\constd{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
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}).
+\var{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
-\const{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene
+\constd{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene
perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con
un errore di \errcode{E2BIG}.
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ù
valori. Oltre al precedente \const{MSG\_NOERROR}, sono possibili altri due
-valori: \const{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo,
+valori: \constd{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo,
di leggere il primo messaggio nella coda con tipo diverso da \param{msgtyp}, e
\const{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non
ci sono messaggi sulla coda.
funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di
una di queste strutture alla volta; ad esempio non si può scrivere un server
che aspetti un messaggio su più di una coda senza fare ricorso ad una tecnica
-di \itindex{polling} \textit{polling} che esegua un ciclo di attesa su
-ciascuna di esse.
+di \textit{polling} che esegua un ciclo di attesa su ciascuna di esse.
Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro
server di \textit{fortunes} usando queste al posto delle \textit{fifo}. In
\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} \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.
+\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{I semafori}
\textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \const{SEMMNI}& 128 & Numero massimo di insiemi di semafori.\\
- \const{SEMMSL}& 250 & Numero massimo di semafori per insieme.\\
- \const{SEMMNS}&\const{SEMMNI}*\const{SEMMSL}& Numero massimo di semafori
- nel sistema.\\
- \const{SEMVMX}& 32767 & Massimo valore per un semaforo.\\
- \const{SEMOPM}& 32 & Massimo numero di operazioni per chiamata a
- \func{semop}. \\
- \const{SEMMNU}&\const{SEMMNS}& Massimo numero di strutture di ripristino.\\
- \const{SEMUME}&\const{SEMOPM}& Massimo numero di voci di ripristino.\\
- \const{SEMAEM}&\const{SEMVMX}& Valore massimo per l'aggiustamento
- all'uscita. \\
+ \constd{SEMMNI}& 128 & Numero massimo di insiemi di semafori.\\
+ \constd{SEMMSL}& 250 & Numero massimo di semafori per insieme.\\
+ \constd{SEMMNS}&\const{SEMMNI}*\const{SEMMSL}& Numero massimo di semafori
+ nel sistema.\\
+ \constd{SEMVMX}& 32767 & Massimo valore per un semaforo.\\
+ \constd{SEMOPM}& 32 & Massimo numero di operazioni per chiamata a
+ \func{semop}. \\
+ \constd{SEMMNU}&\const{SEMMNS}& Massimo numero di strutture di ripristino.\\
+ \constd{SEMUME}&\const{SEMOPM}& Massimo numero di voci di ripristino.\\
+ \constd{SEMAEM}&\const{SEMVMX}& Valore massimo per l'aggiustamento
+ all'uscita. \\
\hline
\end{tabular}
\caption{Valori delle costanti associate ai limiti degli insiemi di
\includestruct{listati/semun.h}
\end{minipage}
\normalsize
- \caption{La definizione dei possibili valori di una \direct{union}
+ \caption{La definizione dei possibili valori di una \dirct{union}
\structd{semun}, usata come quarto argomento della funzione
\func{semctl}.}
\label{fig:ipc_semun}
\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
+macro \macrod{\_SEM\_SEMUN\_UNDEFINED} che può essere usata per controllare la
situazione.
Come già accennato sia il comportamento della funzione che il numero di
\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
+\item[\constd{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.
L'argomento \param{semnum} viene ignorato.
-\item[\const{GETNCNT}] Restituisce come valore di ritorno della funzione il
+\item[\constd{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
lettura.
-\item[\const{GETPID}] Restituisce come valore di ritorno della funzione il
+\item[\constd{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
il permesso di lettura.
-\item[\const{GETVAL}] Restituisce come valore di ritorno della funzione il il
+\item[\constd{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
argomenti. Occorre avere il permesso di lettura.
-\item[\const{GETZCNT}] Restituisce come valore di ritorno della funzione il
+\item[\constd{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.
-\item[\const{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
+\item[\constd{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. L'argomento \param{semnum} viene ignorato.
-\item[\const{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato
+\item[\constd{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.
\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
+\constd{SEM\_STAT} e \constd{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.
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 in tutti quei
+\constd{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
\begin{figure}[!htb]
\centering \includegraphics[width=12cm]{img/semtruct}
- \caption{Schema della struttura di un insieme di semafori.}
+ \caption{Schema delle varie strutture di un insieme di semafori
+ (\kstructd{semid\_ds}, \kstructd{sem}, \kstructd{sem\_queue} e
+ \kstructd{sem\_undo}).}
\label{fig:ipc_sem_schema}
\end{figure}
Alla creazione di un nuovo insieme viene allocata una nuova strutture
-\struct{semid\_ds} ed il relativo vettore di strutture \struct{sem}. Quando si
-richiede una operazione viene anzitutto verificato che tutte le operazioni
+\kstruct{semid\_ds} ed il relativo vettore di strutture \kstruct{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, 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
+\kstruct{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
sblocco non servirebbe comunque, dato che l'operazione non sarebbe atomica.
Vedremo in sez.~\ref{sec:ipc_lock_file} come sia possibile ottenere
un'interfaccia analoga a quella appena illustrata, senza incorrere in questi
-problemi, usando il \itindex{file~locking} \textit{file locking}.
+problemi, usando il \textit{file locking}.
\subsection{Memoria condivisa}
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
+Il primo dei due flag è \constd{SHM\_HUGETLB} che consente di richiedere la
creazione del segmento usando una \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 è
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}
+\constd{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}.
+delle pagine di swap ad uso del meccanismo del \textit{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}.
Infine l'argomento \param{size} specifica la dimensione del segmento di
memoria condivisa; il valore deve essere specificato in byte, ma verrà
& \textbf{Significato} \\
\hline
\hline
- \const{SHMALL}& 0x200000&\sysctlrelfile{kernel}{shmall}
- & Numero massimo di pagine che
- possono essere usate per i segmenti di
- memoria condivisa.\\
- \const{SHMMAX}&0x2000000&\sysctlrelfile{kernel}{shmmax}
- & Dimensione massima di un segmento di memoria
- condivisa.\\
- \const{SHMMNI}& 4096&\sysctlrelfile{kernel}{msgmni}
- & Numero massimo di segmenti di memoria condivisa
+ \constd{SHMALL}& 0x200000&\sysctlrelfiled{kernel}{shmall}
+ & Numero massimo di pagine che
+ possono essere usate per i segmenti di
+ memoria condivisa.\\
+ \constd{SHMMAX}&0x2000000&\sysctlrelfiled{kernel}{shmmax}
+ & Dimensione massima di un segmento di memoria
+ condivisa.\\
+ \constd{SHMMNI}& 4096&\sysctlrelfiled{kernel}{shmmni}
+ & Numero massimo di segmenti di memoria condivisa
presenti nel kernel.\\
- \const{SHMMIN}& 1& --- & Dimensione minima di un segmento di
- memoria condivisa.\\
- \const{SHMLBA}&\const{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni
- minime di un segmento (deve essere
- allineato alle dimensioni di una
- pagina di memoria).\\
- \const{SHMSEG}& --- & --- & Numero massimo di segmenti di
- memoria condivisa per ciascun
- processo (l'implementazione non
- prevede l'esistenza di questo
- limite).\\
+ \constd{SHMMIN}& 1& --- & Dimensione minima di un segmento di
+ memoria condivisa.\\
+ \constd{SHMLBA}&\const{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni
+ minime di un segmento (deve essere
+ allineato alle dimensioni di una
+ pagina di memoria).\\
+ \constd{SHMSEG}& --- & --- & Numero massimo di segmenti di
+ memoria condivisa per ciascun
+ processo (l'implementazione non
+ prevede l'esistenza di questo
+ limite).\\
\hline
si ha a cuore la portabilità. Questi comandi aggiuntivi sono:
\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
-\item[\const{SHM\_LOCK}] Abilita il \textit{memory locking} sul segmento di
+\item[\constd{SHM\_LOCK}] Abilita il \textit{memory locking} sul segmento di
memoria condivisa, impedendo che la memoria usata per il segmento venga
salvata su disco dal meccanismo della memoria virtuale. Come illustrato in
sez.~\ref{sec:proc_mem_lock} fino al kernel 2.6.9 solo l'amministratore
2.6.10 anche gli utenti normali possono farlo fino al limite massimo
determinato da \const{RLIMIT\_MEMLOCK} (vedi
sez.~\ref{sec:sys_resource_limit}).
-\item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento
+\item[\constd{SHM\_UNLOCK}] Disabilita il \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}
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},
+ulteriori valori, \const{IPC\_INFO}, \constd{SHM\_STAT} e \constd{SHM\_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},
\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
+Specificando \constd{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.
-L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola
+L'uso di \constd{SHM\_RDONLY} permette di agganciare il segmento in sola
lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
caso un tentativo di scrivere sul segmento comporterà una violazione di
accesso con l'emissione di un segnale di \signal{SIGSEGV}. Il comportamento
\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in
sola scrittura.
-Infine \const{SHM\_REMAP} è una estensione specifica di Linux (quindi non
+Infine \constd{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.
+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}:
\subsection{I \textsl{file di lock}}
\label{sec:ipc_file_lock}
-\index{file!di lock|(}
+\index{file!di~lock|(}
Come illustrato in sez.~\ref{sec:ipc_sysv_sem} i semafori del \textit{SysV-IPC}
presentano una interfaccia inutilmente complessa e con alcuni difetti
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}.
+ possibilità di una \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}
sincronizzazione: anzitutto in caso di terminazione imprevista del processo,
si lascia allocata la risorsa (il \textsl{file di lock}) e questa deve essere
sempre cancellata esplicitamente. Inoltre il controllo della disponibilità
-può essere eseguito solo con una tecnica di \itindex{polling}
-\textit{polling}, ed è quindi molto inefficiente.
+può essere eseguito solo con una tecnica di \textit{polling}, ed è quindi
+molto inefficiente.
La tecnica dei file di lock ha comunque una sua utilità, e può essere usata
con successo quando l'esigenza è solo quella di segnalare l'occupazione di una
più programmi: qualora si trovi un file di lock il programma che cerca di
accedere alla seriale si limita a segnalare che la risorsa non è disponibile.
-\index{file!di lock|)}
+\index{file!di~lock|)}
\subsection{La sincronizzazione con il \textit{file locking}}
\label{sec:ipc_lock_file}
-Dato che i \index{file!di lock} file di lock presentano gli inconvenienti
-illustrati in precedenza, la tecnica alternativa di sincronizzazione più
-comune è quella di fare ricorso al \itindex{file~locking} \textit{file
- locking} (trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un
-file creato per l'occasione per ottenere un write lock. In questo modo potremo
-usare il lock come un \textit{mutex}: per bloccare la risorsa basterà
-acquisire il lock, per sbloccarla basterà rilasciare il lock. Una richiesta
-fatta con un write lock metterà automaticamente il processo in stato di
-attesa, senza necessità di ricorrere al \itindex{polling} \textit{polling} per
-determinare la disponibilità della risorsa, e al rilascio della stessa da
+Dato che i file di lock presentano gli inconvenienti illustrati in precedenza,
+la tecnica alternativa di sincronizzazione più comune è quella di fare ricorso
+al \textit{file locking} (trattato in sez.~\ref{sec:file_locking}) usando
+\func{fcntl} su un file creato per l'occasione per ottenere un write lock. In
+questo modo potremo usare il lock come un \textit{mutex}: per bloccare la
+risorsa basterà acquisire il lock, per sbloccarla basterà rilasciare il
+lock. Una richiesta fatta con un write lock metterà automaticamente il
+processo in stato di attesa, senza necessità di ricorrere al \textit{polling}
+per determinare la disponibilità della risorsa, e al rilascio della stessa da
parte del processo che la occupava si otterrà il nuovo lock atomicamente.
Questo approccio presenta il notevole vantaggio che alla terminazione di un
\includecodesample{listati/MutexLocking.c}
\end{minipage}
\normalsize
- \caption{Il codice delle funzioni che permettono per la gestione dei
- \textit{mutex} con il \itindex{file~locking} \textit{file locking}.}
+ \caption{Il codice delle funzioni che permettono per la gestione dei
+ \textit{mutex} con il \textit{file locking}.}
\label{fig:ipc_flock_mutex}
\end{figure}
Il codice delle varie funzioni usate per implementare un mutex utilizzando il
-\textit{file locking} \itindex{file~locking} è riportato in
-fig.~\ref{fig:ipc_flock_mutex}; si è mantenuta volutamente una struttura
-analoga alle precedenti funzioni che usano i semafori, anche se le due
-interfacce non possono essere completamente equivalenti, specie per quanto
-riguarda la rimozione del mutex.
+\textit{file locking} è riportato in fig.~\ref{fig:ipc_flock_mutex}; si è
+mantenuta volutamente una struttura analoga alle precedenti funzioni che usano
+i semafori, anche se le due interfacce non possono essere completamente
+equivalenti, specie per quanto riguarda la rimozione del mutex.
La prima funzione (\texttt{\small 1-5}) è \func{CreateMutex}, e serve a
creare il mutex; la funzione è estremamente semplice, e si limita
La seconda funzione (\texttt{\small 6-10}) è \func{FindMutex}, che, come la
precedente, è stata definita per mantenere una analogia con la corrispondente
funzione basata sui semafori. Anch'essa si limita (\texttt{\small 9}) ad
-aprire il file da usare per il \itindex{file~locking} \textit{file locking},
-solo che in questo caso le opzioni di \func{open} sono tali che il file in
-questione deve esistere di già.
+aprire il file da usare per il \textit{file locking}, solo che in questo caso
+le opzioni di \func{open} sono tali che il file in questione deve esistere di
+già.
La terza funzione (\texttt{\small 11-22}) è \func{LockMutex} e serve per
acquisire il mutex. La funzione definisce (\texttt{\small 14}) e inizializza
rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo
caso si inizializza (\texttt{\small 28-31}) la struttura \var{lock} per il
rilascio del lock, che viene effettuato (\texttt{\small 33}) con la opportuna
-chiamata a \func{fcntl}. Avendo usato il \itindex{file~locking} \textit{file
- locking} in semantica POSIX (si riveda quanto detto
-sez.~\ref{sec:file_posix_lock}) solo il processo che ha precedentemente
-eseguito il lock può sbloccare il mutex.
+chiamata a \func{fcntl}. Avendo usato il \textit{file locking} in semantica
+POSIX (si riveda quanto detto sez.~\ref{sec:file_posix_lock}) solo il processo
+che ha precedentemente eseguito il lock può sbloccare il mutex.
La quinta funzione (\texttt{\small 36-39}) è \func{RemoveMutex} e serve a
cancellare il mutex. Anche questa funzione è stata definita per mantenere una
\subsection{Il \textit{memory mapping} anonimo}
\label{sec:ipc_mmap_anonymous}
-\itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono
-\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.
+\itindbeg{memory~mapping}
+
+Abbiamo già visto che quando i processi sono \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
nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica
più avanti, quando realizzeremo una nuova versione del monitor visto in
sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete.
+
\itindend{memory~mapping}
% TODO: fare esempio di mmap anonima
Oggi Linux supporta tutti gli oggetti definito nello standard POSIX per l'IPC,
ma a lungo non è stato così; la memoria condivisa è presente a partire dal
kernel 2.4.x, i semafori sono forniti dalla \acr{glibc} nella sezione che
-implementa i \itindex{thread} \textit{thread} POSIX di nuova generazione che
-richiedono il kernel 2.6, le code di messaggi sono supportate a partire dal
-kernel 2.6.6.
+implementa i \textit{thread} POSIX di nuova generazione che richiedono il
+kernel 2.6, le code di messaggi sono supportate a partire dal kernel 2.6.6.
La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
degli identificatori e delle chiavi visti nel \textit{SysV-IPC}, per passare ai
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}. Nel caso di Linux si tratta in effetti proprio di un normale
+\typed{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
\texttt{/proc/sys/fs/mqueue}, in particolare i file che controllano i valori
dei limiti sono:
\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
-\item[\sysctlfile{fs/mqueue/msg\_max}] Indica il valore massimo del numero di
+\item[\sysctlfiled{fs/mqueue/msg\_max}] Indica il valore massimo del numero di
messaggi in una coda e agisce come limite superiore per il valore di
\var{attr->mq\_maxmsg} in \func{mq\_open}. Il suo valore di default è 10. Il
- valore massimo è \const{HARD\_MAX} che vale \code{(131072/sizeof(void *))},
+ valore massimo è \constd{HARD\_MAX} che vale \code{(131072/sizeof(void *))},
ed il valore minimo 1 (ma era 10 per i kernel precedenti il 2.6.28). Questo
limite viene ignorato per i processi con privilegi amministrativi (più
precisamente con la \textit{capability} \const{CAP\_SYS\_RESOURCE}) ma
\const{HARD\_MAX} resta comunque non superabile.
-\item[\sysctlfile{fs/mqueue/msgsize\_max}] Indica il valore massimo della
+\item[\sysctlfiled{fs/mqueue/msgsize\_max}] Indica il valore massimo della
dimensione in byte di un messaggio sulla coda ed agisce come limite
superiore per il valore di \var{attr->mq\_msgsize} in \func{mq\_open}. Il
suo valore di default è 8192. Il valore massimo è 1048576 ed il valore
processi con privilegi amministrativi (con la \textit{capability}
\const{CAP\_SYS\_RESOURCE}).
-\item[\sysctlfile{fs/mqueue/queues\_max}] Indica il numero massimo di code di
+\item[\sysctlfiled{fs/mqueue/queues\_max}] Indica il numero massimo di code di
messaggi creabili in totale sul sistema, il valore di default è 256 ma si
può usare un valore qualunque fra $0$ e \const{INT\_MAX}. Il limite non
viene applicato ai processi con privilegi amministrativi (cioè con la
\fhead{time.h}
\fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
msg\_len, \\
-\phantom{int mq\_timedsend(}unsigned int msg\_prio, const struct timespec *abs\_timeout)}
+\phantom{int mq\_timedsend(}unsigned int msg\_prio, const struct timespec
+*abs\_timeout)}
\fdesc{Esegue l'inserimento di un messaggio su una coda entro un tempo
specificato}
}
quindi saranno riletti per primi. A parità del valore della priorità il
messaggio sarà inserito in coda a tutti quelli che hanno la stessa priorità
che quindi saranno letti con la politica di una \textit{fifo}. Il valore della
-priorità non può eccedere il limite di sistema \const{MQ\_PRIO\_MAX}, che al
+priorità non può eccedere il limite di sistema \constd{MQ\_PRIO\_MAX}, che al
momento è pari a 32768.
Qualora la coda sia piena, entrambe le funzioni si bloccano, a meno che non
registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore
del segnale di notifica. A differenza della situazione simile che si aveva con
i segnali non affidabili (l'argomento è stato affrontato in
-\ref{sec:sig_semantics}) questa caratteristica non configura una
-\itindex{race~condition} \textit{race condition} perché l'invio di un segnale
-avviene solo se la coda è vuota; pertanto se si vuole evitare di correre il
-rischio di perdere eventuali ulteriori segnali inviati nel lasso di tempo che
-occorre per ripetere la richiesta di notifica basta avere cura di eseguire
-questa operazione prima di estrarre i messaggi presenti dalla coda.
+\ref{sec:sig_semantics}) questa caratteristica non configura una \textit{race
+ condition} perché l'invio di un segnale avviene solo se la coda è vuota;
+pertanto se si vuole evitare di correre il rischio di perdere eventuali
+ulteriori segnali inviati nel lasso di tempo che occorre per ripetere la
+richiesta di notifica basta avere cura di eseguire questa operazione prima di
+estrarre i messaggi presenti dalla coda.
L'invio del segnale di notifica avvalora alcuni campi di informazione
restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in
Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
\texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
la titolarità, e \texttt{nr\_blocks} che permette di specificarne la
-dimensione in blocchi, cioè in multipli di \const{PAGECACHE\_SIZE} che in
+dimensione in blocchi, cioè in multipli di \constd{PAGECACHE\_SIZE} che in
questo caso è l'unità di allocazione elementare.
La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
impostato il flag \const{FD\_CLOEXEC}. Chiamate effettuate da diversi
processi usando lo stesso nome restituiranno file descriptor associati allo
stesso segmento, così come, nel caso di file ordinari, essi sono associati
-allo stesso \itindex{inode} inode. In questo modo è possibile effettuare una
-chiamata ad \func{mmap} sul file descriptor restituito da \func{shm\_open} ed
-i processi vedranno lo stesso segmento di memoria condivisa.
+allo stesso inode. In questo modo è possibile effettuare una chiamata ad
+\func{mmap} sul file descriptor restituito da \func{shm\_open} ed i processi
+vedranno lo stesso segmento di memoria condivisa.
Quando il nome non esiste si può creare un nuovo segmento specificando
\const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file)
\label{sec:ipc_posix_sem}
Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale
-dei semafori POSIX che li realizzava solo a livello di \itindex{thread}
-\textit{thread} e non di processi,\footnote{questo significava che i semafori
- erano visibili solo all'interno dei \itindex{thread} \textit{thread} creati
- da un singolo processo, e non potevano essere usati come meccanismo di
- sincronizzazione fra processi diversi.} fornita attraverso la sezione delle
-estensioni \textit{real-time} della \acr{glibc} (quelle che si accedono
-collegandosi alla libreria \texttt{librt}). Esisteva inoltre una libreria che
-realizzava (parzialmente) l'interfaccia POSIX usando le funzioni dei semafori
-di \textit{SysV-IPC} (mantenendo così tutti i problemi sottolineati in
+dei semafori POSIX che li realizzava solo a livello di \textit{thread} e non
+di processi,\footnote{questo significava che i semafori erano visibili solo
+ all'interno dei \textit{thread} creati da un singolo processo, e non
+ potevano essere usati come meccanismo di sincronizzazione fra processi
+ diversi.} fornita attraverso la sezione delle estensioni \textit{real-time}
+della \acr{glibc} (quelle che si accedono collegandosi alla libreria
+\texttt{librt}). Esisteva inoltre una libreria che realizzava (parzialmente)
+l'interfaccia POSIX usando le funzioni dei semafori di \textit{SysV-IPC}
+(mantenendo così tutti i problemi sottolineati in
sez.~\ref{sec:ipc_sysv_sem}).
A partire dal kernel 2.5.7 è stato introdotto un meccanismo di
\fdesc{Crea un semaforo o ne apre uno esistente.}
}
{La funzione ritorna l'indirizzo del semaforo in caso di successo e
- \const{SEM\_FAILED} per un errore, nel qual caso \var{errno} assumerà uno
+ \constd{SEM\_FAILED} per un errore, nel qual caso \var{errno} assumerà uno
dei valori:
\begin{errlist}
\item[\errcode{EACCES}] il semaforo esiste ma non si hanno permessi
\item[\errcode{EEXIST}] si sono specificati \const{O\_CREAT} e
\const{O\_EXCL} ma il semaforo esiste.
\item[\errcode{EINVAL}] il valore di \param{value} eccede
- \const{SEM\_VALUE\_MAX} o il nome è solo ``\texttt{/}''.
+ \constd{SEM\_VALUE\_MAX} o il nome è solo ``\texttt{/}''.
\item[\errcode{ENAMETOOLONG}] si è utilizzato un nome troppo lungo.
\item[\errcode{ENOENT}] non si è usato \const{O\_CREAT} ed il nome
specificato non esiste.
semafori usano la semantica standard dei file per quanto riguarda i controlli
di accesso, questo significa che un nuovo semaforo viene sempre creato con
l'\ids{UID} ed il \ids{GID} effettivo del processo chiamante, e che i permessi
-indicati con \param{mode} vengono filtrati dal valore della \itindex{umask}
-\textit{umask} del processo. Inoltre per poter aprire un semaforo è
-necessario avere su di esso sia il permesso di lettura che quello di
-scrittura.
+indicati con \param{mode} vengono filtrati dal valore della \textit{umask} del
+processo. Inoltre per poter aprire un semaforo è necessario avere su di esso
+sia il permesso di lettura che quello di scrittura.
La funzione restituisce in caso di successo un puntatore all'indirizzo del
semaforo con un valore di tipo \ctyp{sem\_t *}, è questo valore che dovrà
decrementarlo con successo e proseguire.
Si tenga presente che la funzione può sempre essere interrotta da un segnale,
-nel qual caso si avrà un errore di \const{EINTR}; inoltre questo avverrà
+nel qual caso si avrà un errore di \errval{EINTR}; inoltre questo avverrà
comunque, anche qualora si fosse richiesta la gestione con la semantica BSD,
installando il gestore del suddetto segnale con l'opzione \const{SA\_RESTART}
(vedi sez.~\ref{sec:sig_sigaction}) per riavviare le \textit{system call}
essere utilizzata soltanto se viene definita la macro \macro{\_XOPEN\_SOURCE}
ad un valore di almeno 600 o la macro \macro{\_POSIX\_C\_SOURCE} ad un valore
uguale o maggiore di \texttt{200112L} prima di includere
-\headfile{semaphore.h}, la funzione è \funcd{sem\_timedwait}, ed il suo
+\headfiled{semaphore.h}, la funzione è \funcd{sem\_timedwait}, ed il suo
prototipo è:
\begin{funcproto}{
La funzione incrementa di uno il valore corrente del semaforo indicato
dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà
-sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread})
-eventualmente bloccato in una \func{sem\_wait} sul semaforo possa essere
-svegliato e rimesso in esecuzione. Si tenga presente che la funzione è sicura
-\index{funzioni!sicure} per l'uso all'interno di un gestore di segnali (si
-ricordi quanto detto in sez.~\ref{sec:sig_signal_handler}).
+sbloccata, cosicché un altro processo (o \textit{thread}) eventualmente
+bloccato in una \func{sem\_wait} sul semaforo possa essere svegliato e rimesso
+in esecuzione. Si tenga presente che la funzione è sicura per l'uso
+all'interno di un gestore di segnali (si ricordi quanto detto in
+sez.~\ref{sec:sig_signal_handler}).
Se invece di operare su un semaforo se ne volesse semplicemente leggere il
valore, si potrà usare la funzione \funcd{sem\_getvalue}, il cui prototipo è:
La funzione inizializza un semaforo all'indirizzo puntato dall'argomento
\param{sem}, e come per \func{sem\_open} consente di impostare un valore
iniziale con \param{value}. L'argomento \param{pshared} serve ad indicare se
-il semaforo deve essere utilizzato dai \itindex{thread} \textit{thread} di uno
-stesso processo (con un valore nullo) o condiviso fra processi diversi (con un
-valore non nullo).
+il semaforo deve essere utilizzato dai \textit{thread} di uno stesso processo
+(con un valore nullo) o condiviso fra processi diversi (con un valore non
+nullo).
Qualora il semaforo debba essere condiviso dai \textit{thread} di uno stesso
processo (nel qual caso si parla di \textit{thread-shared semaphore}),
essere stato inizializzato con \func{sem\_init}; non deve quindi essere
applicata a semafori creati con \func{sem\_open}. Inoltre si deve essere
sicuri che il semaforo sia effettivamente inutilizzato, la distruzione di un
-semaforo su cui sono presenti processi (o \itindex{thread} \textit{thread}) in
-attesa (cioè bloccati in una \func{sem\_wait}) provoca un comportamento
-indefinito.
+semaforo su cui sono presenti processi (o \textit{thread}) in attesa (cioè
+bloccati in una \func{sem\_wait}) provoca un comportamento indefinito.
Si tenga presente infine che utilizzare un semaforo che è stato distrutto con
\func{sem\_destroy} di nuovo può dare esito a comportamenti indefiniti. Nel
A questo punto (\texttt{\small 22}) si potrà inizializzare il messaggio posto
nel segmento di memoria condivisa usando la stringa passata come argomento al
programma. Essendo il semaforo stato creato già bloccato non ci si dovrà
-preoccupare di eventuali \itindex{race~condition} \textit{race condition}
-qualora il programma di modifica del messaggio venisse lanciato proprio in
-questo momento. Una volta inizializzato il messaggio occorrerà però
-rilasciare il semaforo (\texttt{\small 24-27}) per consentirne l'uso; in
-tutte queste operazioni si provvederà ad uscire dal programma con un opportuno
-messaggio in caso di errore.
+preoccupare di eventuali \textit{race condition} qualora il programma di
+modifica del messaggio venisse lanciato proprio in questo momento. Una volta
+inizializzato il messaggio occorrerà però rilasciare il semaforo
+(\texttt{\small 24-27}) per consentirne l'uso; in tutte queste operazioni si
+provvederà ad uscire dal programma con un opportuno messaggio in caso di
+errore.
Una volta completate le inizializzazioni il ciclo principale del programma
(\texttt{\small 29-47}) viene ripetuto indefinitamente (\texttt{\small 29})
Una volta completate con successo le precedenti inizializzazioni, il passo
seguente (\texttt{\small 21-24}) è quello di acquisire il semaforo, dopo di
che sarà possibile eseguire la sostituzione del messaggio (\texttt{\small 25})
-senza incorrere in possibili \itindex{race~condition} \textit{race condition}
-con la stampa dello stesso da parte di \file{message\_getter}.
+senza incorrere in possibili \textit{race condition} con la stampa dello
+stesso da parte di \file{message\_getter}.
Una volta effettuata la modifica viene stampato (\texttt{\small 26}) il tempo
di attesa impostato con l'opzione ``\texttt{-t}'' dopo di che (\texttt{\small
\end{Console}
%$
-E si noterà come nel momento in cui si è lanciato \file{message\_setter} le
-stampe di \file{message\_getter} si bloccheranno, come corretto, dopo aver
-registrato un valore nullo per il semaforo. Il programma infatti resterà
-bloccato nella \func{sem\_wait} (quella di riga (\texttt{\small 37}) in
+E si noterà come nel momento in cui si lancia \file{message\_setter} le stampe
+di \file{message\_getter} si bloccheranno, come corretto, dopo aver registrato
+un valore nullo per il semaforo. Il programma infatti resterà bloccato nella
+\func{sem\_wait} (quella di riga (\texttt{\small 37}) in
fig.~\ref{fig:ipc_posix_sem_shm_message_server}) fino alla scadenza
dell'attesa di \file{message\_setter} (con l'esecuzione della \func{sem\_post}
della riga (\texttt{\small 29}) di