%% ipc.tex
%%
-%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2010 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",
simultaneo a detto file.\footnote{il problema potrebbe essere superato
determinando in anticipo un nome appropriato per il file temporaneo, che
verrebbe utilizzato dai vari sotto-processi, e cancellato alla fine della
- loro esecuzione; ma a questo le cose non sarebbero più tanto semplici.}
-L'uso di una 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.
+ loro esecuzione; ma a questo punto le cose non sarebbero più tanto
+ semplici.} L'uso di una 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
il cui codice completo è disponibile nel file \file{BarCodePage.c} che si
trova nella directory dei sorgenti.
-
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
(dove di norma vengono creati sia i programmi che la libreria), il comando da
dare sarà \code{export LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare
il server, facendogli leggere una decina di frasi, con:
-\begin{verbatim}
+\begin{Verbatim}
[piccardi@gont sources]$ ./fortuned -n10
-\end{verbatim}
+\end{Verbatim}
+%$
Avendo usato \func{daemon} per eseguire il server in background il comando
ritornerà immediatamente, ma potremo verificare con \cmd{ps} che in effetti il
programma resta un esecuzione in background, e senza avere associato un
terminale di controllo (si ricordi quanto detto in sez.~\ref{sec:sess_daemon}):
-\begin{verbatim}
+\begin{Verbatim}
[piccardi@gont sources]$ ps aux
...
piccardi 27489 0.0 0.0 1204 356 ? S 01:06 0:00 ./fortuned -n10
piccardi 27492 3.0 0.1 2492 764 pts/2 R 01:08 0:00 ps aux
-\end{verbatim}%$
+\end{Verbatim}
+%$
e si potrà verificare anche che in \file{/tmp} è stata creata la fifo di
ascolto \file{fortune.fifo}. A questo punto potremo interrogare il server con
il programma client; otterremo così:
-\begin{verbatim}
+\begin{Verbatim}
[piccardi@gont sources]$ ./fortune
Linux ext2fs has been stable for a long time, now it's time to break it
-- Linuxkongreß '95 in Berlin
[piccardi@gont sources]$ ./fortune
Linux ext2fs has been stable for a long time, now it's time to break it
-- Linuxkongreß '95 in Berlin
-\end{verbatim}%$
+\end{Verbatim}
+%$
e ripetendo varie volte il comando otterremo, in ordine casuale, le dieci
frasi tenute in memoria dal server.
\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}.
+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}.
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
Il secondo livello di controllo è quello delle varie funzioni che accedono
direttamente (in lettura o scrittura) all'oggetto. In tal caso lo schema dei
controlli è simile a quello dei file, ed avviene secondo questa sequenza:
-\begin{itemize}
+\begin{itemize*}
\item se il processo ha i privilegi di amministratore l'accesso è sempre
consentito.
\item se l'user-ID effettivo del processo corrisponde o al valore del campo
valore del campo \var{cgid} o a quello del campo \var{gid} ed il permesso
per il gruppo in \var{mode} è appropriato l'accesso è consentito.
\item se il permesso per gli altri è appropriato l'accesso è consentito.
-\end{itemize}
+\end{itemize*}
solo se tutti i controlli elencati falliscono l'accesso è negato. Si noti che
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 \var{umask} (si ricordi quanto esposto in
+il valore di \itindex{umask} \textit{umask} (si ricordi quanto esposto in
sez.~\ref{sec:file_perm_management}) non ha alcun significato.
stampa, cancellazione. I valori di default sono per l'uso delle code di
messaggi e un ciclo di 5 volte. Se si lancia il comando si otterrà qualcosa
del tipo:
-\begin{verbatim}
+\begin{Verbatim}
piccardi@gont sources]$ ./ipctestid
Identifier Value 0
Identifier Value 32768
Identifier Value 65536
Identifier Value 98304
Identifier Value 131072
-\end{verbatim}%$
+\end{Verbatim}
+%$
il che ci mostra che abbiamo un kernel della serie 2.4.x nel quale non avevamo
ancora usato nessuna coda di messaggi. Se ripetiamo il comando otterremo
ancora:
-\begin{verbatim}
+\begin{Verbatim}
[piccardi@gont sources]$ ./ipctestid
Identifier Value 163840
Identifier Value 196608
Identifier Value 229376
Identifier Value 262144
Identifier Value 294912
-\end{verbatim}%$
+\end{Verbatim}
+%$
che ci mostra come il valore di \var{seq} sia in effetti una quantità
mantenuta staticamente all'interno del sistema.
\procrelfile{/proc/sys/kernel}{msgmnb} e
\procrelfile{/proc/sys/kernel}{msgmni} di \file{/proc/sys/kernel/}.
-
\begin{figure}[htb]
- \centering \includegraphics[width=15cm]{img/mqstruct}
+ \centering \includegraphics[width=13cm]{img/mqstruct}
\caption{Schema della struttura di una coda messaggi.}
\label{fig:ipc_mq_schema}
\end{figure}
Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
- \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+ \bodydesc{La funzione restituisce 0 in caso di successo o $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma processo
Invia un messaggio sulla coda \param{msqid}.
- \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
+ \bodydesc{La funzione restituisce 0, e $-1$ in caso di errore, nel qual caso
\var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EACCES}] non si hanno i privilegi di accesso sulla coda.
\item[\errcode{EAGAIN}] il messaggio non può essere inviato perché si è
superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti
sulla coda, e si è richiesto \const{IPC\_NOWAIT} in \param{flag}.
- \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
\item[\errcode{EINVAL}] si è specificato un \param{msgid} invalido, o un
valore non positivo per \param{mtype}, o un valore di \param{msgsz}
maggiore di \const{MSGMAX}.
\end{errlist}
- ed inoltre \errval{EFAULT} ed \errval{ENOMEM}.
-}
+ ed inoltre \errval{EFAULT}, \errval{EINTR} ed \errval{ENOMEM}. }
\end{functions}
La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
\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
+ \item[\errcode{EINVAL}] o \param{shmid} non è un identificatore valido o
\param{cmd} non è un comando valido.
\item[\errcode{EIDRM}] l'argomento \param{shmid} fa riferimento ad un
segmento che è stato cancellato.
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
-caso un tentativo di scrivere sul segmento comporterà una violazione di
-accesso con l'emissione di un segnale di \const{SIGSEGV}. Il comportamento
-usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in
-lettura e scrittura (ed il processo deve aver questi permessi in
-\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in
-sola scrittura.
+caso un tentativo di scrivere sul segmento comporterà una
+\itindex{segment~violation} violazione di accesso con l'emissione di un
+segnale di \const{SIGSEGV}. Il comportamento usuale di \func{shmat} è quello
+di agganciare il segmento con l'accesso in lettura e scrittura (ed il processo
+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}:
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}
+\begin{Verbatim}
[piccardi@gont sources]$ ./dirmonitor ./
-\end{verbatim}%$
+\end{Verbatim}
+%$
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}
+\begin{Verbatim}
[piccardi@gont sources]$ ./readmon
Ci sono 68 file dati
Ci sono 3 directory
Ci sono 0 device a caratteri
Ci sono 0 device a blocchi
Totale 71 file, per 489831 byte
-\end{verbatim}%$
+\end{Verbatim}
+%$
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}
+\begin{Verbatim}
[piccardi@gont sources]$ ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
------ Message Queues --------
key msqid owner perms used-bytes messages
-\end{verbatim}%$
+\end{Verbatim}
+%$
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}
+\begin{Verbatim}
[piccardi@gont sources]$ ./readmon
Ci sono 69 file dati
Ci sono 3 directory
Ci sono 0 device a caratteri
Ci sono 0 device a blocchi
Totale 72 file, per 489887 byte
-\end{verbatim}%$
+\end{Verbatim}
+%$
A questo punto possiamo far uscire il server inviandogli un segnale di
\const{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto
ripetendo la lettura, otterremo un errore:
-\begin{verbatim}
+\begin{Verbatim}
[piccardi@gont sources]$ ./readmon
Cannot find shared memory: No such file or directory
-\end{verbatim}%$
+\end{Verbatim}
+%$
e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione
visti in precedenza sono stati regolarmente cancellati:
-\begin{verbatim}
+\begin{Verbatim}
[piccardi@gont sources]$ ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
------ Message Queues --------
key msqid owner perms used-bytes messages
-\end{verbatim}%$
-
+\end{Verbatim}
+%$
%% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
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 dalle \acr{glibc} nella sezione che
-implementa i 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 \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.
La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
degli identificatori e delle chiavi visti nel SysV IPC, per passare ai
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
\itindex{pathname} \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
2.6.6-rc1 del kernel,\footnote{l'implementazione è dovuta a Michal Wronski e
Krzysztof Benedyczak, e le relative informazioni si possono trovare su
\href{http://www.geocities.com/wronski12/posix_ipc/index.html}
- {\texttt{http://www.geocities.com/wronski12/posix\_ipc/index.html}}.} In
+ {\textsf{http://www.geocities.com/wronski12/posix\_ipc/index.html}}.} In
generale, come le corrispettive del SysV IPC, le code di messaggi sono poco
usate, dato che i socket, nei casi in cui sono sufficienti, sono più comodi, e
che in casi più complessi la comunicazione può essere gestita direttamente con
alla memoria secondo quanto specificato da \param{oflag}.
\item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e
\const{O\_EXCL} ma la coda già esiste.
- \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
\item[\errcode{EINVAL}] il file non supporta la funzione, o si è
specificato \const{O\_CREAT} con una valore non nullo di \param{attr} e
valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}.
non esiste.
\end{errlist}
ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
- \errval{EMFILE} ed \errval{ENFILE}.}
+ \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE}.
+}
\end{functions}
La funzione apre la coda di messaggi identificata dall'argomento \param{name}
\param{abs\_timeout}.
- \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+ \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ in caso di
errore; nel quel caso \var{errno} assumerà i valori:
\begin{errlist}
\item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
coda è piena.
\item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len}
eccede il limite impostato per la coda.
- \item[\errcode{ENOMEM}] il kernel non ha memoria sufficiente. Questo
- errore può avvenire quando l'inserimento del messaggio
\item[\errcode{EINVAL}] si è specificato un valore nullo per
\param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o
un valore non valido per \param{abs\_timeout}.
\item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato
effettuato entro il tempo stabilito.
\end{errlist}
- ed inoltre \errval{EBADF} ed \errval{EINTR}.}
+ ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR}.}
\end{functions}
Entrambe le funzioni richiedono un puntatore al testo del messaggio
La sola differenza fra le due funzioni è che la seconda, passato il tempo
massimo impostato con l'argomento \param{abs\_timeout},\footnote{deve essere
specificato un tempo assoluto tramite una struttura \struct{timespec} (vedi
- fig.~\ref{fig:sys_timeval_struct}) indicato in numero di secondi e
+ fig.~\ref{fig:sys_timespec_struct}) indicato in numero di secondi e
nanosecondi a partire dal 1 gennaio 1970.} ritorna comunque con un errore di
\errcode{ETIMEDOUT}, se invece il tempo è già scaduto al momento della
chiamata e la coda è vuota la funzione ritorna immediatamente.
Il comportamento di \func{mq\_notify} dipende dal valore dell'argomento
\param{notification}, che è un puntatore ad una apposita struttura
-\struct{sigevent}, (definita in fig.~\ref{fig:file_sigevent}) introdotta dallo
-standard POSIX.1b per gestire la notifica di eventi; per altri dettagli si può
-vedere quanto detto in sez.~\ref{sec:file_asyncronous_io} a proposito dell'uso
-della stessa struttura per l'invio dei segnali usati per l'I/O asincrono.
+\struct{sigevent}, (definita in fig.~\ref{fig:struct_sigevent}) introdotta
+dallo standard POSIX.1b per gestire la notifica di eventi; per altri dettagli
+si può vedere quanto detto in sez.~\ref{sec:file_asyncronous_io} a proposito
+dell'uso della stessa struttura per l'invio dei segnali usati per l'I/O
+asincrono.
Attraverso questa struttura si possono impostare le modalità con cui viene
effettuata la notifica; in particolare il campo \var{sigev\_notify} deve
essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato
- sui thread, specificato tramite il valore \const{SIGEV\_THREAD}, non è
- implementato.} ed il campo \var{sigev\_signo} deve indicare il valore del
-segnale che sarà inviato al processo. Inoltre il campo \var{sigev\_value} è il
-puntatore ad una struttura \struct{sigval\_t} (definita in
-fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale un
-valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
- trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali
- real-time.} posto che questo sia installato nella forma estesa vista in
-sez.~\ref{sec:sig_sigaction}.
+ sui \itindex{thread} \textit{thread}, specificato tramite il valore
+ \const{SIGEV\_THREAD}, non è implementato.} ed il campo \var{sigev\_signo}
+deve indicare il valore del segnale che sarà inviato al processo. Inoltre il
+campo \var{sigev\_value} è il puntatore ad una struttura \struct{sigval\_t}
+(definita in fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore
+del segnale un valore numerico o un indirizzo,\footnote{per il suo uso si
+ riveda la trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei
+ segnali real-time.} posto che questo sia installato nella forma estesa vista
+in sez.~\ref{sec:sig_sigaction}.
La funzione registra il processo chiamante per la notifica se
\param{notification} punta ad una struttura \struct{sigevent} opportunamente
\label{sec:ipc_posix_sem}
Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale
-dei semafori POSIX che li realizzava solo a livello di thread e non di
-processi,\footnote{questo significava che i semafori erano visibili solo
- all'interno dei thread creati da un singolo processo, e non potevano essere
- usati come meccanismo di sincronizzazione fra processi diversi.} fornita
-attraverso la sezione delle estensioni \textit{real-time} delle
-\acr{glibc}.\footnote{quelle che si accedono collegandosi alla libreria
- \texttt{librt}.} Esisteva inoltre una libreria che realizzava (parzialmente)
-l'interfaccia POSIX usando le funzioni dei semafori di SysV IPC (mantenendo
-così tutti i problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem}).
+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} delle \acr{glibc}.\footnote{quelle che si
+ accedono collegandosi alla libreria \texttt{librt}.} Esisteva inoltre una
+libreria che realizzava (parzialmente) l'interfaccia POSIX usando le funzioni
+dei semafori di SysV IPC (mantenendo così tutti i problemi sottolineati in
+sez.~\ref{sec:ipc_sysv_sem}).
A partire dal kernel 2.5.7 è stato introdotto un meccanismo di
sincronizzazione completamente nuovo, basato sui cosiddetti
Questo significa che un nuovo semaforo viene sempre creato con l'user-ID ed il
group-ID effettivo del processo chiamante, e che i permessi indicati con
-\param{mode} vengono filtrati dal valore della \textit{umask} del processo.
-Inoltre per poter aprire un semaforo è necessario avere su di esso sia il
-permesso di lettura che quello di scrittura.
+\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.
Una volta che si sia ottenuto l'indirizzo di un semaforo, sarà possibile
utilizzarlo; se si ricorda quanto detto all'inizio di
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 thread) eventualmente bloccato in una
-\func{sem\_wait} sul semaforo potrà 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 \itindex{thread} \textit{thread})
+eventualmente bloccato in una \func{sem\_wait} sul semaforo potrà 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}).
Se invece di operare su un semaforo se ne vuole solamente leggere il valore,
si può 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} 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 \itindex{thread} \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 \itindex{thread} thread di uno
-stesso processo (nel qual caso si parla di \textit{thread-shared semaphore}),
-occorrerà che \param{sem} sia l'indirizzo di una variabile visibile da tutti i
-\itindex{thread} thread, si dovrà usare cioè una variabile globale o una
-variabile allocata dinamicamente nello \itindex{heap} heap.
+Qualora il semaforo debba essere condiviso dai \itindex{thread}
+\textit{thread} di uno stesso processo (nel qual caso si parla di
+\textit{thread-shared semaphore}), occorrerà che \param{sem} sia l'indirizzo
+di una variabile visibile da tutti i \itindex{thread} \textit{thread}, si
+dovrà usare cioè una variabile globale o una variabile allocata dinamicamente
+nello \itindex{heap} heap.
Qualora il semaforo debba essere condiviso fra più processi (nel qual caso si
parla di \textit{process-shared semaphore}) la sola scelta possibile per
semaforo può dar luogo ad un comportamento indefinito.
-Una volta che non si indenda più utilizzare un semaforo anonimo questo può
+Una volta che non si intenda più utilizzare un semaforo anonimo questo può
essere eliminato da sistema; per far questo di deve utilizzare una apposita
funzione, \funcd{sem\_destroy}, il cui prototipo è:
\begin{functions}
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 thread) in attesa (cioè bloccati in
-una \func{sem\_wait}) provoca un comportamento indefinito.
+semaforo su cui sono presenti processi (o \itindex{thread} \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
% LocalWords: lrt blocks PAGECACHE TRUNC CLOEXEC mmap ftruncate munmap FindShm
% LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS
% LocalWords: ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait
-% LocalWords: process getvalue sval execve pshared ENOSYS heap
+% LocalWords: process getvalue sval execve pshared ENOSYS heap PAGE destroy
%%% Local Variables: