X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=8cb04d0729d192b99e5cd8a52a256432fd771e6e;hp=75e8849f83943f159015a8e36e96d35968f7249b;hb=5d621249af8897e27fc0a842a33e7a7ef3b9c2ca;hpb=eba75c4aaf390ff55ad6697ab80d4c1512ea2f39 diff --git a/ipc.tex b/ipc.tex index 75e8849..8cb04d0 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1,6 +1,6 @@ %% 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", @@ -134,7 +134,7 @@ Per capire meglio il funzionamento delle pipe faremo un esempio di quello che è il loro uso più comune, analogo a quello effettuato della shell, e che consiste nell'inviare l'output di un processo (lo standard output) sull'input di un altro. Realizzeremo il programma di esempio nella forma di un -\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un +\textit{CGI}\footnote{un CGI (\textit{Common Gateway Interface}) è un programma che permette la creazione dinamica di un oggetto da inserire all'interno di una pagina HTML.} per Apache, che genera una immagine JPEG di un codice a barre, specificato come argomento in ingresso. @@ -175,10 +175,10 @@ evidente \itindex{race~condition} \textit{race condition} in caso di accesso 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 @@ -190,7 +190,6 @@ fig.~\ref{fig:ipc_barcodepage_code} abbiamo riportato il corpo del programma, 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} @@ -569,7 +568,7 @@ ricevuta la risposta, uscir A questo punto il server resta (se non ci sono altri client che stanno effettuando richieste) con la fifo chiusa sul lato in lettura, ed in questo stato la funzione \func{read} non si bloccherà in attesa di input, ma -ritornerà in continuazione, restituendo un end-of-file.\footnote{Si è usata +ritornerà in continuazione, restituendo un end-of-file.\footnote{si è usata questa tecnica per compatibilità, Linux infatti supporta l'apertura delle fifo in lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura con \const{O\_RDWR}, la doppia apertura comunque ha il vantaggio @@ -656,24 +655,26 @@ verificata) che si facciano le prove direttamente nella directory dei sorgenti (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 @@ -692,7 +693,8 @@ Let's call it an accidental feature. [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. @@ -894,8 +896,9 @@ con i 16 bit meno significativi \index{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 \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 @@ -961,7 +964,7 @@ nullo, nel qual caso l'identificatore sar 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 @@ -973,12 +976,12 @@ controlli 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. @@ -1057,25 +1060,27 @@ inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e 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. @@ -1181,9 +1186,8 @@ file \procrelfile{/proc/sys/kernel}{msgmax}, \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} @@ -1270,7 +1274,7 @@ prototipo 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 @@ -1325,7 +1329,7 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo 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. @@ -1333,13 +1337,11 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo \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 @@ -2476,7 +2478,7 @@ un segmento di memoria condivisa \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. @@ -2573,9 +2575,9 @@ stato marcato per la cancellazione. \label{fig:ipc_shmem_layout} \end{figure} -L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{Lo standard +L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{lo standard SVID prevede che l'argomento \param{shmaddr} sia di tipo \ctyp{char *}, così - come il valore di ritorno della funzione. In Linux è stato così con le + come il valore di ritorno della funzione; in Linux è stato così con le \acr{libc4} e le \acr{libc5}, con il passaggio alle \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 @@ -2605,12 +2607,12 @@ indirizzo come arrotondamento, in Linux 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}: @@ -2902,13 +2904,14 @@ il mutex, prima di uscire. 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 @@ -2918,12 +2921,13 @@ Ci sono 0 socket 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 @@ -2935,12 +2939,13 @@ key semid owner perms nsems ------ 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 @@ -2950,18 +2955,20 @@ Ci sono 0 socket 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 @@ -2971,8 +2978,8 @@ key semid owner perms nsems ------ Message Queues -------- key msqid owner perms used-bytes messages -\end{verbatim}%$ - +\end{Verbatim} +%$ %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta @@ -3258,8 +3265,9 @@ una interfaccia completamente nuova, che tratteremo in questa sezione. 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 @@ -3269,7 +3277,7 @@ POSIX prendono come primo argomento una stringa che indica uno di questi nomi; 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. @@ -3278,7 +3286,7 @@ richiesto 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 @@ -3322,7 +3330,7 @@ Le code di messaggi POSIX sono supportate da Linux a partire dalla versione 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 @@ -3373,7 +3381,6 @@ di messaggi POSIX 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}. @@ -3381,7 +3388,8 @@ di messaggi POSIX 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} @@ -3557,22 +3565,20 @@ Per inserire messaggi su di una coda sono previste due funzioni, \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 @@ -3594,7 +3600,7 @@ bloccante,\footnote{o si sia impostato il flag \const{O\_NONBLOCK} sul file 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. @@ -3702,23 +3708,27 @@ processo alla volta per ciascuna coda. 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. + +% TODO la notifica non è più limitata al solo uso dei segnali, adesso si +% possono anche usare i thread, correggere!. 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 @@ -3946,15 +3956,16 @@ restituendo al chiamante il valore di ritorno. \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 @@ -4041,9 +4052,9 @@ accesso. Questo significa che un nuovo semaforo viene sempre creato con l'user-ID ed il group-ID effettivo del processo chiamante, e che i permessi indicati con -\param{mode} vengono filtrati dal valore della \textit{umask} del processo. -Inoltre per poter aprire un semaforo è necessario avere su di esso sia il -permesso di lettura che quello di scrittura. +\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 @@ -4162,11 +4173,11 @@ fosse occupato;\footnote{si ricordi che in generale un semaforo viene usato 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 è: @@ -4290,15 +4301,16 @@ 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} \textit{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 @@ -4316,9 +4328,8 @@ utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e \func{sem\_post}. Si tenga presente però che inizializzare due volte lo stesso semaforo può dar luogo ad un comportamento indefinito. - -Una volta che non si indenda più utilizzare un semaforo anonimo questo può -essere eliminato da sistema; per far questo di deve utilizzare una apposita +Una volta che non si intenda più utilizzare un semaforo anonimo questo può +essere eliminato dal sistema; per far questo di deve utilizzare una apposita funzione, \funcd{sem\_destroy}, il cui prototipo è: \begin{functions} \headdecl{semaphore.h} @@ -4340,8 +4351,9 @@ La funzione prende come unico argomento l'indirizzo di un semaforo che deve 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 @@ -4399,7 +4411,7 @@ seconda volta con \func{sem\_init}. % 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: