X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=4168b12ddb2afdd52887e87e8d55342496b44474;hp=762eae1c3d2501c50506c77996c5a17527900168;hb=c474f4307db945bc45287edd0ea4c2c29374d0ee;hpb=687f101ae37d793ffda23c39ca8735e127b5fc9d diff --git a/ipc.tex b/ipc.tex index 762eae1..4168b12 100644 --- a/ipc.tex +++ b/ipc.tex @@ -41,7 +41,7 @@ ne gestiscono l'uso e le varie forme in cui si Le \textit{pipe} nascono sostanzialmente con Unix, e sono il primo, e tuttora uno dei più usati, meccanismi di comunicazione fra processi. Si tratta in -sostanza di una una coppia di file descriptor\footnote{si tenga presente che +sostanza di una coppia di file descriptor\footnote{si tenga presente che le pipe sono oggetti creati dal kernel e non risiedono su disco.} connessi fra di loro in modo che se quanto scrive su di uno si può rileggere dall'altro. Si viene così a costituire un canale di comunicazione tramite i @@ -67,8 +67,8 @@ scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale nel file descriptor aperto in lettura. I file descriptor infatti non sono connessi a nessun file reale, ma ad un buffer nel kernel, la cui dimensione è specificata dal parametro di sistema \const{PIPE\_BUF}, (vedi -\secref{sec:sys_file_limits}). Lo schema di funzionamento di una pipe è -illustrato in \figref{fig:ipc_pipe_singular}, in cui sono illustrati i due +sez.~\ref{sec:sys_file_limits}). Lo schema di funzionamento di una pipe è +illustrato in fig.~\ref{fig:ipc_pipe_singular}, in cui sono illustrati i due capi della pipe, associati a ciascun file descriptor, con le frecce che indicano la direzione del flusso dei dati. @@ -80,12 +80,12 @@ indicano la direzione del flusso dei dati. \end{figure} Chiaramente creare una pipe all'interno di un singolo processo non serve a -niente; se però ricordiamo quanto esposto in \secref{sec:file_sharing} +niente; se però ricordiamo quanto esposto in sez.~\ref{sec:file_sharing} riguardo al comportamento dei file descriptor nei processi figli, è immediato capire come una pipe possa diventare un meccanismo di intercomunicazione. Un processo figlio infatti condivide gli stessi file descriptor del padre, compresi quelli associati ad una pipe (secondo la situazione illustrata in -\figref{fig:ipc_pipe_fork}). In questo modo se uno dei processi scrive su un +fig.~\ref{fig:ipc_pipe_fork}). In questo modo se uno dei processi scrive su un capo della pipe, l'altro può leggere. \begin{figure}[htb] @@ -154,15 +154,15 @@ Per realizzare quanto voluto useremo in sequenza i programmi \cmd{barcode} e codici a barre corrispondenti ad una qualunque stringa, mentre il secondo serve per poter effettuare la conversione della stessa immagine in formato JPEG. Usando una pipe potremo inviare l'output del primo sull'input del -secondo, secondo lo schema mostrato in \figref{fig:ipc_pipe_use}, in cui la +secondo, secondo lo schema mostrato in fig.~\ref{fig:ipc_pipe_use}, in cui la direzione del flusso dei dati è data dalle frecce continue. \begin{figure}[htb] \centering \includegraphics[height=5cm]{img/pipeuse} \caption{Schema dell'uso di una pipe come mezzo di comunicazione fra - due processi attraverso attraverso l'esecuzione una \func{fork} e la - chiusura dei capi non utilizzati.} + due processi attraverso l'esecuzione una \func{fork} e la chiusura dei + capi non utilizzati.} \label{fig:ipc_pipe_use} \end{figure} @@ -179,12 +179,13 @@ essere molto pi Il programma ci servirà anche come esempio dell'uso delle funzioni di duplicazione dei file descriptor che abbiamo trattato in -\secref{sec:file_dup}, in particolare di \func{dup2}. È attraverso queste +sez.~\ref{sec:file_dup}, in particolare di \func{dup2}. È attraverso queste funzioni infatti che è possibile dirottare gli stream standard dei processi -(che abbiamo visto in \secref{sec:file_std_descr} e -\secref{sec:file_std_stream}) sulla pipe. In \figref{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. +(che abbiamo visto in sez.~\ref{sec:file_std_descr} e +sez.~\ref{sec:file_std_stream}) sulla pipe. In +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] @@ -203,7 +204,7 @@ le due pipe che serviranno per la comunicazione fra i due comandi utilizzati per produrre il codice a barre; si ha cura di controllare la riuscita della chiamata, inviando in caso di errore un messaggio invece dell'immagine richiesta.\footnote{la funzione \func{WriteMess} non è riportata in - \secref{fig:ipc_barcodepage_code}; essa si incarica semplicemente di + fig.~\ref{fig:ipc_barcodepage_code}; essa si incarica semplicemente di formattare l'uscita alla maniera dei CGI, aggiungendo l'opportuno \textit{mime type}, e formattando il messaggio in HTML, in modo che quest'ultimo possa essere visualizzato correttamente da un browser.} @@ -300,11 +301,11 @@ programma indicato) in caso si sia indicato \code{"r"}, o in sola scrittura (e quindi associato allo standard input) in caso di \code{"w"}. Lo stream restituito da \func{popen} è identico a tutti gli effetti ai file -stream visti in \capref{cha:files_std_interface}, anche se è collegato ad una -pipe e non ad un file, e viene sempre aperto in modalità -\textit{fully-buffered} (vedi \secref{sec:file_buffering}); l'unica differenza -con gli usuali stream è che dovrà essere chiuso dalla seconda delle due nuove -funzioni, \funcd{pclose}, il cui prototipo è: +stream visti in cap.~\ref{cha:files_std_interface}, anche se è collegato ad +una pipe e non ad un file, e viene sempre aperto in modalità +\textit{fully-buffered} (vedi sez.~\ref{sec:file_buffering}); l'unica +differenza con gli usuali stream è che dovrà essere chiuso dalla seconda delle +due nuove funzioni, \funcd{pclose}, il cui prototipo è: \begin{prototype}{stdio.h} {int pclose(FILE *stream)} @@ -320,7 +321,7 @@ attendendo la terminazione del processo ad essa associato. \func{popen}. Per illustrare l'uso di queste due funzioni riprendiamo il problema -precedente: il programma mostrato in \figref{fig:ipc_barcodepage_code} per +precedente: il programma mostrato in fig.~\ref{fig:ipc_barcodepage_code} per quanto funzionante, è (volutamente) codificato in maniera piuttosto complessa, inoltre nella pratica sconta un problema di \cmd{gs} che non è in grado\footnote{nella versione GNU Ghostscript 6.53 (2002-02-13).} di @@ -364,13 +365,13 @@ semplificare notevolmente la stesura del codice. Nel nostro caso, dato che ciascun processo deve scrivere il suo output sullo standard input del successivo, occorrerà usare \func{popen} aprendo la pipe in scrittura. Il codice del nuovo programma è riportato in -\figref{fig:ipc_barcode_code}. Come si può notare l'ordine di invocazione dei -programmi è l'inverso di quello in cui ci si aspetta che vengano +fig.~\ref{fig:ipc_barcode_code}. Come si può notare l'ordine di invocazione +dei programmi è l'inverso di quello in cui ci si aspetta che vengano effettivamente eseguiti. Questo non comporta nessun problema dato che la lettura su una pipe è bloccante, per cui ciascun processo, per quanto lanciato per primo, si bloccherà in attesa di ricevere sullo standard input il -risultato dell'elaborazione del precedente, benchè quest'ultimo venga -invocato dopo. +risultato dell'elaborazione del precedente, benchè quest'ultimo venga invocato +dopo. \begin{figure}[!htb] \footnotesize \centering @@ -409,10 +410,10 @@ create, tutte le pipe create con \func{pclose}. \subsection{Le \textit{pipe} con nome, o \textit{fifo}} \label{sec:ipc_named_pipe} -Come accennato in \secref{sec:ipc_pipes} il problema delle \textit{pipe} è che -esse possono essere utilizzate solo da processi con un progenitore comune o -nella relazione padre/figlio; per superare questo problema lo standard POSIX.1 -ha definito dei nuovi oggetti, le \textit{fifo}, che hanno le stesse +Come accennato in sez.~\ref{sec:ipc_pipes} il problema delle \textit{pipe} è +che esse possono essere utilizzate solo da processi con un progenitore comune +o nella relazione padre/figlio; per superare questo problema lo standard +POSIX.1 ha definito dei nuovi oggetti, le \textit{fifo}, che hanno le stesse caratteristiche delle pipe, ma che invece di essere strutture interne del kernel, visibili solo attraverso un file descriptor, sono accessibili attraverso un inode\index{inode} che risiede sul filesystem, così che i @@ -424,9 +425,9 @@ attraverso un apposito buffer nel kernel, senza transitare dal filesystem; l'inode\index{inode} allocato sul filesystem serve infatti solo a fornire un punto di riferimento per i processi, che permetta loro di accedere alla stessa fifo; il comportamento delle funzioni di lettura e scrittura è identico a -quello illustrato per le pipe in \secref{sec:ipc_pipes}. +quello illustrato per le pipe in sez.~\ref{sec:ipc_pipes}. -Abbiamo già visto in \secref{sec:file_mknod} le funzioni \func{mknod} e +Abbiamo già visto in sez.~\ref{sec:file_mknod} le funzioni \func{mknod} e \func{mkfifo} che permettono di creare una fifo; per utilizzarne una un processo non avrà che da aprire il relativo file speciale o in lettura o scrittura; nel primo caso sarà collegato al capo di uscita della fifo, e dovrà @@ -460,7 +461,7 @@ situazioni un processo deve ricevere informazioni da altri. In questo caso fondamentale che le operazioni di scrittura siano atomiche; per questo si deve sempre tenere presente che questo è vero soltanto fintanto che non si supera il limite delle dimensioni di \const{PIPE\_BUF} (si ricordi quanto detto in -\secref{sec:ipc_pipes}). +sez.~\ref{sec:ipc_pipes}). A parte il caso precedente, che resta probabilmente il più comune, Stevens riporta in \cite{APUE} altre due casistiche principali per l'uso delle fifo: @@ -470,7 +471,7 @@ riporta in \cite{APUE} altre due casistiche principali per l'uso delle fifo: sull'input di parecchi altri (attraverso l'uso del comando \cmd{tee}). \item Come canale di comunicazione fra client ed server (il modello - \textit{client-server} è illustrato in \secref{sec:net_cliserv}). + \textit{client-server} è illustrato in sez.~\ref{sec:net_cliserv}). \end{itemize} Nel primo caso quello che si fa è creare tante fifo, da usare come standard @@ -489,7 +490,7 @@ la struttura sequenziale delle fifo, i client dovrebbero sapere, prima di leggerli, quando i dati inviati sono destinati a loro. Per risolvere questo problema, si può usare un'architettura come quella -illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le +illustrata in fig.~\ref{fig:ipc_fifo_server_arch} in cui i client inviano le richieste al server su una fifo nota mentre le risposte vengono reinviate dal server a ciascuno di essi su una fifo temporanea creata per l'occasione. @@ -506,7 +507,7 @@ un server di \textit{fortunes}, che restituisce, alle richieste di un client, un detto a caso estratto da un insieme di frasi; sia il numero delle frasi dell'insieme, che i file da cui esse vengono lette all'avvio, sono importabili da riga di comando. Il corpo principale del server è riportato in -\figref{fig:ipc_fifo_server}, dove si è tralasciata la parte che tratta la +fig.~\ref{fig:ipc_fifo_server}, dove si è tralasciata la parte che tratta la gestione delle opzioni a riga di comando, che effettua il settaggio delle variabili \var{fortunefilename}, che indica il file da cui leggere le frasi, ed \var{n}, che indica il numero di frasi tenute in memoria, ad un valore @@ -530,8 +531,8 @@ dell'insieme delle frasi non nulla, dato che l'inizializzazione del vettore presenza di un valore nullo provoca l'uscita dal programma attraverso la routine (non riportata) che ne stampa le modalità d'uso. Dopo di che installa (\texttt{\small 13--15}) la funzione che gestisce i segnali di interruzione -(anche questa non è riportata in \figref{fig:ipc_fifo_server}) che si limita a -rimuovere dal filesystem la fifo usata dal server per comunicare. +(anche questa non è riportata in fig.~\ref{fig:ipc_fifo_server}) che si limita +a rimuovere dal filesystem la fifo usata dal server per comunicare. Terminata l'inizializzazione (\texttt{\small 16}) si effettua la chiamata alla funzione \code{FortuneParse} che legge dal file specificato in @@ -597,9 +598,9 @@ all'apertura della fifo per la risposta, che poi \texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si chiude la fifo di risposta che non serve più. -Il codice del client è invece riportato in \figref{fig:ipc_fifo_client}, anche -in questo caso si è omessa la gestione delle opzioni e la funzione che stampa -a video le informazioni di utilizzo ed esce, riportando solo la sezione +Il codice del client è invece riportato in fig.~\ref{fig:ipc_fifo_client}, +anche in questo caso si è omessa la gestione delle opzioni e la funzione che +stampa a video le informazioni di utilizzo ed esce, riportando solo la sezione principale del programma e le definizioni delle variabili. Il codice completo è nel file \file{FortuneClient.c} dei sorgenti allegati. @@ -658,7 +659,7 @@ leggere una decina di frasi, con: 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 \secref{sec:sess_daemon}): +terminale di controllo (si ricordi quanto detto in sez.~\ref{sec:sess_daemon}): \begin{verbatim} [piccardi@gont sources]$ ps aux ... @@ -706,8 +707,8 @@ complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens, fifo non è adatta a risolvere questo tipo di problemi, che possono essere affrontati in maniera più semplice ed efficace o usando i \textit{socket}\index{socket} (che tratteremo in dettaglio a partire da -\capref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione diversi, -come quelli che esamineremo in seguito. +cap.~\ref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione +diversi, come quelli che esamineremo in seguito. @@ -717,12 +718,12 @@ come quelli che esamineremo in seguito. Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti \textsl{socket locali} (o \textit{Unix domain socket}). Tratteremo l'argomento -dei \textit{socket}\index{socket} in \capref{cha:socket_intro},\footnote{si +dei \textit{socket}\index{socket} in cap.~\ref{cha:socket_intro},\footnote{si tratta comunque di oggetti di comunicazione che, come le pipe, sono utilizzati attraverso dei file descriptor.} nell'ambito dell'interfaccia generale che essi forniscono per la programmazione di rete; e vedremo anche -(in~\secref{sec:sock_sa_local}) come si possono definire dei file speciali (di -tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede +(in~sez.~\ref{sec:sock_sa_local}) come si possono definire dei file speciali +(di tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede però attraverso quella medesima interfaccia; vale però la pena esaminare qui una modalità di uso dei socket locali\footnote{la funzione \func{socketpair} è stata introdotta in BSD4.4, ma è supportata in genere da qualunque sistema @@ -770,7 +771,7 @@ socket\index{socket} locali in generale) permette di trasmettere attraverso le linea non solo dei dati, ma anche dei file descriptor: si può cioè passare da un processo ad un altro un file descriptor, con una sorta di duplicazione dello stesso non all'interno di uno stesso processo, ma fra processi distinti -(torneremo su questa funzionalità in \secref{sec:xxx_fd_passing}). +(torneremo su questa funzionalità in sez.~\ref{sec:xxx_fd_passing}). \section{La comunicazione fra processi di System V} @@ -813,7 +814,7 @@ Un'ulteriore caratteristica negativa specificando il relativo \textsl{identificatore}. Questo è un numero progressivo (un po' come il \acr{pid} dei processi) che il kernel assegna a ciascuno di essi quanto vengono creati (sul procedimento di assegnazione -torneremo in \secref{sec:ipc_sysv_id_use}). L'identificatore viene restituito +torneremo in sez.~\ref{sec:ipc_sysv_id_use}). L'identificatore viene restituito dalle funzioni che creano l'oggetto, ed è quindi locale al processo che le ha eseguite. Dato che l'identificatore viene assegnato dinamicamente dal kernel non è possibile prevedere quale sarà, né utilizzare un qualche valore statico, @@ -828,7 +829,7 @@ tramite la quale si sposta il problema dell'accesso dalla classificazione in base all'identificatore alla classificazione in base alla chiave, una delle tante complicazioni inutili presenti nel \textit{SysV IPC}.} Oltre la chiave, la -struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm}, +struttura, la cui definizione è riportata in fig.~\ref{fig:ipc_ipc_perm}, mantiene varie proprietà ed informazioni associate all'oggetto. \begin{figure}[!htb] @@ -910,7 +911,7 @@ problema del \textit{SysV IPC}. Non esiste infatti una modalit identificare un oggetto, come sarebbe stato se lo si fosse associato ad in file, e tutta l'interfaccia è inutilmente complessa. Per questo ne è stata effettuata una revisione completa nello standard POSIX.1b, che tratteremo in -\secref{sec:ipc_posix}. +sez.~\ref{sec:ipc_posix}. \subsection{Il controllo di accesso} @@ -921,7 +922,7 @@ Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in (nei campi \var{cuid} e \var{cgid}) e del proprietario (nei campi \var{uid} e \var{gid}) dello stesso, e un insieme di permessi (nel campo \var{mode}). In questo modo è possibile definire un controllo di accesso sugli oggetti di IPC, -simile a quello che si ha per i file (vedi \secref{sec:file_perm_overview}). +simile a quello che si ha per i file (vedi sez.~\ref{sec:file_perm_overview}). Benché questo controllo di accesso sia molto simile a quello dei file, restano delle importanti differenze. La prima è che il permesso di esecuzione non @@ -929,7 +930,7 @@ esiste (e se specificato viene ignorato), per cui si pu permessi di lettura e scrittura (nel caso dei semafori poi quest'ultimo è più propriamente un permesso di modifica). I valori di \var{mode} sono gli stessi ed hanno lo stesso significato di quelli riportati in -\secref{tab:file_mode_flags}\footnote{se però si vogliono usare le costanti +tab.~\ref{tab:file_mode_flags}\footnote{se però si vogliono usare le costanti simboliche ivi definite occorrerà includere il file \file{sys/stat.h}, alcuni sistemi definiscono le costanti \const{MSG\_R} (\texttt{0400}) e \const{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e @@ -975,14 +976,14 @@ 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 -\secref{sec:file_umask}) non ha alcun significato. +sez.~\ref{sec:file_umask}) non ha alcun significato. \subsection{Gli identificatori ed il loro utilizzo} \label{sec:ipc_sysv_id_use} L'unico campo di \struct{ipc\_perm} del quale non abbiamo ancora parlato è -\var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico +\var{seq}, che in fig.~\ref{fig:ipc_ipc_perm} è qualificato con un criptico ``\textsl{numero di sequenza}'', ne parliamo adesso dato che esso è strettamente attinente alle modalità con cui il kernel assegna gli identificatori degli oggetti del sistema di IPC. @@ -1039,12 +1040,12 @@ s \label{fig:ipc_sysv_idtest} \end{figure} -In \figref{fig:ipc_sysv_idtest} è riportato il codice di un semplice programma -di test che si limita a creare un oggetto (specificato a riga di comando), -stamparne il numero di identificatore e cancellarlo per un numero specificato -di volte. Al solito non si è riportato il codice della gestione delle opzioni -a riga di comando, che permette di specificare quante volte effettuare il -ciclo \var{n}, e su quale tipo di oggetto eseguirlo. +In fig.~\ref{fig:ipc_sysv_idtest} è riportato il codice di un semplice +programma di test che si limita a creare un oggetto (specificato a riga di +comando), stamparne il numero di identificatore e cancellarlo per un numero +specificato di volte. Al solito non si è riportato il codice della gestione +delle opzioni a riga di comando, che permette di specificare quante volte +effettuare il ciclo \var{n}, e su quale tipo di oggetto eseguirlo. La figura non riporta il codice di selezione delle opzioni, che permette di inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e @@ -1133,7 +1134,7 @@ 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 significativi di \param{flag} saranno usati come permessi per il nuovo -oggetto, secondo quanto illustrato in \secref{sec:ipc_sysv_access_control}. +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à successo solo se l'oggetto non esiste già, fallendo con un errore di \errcode{EEXIST} altrimenti. @@ -1170,7 +1171,7 @@ coda. Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti negli header e corrispondenti alle prime tre costanti riportate in -\tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile +tab.~\ref{tab:ipc_msg_limits}, come accennato però in Linux è possibile modificare questi limiti attraverso l'uso di \func{sysctl} o scrivendo nei file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}. @@ -1190,9 +1191,9 @@ Una coda di messaggi 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 \figref{fig:ipc_mq_schema} si è -riportato lo schema con cui queste strutture vengono mantenute dal -kernel.\footnote{lo schema illustrato in \figref{fig:ipc_mq_schema} è in +coda alla lista e vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si +è riportato lo schema con cui queste strutture vengono mantenute dal +kernel.\footnote{lo schema illustrato in fig.~\ref{fig:ipc_mq_schema} è in realtà una semplificazione di quello usato effettivamente fino ai kernel della serie 2.2.x, nei kernel della serie 2.4.x la gestione delle code di messaggi è stata modificata ed è effettuata in maniera diversa; abbiamo @@ -1211,22 +1212,22 @@ kernel.\footnote{lo schema illustrato in \figref{fig:ipc_mq_schema} \end{figure} A ciascuna coda è associata una struttura \struct{msgid\_ds}, la cui -definizione, è riportata in \secref{fig:ipc_msqid_ds}. In questa struttura il +definizione, è riportata in fig.~\ref{fig:ipc_msqid_ds}. In questa struttura il kernel mantiene le principali informazioni riguardo lo stato corrente della coda.\footnote{come accennato questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle funzioni dell'interfaccia. Si noti come ci sia una differenza con i campi mostrati nello schema di - \figref{fig:ipc_mq_schema} che sono presi dalla definizione di + fig.~\ref{fig:ipc_mq_schema} che sono presi dalla definizione di \file{linux/msg.h}, e fanno riferimento alla definizione della omonima - struttura usata nel kernel.} In \figref{fig:ipc_msqid_ds} sono elencati i + struttura usata nel kernel.} In fig.~\ref{fig:ipc_msqid_ds} sono elencati i campi significativi definiti in \file{sys/msg.h}, a cui si sono aggiunti gli ultimi tre campi che sono previsti dalla implementazione originale di System V, ma non dallo standard Unix98. Quando si crea una nuova coda con \func{msgget} questa struttura viene inizializzata, in particolare il campo \var{msg\_perm} viene inizializzato -come illustrato in \secref{sec:ipc_sysv_access_control}, per quanto riguarda +come illustrato in sez.~\ref{sec:ipc_sysv_access_control}, per quanto riguarda gli altri campi invece: \begin{itemize*} \item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti @@ -1289,7 +1290,7 @@ eseguire; i valori possibili sono: \item[\const{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con effetto immediato. Tutti i processi che cercheranno di accedere alla coda riceveranno un errore di \errcode{EIDRM}, e tutti processi in attesa su - funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo + funzioni di lettura o di scrittura sulla coda saranno svegliati ricevendo il medesimo errore. Questo comando può essere eseguito solo da un processo con user-ID effettivo corrispondente al creatore o al proprietario della coda, o all'amministratore. @@ -1338,11 +1339,11 @@ La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso il l'argomento \param{msgp}. Quest'ultimo deve venire passato sempre come puntatore ad una struttura \struct{msgbuf} analoga a quella riportata in -\figref{fig:ipc_msbuf} che è quella che deve contenere effettivamente il +fig.~\ref{fig:ipc_msbuf} che è quella che deve contenere effettivamente il messaggio. La dimensione massima per il testo di un messaggio non può comunque superare il limite \const{MSGMAX}. -La struttura di \figref{fig:ipc_msbuf} è comunque solo un modello, tanto che +La struttura di fig.~\ref{fig:ipc_msbuf} è comunque solo un modello, tanto che la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici. La sola cosa che conta è che la struttura abbia come primo membro un campo @@ -1352,7 +1353,7 @@ messaggio e deve essere sempre specificato come intero positivo di tipo dimensione, e serve a contenere il testo del messaggio. In generale pertanto per inviare un messaggio con \func{msgsnd} si usa -ridefinire una struttura simile a quella di \figref{fig:ipc_msbuf}, adattando +ridefinire una struttura simile a quella di fig.~\ref{fig:ipc_msbuf}, adattando alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il corpo del messaggio, anche con più campi o con strutture più complesse) avendo però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne @@ -1362,7 +1363,7 @@ Si tenga presente che la lunghezza che deve essere indicata in questo argomento è solo quella del messaggio, non quella di tutta la struttura, se 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 \figref{fig:ipc_msbuf}, \param{msgsz} +consideriamo il caso dell'esempio in fig.~\ref{fig:ipc_msbuf}, \param{msgsz} dovrà essere pari a \const{LENGTH}). \begin{figure}[!htb] @@ -1378,7 +1379,7 @@ dovr Per capire meglio il funzionamento della funzione riprendiamo in considerazione la struttura della coda illustrata in -\figref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio +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 @@ -1443,10 +1444,10 @@ La funzione che viene utilizzata per estrarre un messaggio da una coda La funzione legge un messaggio dalla coda specificata, scrivendolo sulla struttura puntata da \param{msgp}, che dovrà avere un formato analogo a quello -di \figref{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 -\figref{fig:ipc_msbuf}). +di fig.~\ref{fig:ipc_msbuf}. Una volta estratto, il messaggio sarà rimosso +dalla coda. L'argomento \param{msgsz} indica la lunghezza massima del testo +del messaggio (equivalente al valore del parametro \const{LENGTH} nell'esempio +di fig.~\ref{fig:ipc_msbuf}). Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a @@ -1456,13 +1457,13 @@ un errore di \errcode{E2BIG}. L'argomento \param{msgtyp} permette di restringere la ricerca ad un sottoinsieme dei messaggi presenti sulla coda; la ricerca infatti è fatta con -una scansione della struttura mostrata in \figref{fig:ipc_mq_schema}, +una scansione della struttura mostrata in fig.~\ref{fig:ipc_mq_schema}, restituendo il primo messaggio incontrato che corrisponde ai criteri specificati (che quindi, visto come i messaggi vengono sempre inseriti dalla coda, è quello meno recente); in particolare: \begin{itemize} \item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè - quello fra i presenti che è stato inserito inserito per primo. + quello fra i presenti che è stato inserito per primo. \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui tipo (il valore del campo \var{mtype}) corrisponde al valore di \param{msgtyp}. @@ -1505,10 +1506,10 @@ tutte le risorse occupate vengono rilasciate quanto l'ultimo processo che le utilizzava termina. Questo comporta che in caso di errori si può saturare il sistema, e che devono comunque essere esplicitamente previste delle funzioni di rimozione in caso di interruzioni o uscite dal programma (come vedremo in -\figref{fig:ipc_mq_fortune_server}). +fig.~\ref{fig:ipc_mq_fortune_server}). L'altro problema è non facendo uso di file descriptor le tecniche di -\textit{I/O multiplexing} descritte in \secref{sec:file_multiplexing} non +\textit{I/O multiplexing} descritte in sez.~\ref{sec:file_multiplexing} non possono essere utilizzate, e non si ha a disposizione niente di analogo alle funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di una di queste strutture alla volta; ad esempio non si può scrivere un server @@ -1532,7 +1533,7 @@ in maniera indipendente con client diversi. \label{fig:ipc_mq_fortune_server} \end{figure} -In \figref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti +In fig.~\ref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti principali del codice del nuovo server (il codice completo è nel file \file{MQFortuneServer.c} nei sorgenti allegati). Il programma è basato su un uso accorto della caratteristica di poter associate un ``tipo'' ai messaggi @@ -1606,13 +1607,13 @@ gestore \code{HandSIGTERM}, che semplicemente si limita a cancellare la coda \label{fig:ipc_mq_fortune_client} \end{figure} -In \figref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice del -programma client. Al solito il codice completo è con i sorgenti allegati, nel -file \file{MQFortuneClient.c}. Come sempre si sono rimosse le parti relative -alla gestione delle opzioni, ed in questo caso, anche la dichiarazione delle -variabili, che, per la parte relative alle strutture usate per la -comunicazione tramite le code, sono le stesse viste in -\figref{fig:ipc_mq_fortune_server}. +In fig.~\ref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice +del programma client. Al solito il codice completo è con i sorgenti allegati, +nel file \file{MQFortuneClient.c}. Come sempre si sono rimosse le parti +relative alla gestione delle opzioni, ed in questo caso, anche la +dichiarazione delle variabili, che, per la parte relative alle strutture usate +per la comunicazione tramite le code, sono le stesse viste in +fig.~\ref{fig:ipc_mq_fortune_server}. Il client in questo caso è molto semplice; la prima parte del programma (\texttt{\small 4--9}) si occupa di accedere alla coda di messaggi, ed è @@ -1690,7 +1691,7 @@ I semafori non sono meccanismi di intercomunicazione diretta come quelli (pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del -codice (si ricordi quanto detto in \secref{sec:proc_race_cond}). +codice (si ricordi quanto detto in sez.~\ref{sec:proc_race_cond}). Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione @@ -1759,7 +1760,7 @@ permette di creare o ottenere l'identificatore di un insieme di semafori La funzione è del tutto analoga a \func{msgget}, solo che in questo caso restituisce l'identificatore di un insieme di semafori, in particolare è identico l'uso degli argomenti \param{key} e \param{flag}, per cui non -ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento +ripeteremo quanto detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. L'argomento \param{nsems} permette di specificare quanti semafori deve contenere l'insieme quando se ne richieda la creazione, e deve essere nullo quando si effettua una richiesta dell'identificatore di un insieme già esistente. @@ -1797,14 +1798,15 @@ semaforo all'uscita del processo. \end{figure} A ciascun insieme di semafori è associata una struttura \struct{semid\_ds}, -riportata in \figref{fig:ipc_semid_ds}.\footnote{non si sono riportati i campi - ad uso interno del kernel, che vedremo in \figref{fig:ipc_sem_schema}, che - dipendono dall'implementazione.} Come nel caso delle code di messaggi quando -si crea un nuovo insieme di semafori con \func{semget} questa struttura viene -inizializzata, in particolare il campo \var{sem\_perm} viene inizializzato -come illustrato in \secref{sec:ipc_sysv_access_control} (si ricordi che in -questo caso il permesso di scrittura è in realtà permesso di alterare il -semaforo), per quanto riguarda gli altri campi invece: +riportata in fig.~\ref{fig:ipc_semid_ds}.\footnote{non si sono riportati i + campi ad uso interno del kernel, che vedremo in + fig.~\ref{fig:ipc_sem_schema}, che dipendono dall'implementazione.} Come nel +caso delle code di messaggi quando si crea un nuovo insieme di semafori con +\func{semget} questa struttura viene inizializzata, in particolare il campo +\var{sem\_perm} viene inizializzato come illustrato in +sez.~\ref{sec:ipc_sysv_access_control} (si ricordi che in questo caso il +permesso di scrittura è in realtà permesso di alterare il semaforo), per +quanto riguarda gli altri campi invece: \begin{itemize*} \item il campo \var{sem\_nsems}, che esprime il numero di semafori nell'insieme, viene inizializzato al valore di \param{nsems}. @@ -1822,10 +1824,10 @@ Ciascun semaforo dell'insieme ormai è ridotta ai soli due primi membri, e gli altri vengono calcolati dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i valori associati ad un semaforo, restituiti dalle funzioni di controllo, e - citati dalle pagine di manuale.} è riportata in \figref{fig:ipc_sem}. Questa -struttura, non è accessibile in user space, ma i valori in essa specificati -possono essere letti in maniera indiretta, attraverso l'uso delle funzioni di -controllo. + citati dalle pagine di manuale.} è riportata in fig.~\ref{fig:ipc_sem}. +Questa struttura, non è accessibile in user space, ma i valori in essa +specificati possono essere letti in maniera indiretta, attraverso l'uso delle +funzioni di controllo. \begin{figure}[!htb] \footnotesize \centering @@ -1838,7 +1840,7 @@ controllo. \label{fig:ipc_sem} \end{figure} -I dati mantenuti nella struttura, ed elencati in \figref{fig:ipc_sem}, +I dati mantenuti nella struttura, ed elencati in fig.~\ref{fig:ipc_sem}, indicano rispettivamente: \begin{description*} \item[\var{semval}] il valore numerico del semaforo. @@ -1877,8 +1879,8 @@ indicano rispettivamente: Come per le code di messaggi anche per gli insiemi di semafori esistono una serie di limiti, i cui valori sono associati ad altrettante costanti, che si -sono riportate in \tabref{tab:ipc_sem_limits}. Alcuni di questi limiti sono al -solito accessibili e modificabili attraverso \func{sysctl} o scrivendo +sono riportate in tab.~\ref{tab:ipc_sem_limits}. Alcuni di questi limiti sono +al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo direttamente nel file \file{/proc/sys/kernel/sem}. La funzione che permette di effettuare le varie operazioni di controllo sui @@ -1933,7 +1935,7 @@ Qualora la funzione operi con quattro argomenti \param{arg} generico, che conterrà un dato diverso a seconda dell'azione richiesta; per unificare l'argomento esso deve essere passato come una \struct{semun}, la cui definizione, con i possibili valori che può assumere, è riportata in -\figref{fig:ipc_semun}. +fig.~\ref{fig:ipc_semun}. Come già accennato sia il comportamento della funzione che il numero di parametri con cui deve essere invocata, dipendono dal valore dell'argomento @@ -2018,7 +2020,7 @@ tutti i semafori il cui valore viene modificato. Il valore di ritorno della funzione in caso di successo dipende dall'operazione richiesta; per tutte le operazioni che richiedono quattro argomenti esso è sempre nullo, per le altre operazioni, elencate in -\tabref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto, +tab.~\ref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto, corrispondente al campo della struttura \struct{sem} indicato nella seconda colonna della tabella. @@ -2076,7 +2078,7 @@ effettivamente eseguite se e soltanto se Il contenuto di ciascuna operazione deve essere specificato attraverso una opportuna struttura \struct{sembuf} (la cui definizione è riportata in -\figref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di +fig.~\ref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di allocare in un opportuno vettore. La struttura permette di indicare il semaforo su cui operare, il tipo di operazione, ed un flag di controllo. Il campo \var{sem\_num} serve per indicare a quale semaforo dell'insieme fa @@ -2167,7 +2169,7 @@ una \func{exec} (altrimenti non si avrebbe ripristino). Tutto questo però ha un problema di fondo. Per capire di cosa si tratta occorre fare riferimento all'implementazione usata in Linux, che è riportata -in maniera semplificata nello schema di \figref{fig:ipc_sem_schema}. Si è +in maniera semplificata nello schema di fig.~\ref{fig:ipc_sem_schema}. Si è presa come riferimento l'architettura usata fino al kernel 2.2.x che è più semplice (ed illustrata in dettaglio in \cite{tlk}); nel kernel 2.4.x la struttura del \textit{SysV IPC} è stata modificata, ma le definizioni relative @@ -2234,7 +2236,7 @@ ripristino non Come esempio di uso dell'interfaccia dei semafori vediamo come implementare con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice in questione, contenuto nel file \file{Mutex.c} allegato ai sorgenti, è -riportato in \figref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per +riportato in fig.~\ref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per creare un insieme contenente un singolo semaforo, per il quale poi useremo un valore unitario per segnalare la disponibilità della risorsa, ed un valore nullo per segnalarne l'indisponibilità. @@ -2306,7 +2308,7 @@ non avrebbe pi considerata libera). Infine si tenga presente che usare \func{MutexRead} per controllare il valore dei mutex prima di proseguire in una operazione di sblocco non servirebbe comunque, dato che l'operazione non sarebbe atomica. -Vedremo in \secref{sec:ipc_lock_file} come sia possibile ottenere +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 file locking\index{file!locking}. @@ -2345,7 +2347,7 @@ ed il suo prototipo La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed identico è l'uso degli argomenti \param{key} e \param{flag} per cui non -ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento +ripeteremo quanto detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. L'argomento \param{size} specifica invece la dimensione, in byte, del segmento, che viene comunque arrotondata al multiplo superiore di \const{PAGE\_SIZE}. @@ -2379,11 +2381,11 @@ norma, significa insieme a dei semafori. \end{figure} A ciascun segmento di memoria condivisa è associata una struttura -\struct{shmid\_ds}, riportata in \figref{fig:ipc_shmid_ds}. Come nel caso +\struct{shmid\_ds}, riportata in fig.~\ref{fig:ipc_shmid_ds}. Come nel caso delle code di messaggi quando si crea un nuovo segmento di memoria condivisa con \func{shmget} questa struttura viene inizializzata, in particolare il campo \var{shm\_perm} viene inizializzato come illustrato in -\secref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte +sez.~\ref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte relativamente ai permessi di accesso; per quanto riguarda gli altri campi invece: \begin{itemize} @@ -2408,7 +2410,7 @@ di questi limiti sono al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo direttamente nei rispettivi file di \file{/proc/sys/kernel/}. -In \tabref{tab:ipc_shm_limits} si sono riportate le +In tab.~\ref{tab:ipc_shm_limits} si sono riportate le costanti simboliche associate a ciascuno di essi, il loro significato, i valori preimpostati, e, quando presente, il file in \file{/proc/sys/kernel/} che permettono di cambiarne il valore. @@ -2502,7 +2504,7 @@ corrispondente comportamento della funzione, sono i seguenti: \textit{memory locking}\index{memory locking}\footnote{impedisce cioè che la memoria usata per il segmento venga salvata su disco dal meccanismo della memoria virtuale\index{memoria virtuale}; si ricordi quanto trattato in - \secref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo + sez.~\ref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo l'amministratore può utilizzare questo comando. \item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento di memoria condivisa. Solo l'amministratore può utilizzare questo comando. @@ -2546,10 +2548,10 @@ il suo prototipo La funzione inserisce un segmento di memoria condivisa all'interno dello spazio di indirizzi del processo, in modo che questo possa accedervi direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in -\figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si -ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). In +fig.~\ref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si +ricordi quanto illustrato al proposito in sez.~\ref{sec:proc_mem_layout}). In particolare l'indirizzo finale del segmento dati (quello impostato da -\func{brk}, vedi \secref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga +\func{brk}, vedi sez.~\ref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga presente infine che la funzione ha successo anche se il segmento è stato marcato per la cancellazione. @@ -2611,7 +2613,7 @@ In caso di successo la funzione aggiorna anche i seguenti campi di aumentato di uno. \end{itemize*} -Come accennato in \secref{sec:proc_fork} un segmento di memoria condivisa +Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa agganciato ad un processo viene ereditato da un figlio attraverso una \func{fork}, dato che quest'ultimo riceve una copia dello spazio degli indirizzi del padre. Invece, dato che attraverso una \func{exec} viene @@ -2668,7 +2670,7 @@ viene tolta dallo spazio di indirizzi del processo. Come esempio di uso di queste funzioni vediamo come implementare una serie di funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in -\figref{fig:ipc_sysv_shm_func}. +fig.~\ref{fig:ipc_sysv_shm_func}. La prima funzione (\texttt{\small 3--16}) è \func{ShmCreate} che, data una chiave, crea il segmento di memoria condivisa restituendo il puntatore allo @@ -2710,7 +2712,7 @@ accessi. Per questo motivo, quando la comunicazione fra processi sequenziale, altri meccanismi come le pipe, le fifo o i socket, che non necessitano di sincronizzazione esplicita, sono da preferire. Essa diventa l'unico meccanismo possibile quando la comunicazione non è -sequenziale\footnote{come accennato in \secref{sec:ipc_sysv_mq} per la +sequenziale\footnote{come accennato in sez.~\ref{sec:ipc_sysv_mq} per la comunicazione non sequenziale si possono usare le code di messaggi, attraverso l'uso del campo \var{mtype}, ma solo se quest'ultima può essere effettuata in forma di messaggio.} o quando non può avvenire secondo una @@ -2734,7 +2736,7 @@ directory, link simbolici, file normali, ecc.) che saranno salvati in un segmento di memoria condivisa cui altri processi potranno accedere per ricavare la parte di informazione che interessa. -In \figref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del +In fig.~\ref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del corpo del programma server, insieme alle definizioni delle altre funzioni usate nel programma e delle variabili globali, omettendo tutto quello che riguarda la gestione delle opzioni e la stampa delle istruzioni di uso a @@ -2771,7 +2773,7 @@ immediatamente in caso di errore. Questa funzione serve anche per impostare la directory di lavoro del programma nella directory da tenere sotto controllo, in vista del successivo uso della funzione \func{daemon}.\footnote{si noti come si è potuta fare questa scelta, - nonostante le indicazioni illustrate in \secref{sec:sess_daemon}, per il + nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il particolare scopo del programma, che necessita comunque di restare all'interno di una directory.} Infine (\texttt{\small 27--29}) si installano i gestori per i vari segnali di terminazione che, avendo a che fare con un @@ -2792,8 +2794,8 @@ abbia successo. Con l'indirizzo \var{shmptr} cos accedere alla memoria condivisa, che, per come abbiamo lo abbiamo definito, sarà vista nella forma data da \struct{DirProp}. Infine (\texttt{\small 36--39}) utilizzando sempre la stessa chiave, si crea, tramite le funzioni -di interfaccia già descritte in \secref{sec:ipc_sysv_sem}, anche un mutex, che -utilizzeremo per regolare l'accesso alla memoria condivisa. +di interfaccia già descritte in sez.~\ref{sec:ipc_sysv_sem}, anche un mutex, +che utilizzeremo per regolare l'accesso alla memoria condivisa. \begin{figure}[!htb] \footnotesize \centering @@ -2825,13 +2827,13 @@ l'opzione \code{-p} con una \func{sleep}. Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si sia usata ancora una volta la funzione \func{DirScan}, già utilizzata (e -descritta in dettaglio) in \secref{sec:file_dir_read}, che ci permette di +descritta in dettaglio) in sez.~\ref{sec:file_dir_read}, che ci permette di effettuare la scansione delle voci della directory, chiamando per ciascuna di esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari. -Il codice di quest'ultima è riportato in \figref{fig:ipc_dirmonitor_sub}. Come -si vede la funzione (\texttt{\small 2--16}) è molto semplice e si limita a -chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da +Il codice di quest'ultima è riportato in fig.~\ref{fig:ipc_dirmonitor_sub}. +Come si vede la funzione (\texttt{\small 2--16}) è molto semplice e si limita +a chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari contatori nella memoria condivisa, cui accede grazie alla variabile globale \var{shmptr}. @@ -2842,14 +2844,14 @@ effettuare nessun controllo e si pu condivisa usando \var{shmptr} per riempire i campi della struttura \struct{DirProp}; così prima (\texttt{\small 6--7}) si sommano le dimensioni dei file ed il loro numero, poi, utilizzando le macro di -\tabref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce ne -sono per ciascun tipo. - -In \figref{fig:ipc_dirmonitor_sub} è riportato anche il codice (\texttt{\small - 17--23}) del gestore dei segnali di terminazione, usato per chiudere il -programma. Esso, oltre a provocare l'uscita del programma, si incarica anche -di cancellare tutti gli oggetti di intercomunicazione non più necessari. Per -questo anzitutto (\texttt{\small 19}) acquisisce il mutex con +tab.~\ref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce +ne sono per ciascun tipo. + +In fig.~\ref{fig:ipc_dirmonitor_sub} è riportato anche il codice +(\texttt{\small 17--23}) del gestore dei segnali di terminazione, usato per +chiudere il programma. Esso, oltre a provocare l'uscita del programma, si +incarica anche di cancellare tutti gli oggetti di intercomunicazione non più +necessari. Per questo anzitutto (\texttt{\small 19}) acquisisce il mutex con \func{MutexLock}, per evitare di operare mentre un client sta ancora leggendo i dati, dopo di che (\texttt{\small 20}) distacca e rimuove il segmento di memoria condivisa usando \func{ShmRemove}. Infine (\texttt{\small 21}) @@ -2867,7 +2869,7 @@ rimuove il mutex con \func{MutexRemove} ed esce (\texttt{\small 22}). \end{figure} Il codice del client usato per leggere le informazioni mantenute nella memoria -condivisa è riportato in \figref{fig:ipc_dirmonitor_client}. Al solito si è +condivisa è riportato in fig.~\ref{fig:ipc_dirmonitor_client}. Al solito si è omessa la sezione di gestione delle opzioni e la funzione che stampa a video le istruzioni; il codice completo è nei sorgenti allegati, nel file \file{ReadMonitor.c}. @@ -2966,7 +2968,7 @@ key msqid owner perms used-bytes messages %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta %% riferimento alle strutture con cui il kernel implementa i segmenti di memoria %% condivisa; uno schema semplificato della struttura è illustrato in -%% \figref{fig:ipc_shm_struct}. +%% fig.~\ref{fig:ipc_shm_struct}. %% \begin{figure}[htb] %% \centering @@ -2982,7 +2984,7 @@ key msqid owner perms used-bytes messages \section{Tecniche alternative} \label{sec:ipc_alternatives} -Come abbiamo detto in \secref{sec:ipc_sysv_generic}, e ripreso nella +Come abbiamo detto in sez.~\ref{sec:ipc_sysv_generic}, e ripreso nella descrizione dei singoli oggetti che ne fan parte, il \textit{SysV IPC} presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel capitolo 14.} Stevens ne effettua una accurata analisi (alcuni dei concetti @@ -2996,7 +2998,7 @@ alternative, che vogliamo riprendere in questa sezione. Le code di messaggi sono probabilmente il meno usato degli oggetti del \textit{SysV IPC}; esse infatti nacquero principalmente come meccanismo di comunicazione bidirezionale quando ancora le pipe erano unidirezionali; con la -disponibilità di \func{socketpair} (vedi \secref{sec:ipc_socketpair}) o +disponibilità di \func{socketpair} (vedi sez.~\ref{sec:ipc_socketpair}) o utilizzando una coppia di pipe, si può ottenere questo risultato senza incorrere nelle complicazioni introdotte dal \textit{SysV IPC}. @@ -3013,7 +3015,7 @@ relativamente poco diffuso. \label{sec:ipc_file_lock} \index{file!di lock|(} -Come illustrato in \secref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC} +Come illustrato in sez.~\ref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC} presentano una interfaccia inutilmente complessa e con alcuni difetti strutturali, per questo quando si ha una semplice esigenza di sincronizzazione per la quale basterebbe un semaforo binario (quello che abbiamo definito come @@ -3025,7 +3027,7 @@ La prima possibilit dei \textsl{file di lock} (per i quali esiste anche una opportuna directory, \file{/var/lock}, nel filesystem standard). Per questo si usa la caratteristica della funzione \func{open} (illustrata in -\secref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo +sez.~\ref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non toglie che in alcune implementazioni questa tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si è comunque soggetti alla possibilità di una race @@ -3037,7 +3039,7 @@ risorsa ad esso associata) mentre il rilascio si pu ad \func{unlink}. Un esempio dell'uso di questa funzione è mostrato dalle funzioni -\func{LockFile} ed \func{UnlockFile} riportate in \figref{fig:ipc_file_lock} +\func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock} (sono contenute in \file{LockFile.c}, un'altro dei sorgenti allegati alla guida) che permettono rispettivamente di creare e rimuovere un \textsl{file di lock}. Come si può notare entrambe le funzioni sono elementari; la prima @@ -3057,16 +3059,17 @@ cancella con \func{unlink}. \end{figure} Uno dei limiti di questa tecnica è che, come abbiamo già accennato in -\secref{sec:file_open}, questo comportamento di \func{open} può non funzionare -(la funzione viene eseguita, ma non è garantita l'atomicità dell'operazione) -se il filesystem su cui si va ad operare è su NFS; in tal caso si può adottare -una tecnica alternativa che prevede l'uso della \func{link} per creare come -\textsl{file di lock} un hard link ad un file esistente; se il link esiste già -e la funzione fallisce, significa che la risorsa è bloccata e potrà essere -sbloccata solo con un \func{unlink}, altrimenti il link è creato ed il lock -acquisito; il controllo e l'eventuale acquisizione sono atomici; la soluzione -funziona anche su NFS, ma ha un'altro difetto è che è quello di poterla usare -solo se si opera all'interno di uno stesso filesystem. +sez.~\ref{sec:file_open}, questo comportamento di \func{open} può non +funzionare (la funzione viene eseguita, ma non è garantita l'atomicità +dell'operazione) se il filesystem su cui si va ad operare è su NFS; in tal +caso si può adottare una tecnica alternativa che prevede l'uso della +\func{link} per creare come \textsl{file di lock} un hard link ad un file +esistente; se il link esiste già e la funzione fallisce, significa che la +risorsa è bloccata e potrà essere sbloccata solo con un \func{unlink}, +altrimenti il link è creato ed il lock acquisito; il controllo e l'eventuale +acquisizione sono atomici; la soluzione funziona anche su NFS, ma ha un'altro +difetto è che è quello di poterla usare solo se si opera all'interno di uno +stesso filesystem. Un generale comunque l'uso di un \textsl{file di lock} presenta parecchi problemi, che non lo rendono una alternativa praticabile per la @@ -3091,7 +3094,7 @@ disponibile.\index{file!di lock|)} Dato che i file di lock\index{file!di lock} presentano gli inconvenienti illustrati in precedenza, la tecnica alternativa di sincronizzazione più comune è quella di fare ricorso al \textit{file locking}\index{file!locking} -(trattato in \secref{sec:file_locking}) usando \func{fcntl} su un file creato +(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 @@ -3119,7 +3122,7 @@ leggermente pi \end{figure} Il codice delle varie funzioni usate per implementare un mutex utilizzando il -file locking\index{file!locking} è riportato in \figref{fig:ipc_flock_mutex}; +file locking\index{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. @@ -3153,7 +3156,7 @@ rilasciare il mutex. La funzione 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 file locking in semantica POSIX (si -riveda quanto detto \secref{sec:file_posix_lock}) solo il processo che ha +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 @@ -3183,8 +3186,8 @@ successo, ad indicare che il mutex Basandosi sulla semantica dei file lock POSIX valgono tutte le considerazioni relative al comportamento di questi ultimi fatte in -\secref{sec:file_posix_lock}; questo significa ad esempio che, al contrario di -quanto avveniva con l'interfaccia basata sui semafori, chiamate multiple a +sez.~\ref{sec:file_posix_lock}; questo significa ad esempio che, al contrario +di quanto avveniva con l'interfaccia basata sui semafori, chiamate multiple a \func{UnlockMutex} o \func{LockMutex} non si cumulano e non danno perciò nessun inconveniente. @@ -3198,7 +3201,7 @@ 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 \secref{sec:file_memory_map} abbiamo visto come sia possibile mappare il +In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il contenuto di un file nella memoria di un processo, e che, quando viene usato il flag \const{MAP\_SHARED}, le modifiche effettuate al contenuto del file vengono viste da tutti i processi che lo hanno mappato. Utilizzare questa @@ -3219,7 +3222,7 @@ il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una restano in memoria e possono essere riletti secondo le stesse modalità usate nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica più avanti, quando realizzeremo una nuova versione del monitor visto in -\secref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. +sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. @@ -3227,7 +3230,7 @@ pi \label{sec:ipc_posix} Per superare i numerosi problemi del \textit{SysV IPC}, evidenziati per i suoi -aspetti generali in coda a \secref{sec:ipc_sysv_generic} e per i singoli +aspetti generali in coda a sez.~\ref{sec:ipc_sysv_generic} e per i singoli oggetti nei paragrafi successivi, lo standard POSIX.1b ha introdotto dei nuovi meccanismi di comunicazione, che vanno sotto il nome di POSIX IPC, definendo una interfaccia completamente nuova, che tratteremo in questa sezione. @@ -3270,10 +3273,10 @@ implementazione.\footnote{tanto che Stevens in \cite{UNP2} cita questo caso quanto riguarda la memoria condivisa, che per quanto riguarda le code di messaggi, tutto viene creato usando come radici delle opportune directory (rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si -faccia riferimento a \secref{sec:ipc_posix_shm} e \secref{sec:ipc_posix_mq}) -ed i nomi specificati nelle relative funzioni sono considerati come un -pathname assoluto (comprendente eventuali sottodirectory) rispetto a queste -radici. +faccia riferimento a sez.~\ref{sec:ipc_posix_shm} e +sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni +sono considerati come un pathname assoluto (comprendente eventuali +sottodirectory) rispetto a queste radici. Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti nell'albero dei file, e possono essere maneggiati con le usuali funzioni e @@ -3287,9 +3290,9 @@ file normali. In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai permessi dei file, e il controllo di accesso segue esattamente la stessa -semantica (quella illustrata in \secref{sec:file_access_control}), invece di +semantica (quella illustrata in sez.~\ref{sec:file_access_control}), invece di quella particolare (si ricordi quanto visto in -\secref{sec:ipc_sysv_access_control}) usata per gli oggetti del SysV IPC. Per +sez.~\ref{sec:ipc_sysv_access_control}) usata per gli oggetti del SysV IPC. Per quanto riguarda l'attribuzione dell'utente e del gruppo proprietari dell'oggetto alla creazione di quest'ultimo essa viene effettuata secondo la semantica SysV (essi corrispondono cioè a userid e groupid effettivi del @@ -3379,7 +3382,7 @@ stesso oggetto, consentendo cos La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che possono essere specificati per \param{oflag}, che deve essere specificato come maschera binaria; i valori possibili per i vari bit sono quelli visti in -\tabref{tab:file_open_flags} dei quali però \func{mq\_open} riconosce solo i +tab.~\ref{tab:file_open_flags} dei quali però \func{mq\_open} riconosce solo i seguenti: \begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}} \item[\const{O\_RDONLY}] Apre la coda solo per la ricezione di messaggi. Il @@ -3415,7 +3418,7 @@ solo i permessi di lettura e scrittura. Oltre ai permessi di creazione possono essere specificati anche gli attributi specifici della coda tramite l'argomento \param{attr}; quest'ultimo è un puntatore ad una apposita struttura \struct{mq\_attr}, la cui definizione è riportata in -\figref{fig:ipc_mq_attr}. +fig.~\ref{fig:ipc_mq_attr}. \begin{figure}[!htb] \footnotesize \centering @@ -3677,9 +3680,9 @@ 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 \figref{fig:file_sigevent}) introdotta dallo +\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 \secref{sec:file_asyncronous_io} a proposito dell'uso +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 @@ -3689,11 +3692,11 @@ essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato 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 -\figref{fig:sig_sigval}) che permette di restituire al gestore del segnale un +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 \secref{sec:sig_real_time} a proposito dei segnali + 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 -\secref{sec:sig_sigaction}. +sez.~\ref{sec:sig_sigaction}. La funzione registra il processo chiamante per la notifica se \param{notification} punta ad una struttura \struct{sigevent} opportunamente @@ -3727,14 +3730,14 @@ 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 -\figref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al +fig.~\ref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al valore del \acr{pid} del processo che ha emesso il segnale, \var{si\_uid} all'userid effettivo, \var{si\_code} a \const{SI\_MESGQ}, e \var{si\_errno} a 0. Questo ci dice che, se si effettua la ricezione dei messaggi usando esclusivamente il meccanismo di notifica, è possibile ottenere le informazioni sul processo che ha inserito un messaggio usando un gestore per il segnale in forma estesa\footnote{di nuovo si faccia riferimento a quanto detto al - proposito in \secref{sec:sig_sigaction} e \secref{sec:sig_real_time}.} + proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}.} @@ -3749,7 +3752,7 @@ implementa solo a livello di thread e non di processi.\footnote{questo sincronizzazione fra processi diversi.} Esiste però anche una libreria realizzata da Konstantin Knizhnik, che reimplementa l'interfaccia POSIX usando i semafori di SysV IPC, e che non vale comunque la pena di usare visto che i -problemi sottolineati in \secref{sec:ipc_sysv_sem} rimangono, anche se +problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem} rimangono, anche se mascherati. In realtà a partire dal kernel 2.5.7 è stato introdotto un meccanismo di @@ -3815,7 +3818,7 @@ Apre un segmento di memoria condivisa. \end{prototype} La funzione apre un segmento di memoria condivisa identificato dal nome -\param{name}. Come già spiegato in \secref{sec:ipc_posix_generic} questo nome +\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo nome può essere specificato in forma standard solo facendolo iniziare per \file{/} e senza ulteriori \file{/}, Linux supporta comunque nomi generici, che verranno intepretati prendendo come radice \file{/dev/shm}.\footnote{occorre @@ -3827,8 +3830,8 @@ La funzione possono essere specificati per \param{oflag}, che deve essere specificato come maschera binaria comprendente almeno uno dei due valori \const{O\_RDONLY} e \const{O\_RDWR}; i valori possibili per i vari bit sono quelli visti in -\tabref{tab:file_open_flags} dei quali però \func{shm\_open} riconosce solo i -seguenti: +tab.~\ref{tab:file_open_flags} dei quali però \func{shm\_open} riconosce solo +i seguenti: \begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}} \item[\const{O\_RDONLY}] Apre il file descriptor associato al segmento di memoria condivisa per l'accesso in sola lettura. @@ -3849,7 +3852,7 @@ In caso di successo la funzione restituisce un file descriptor associato al segmento di memoria condiviso con le stesse modalità di \func{open}\footnote{in realtà, come accennato, \func{shm\_open} è un semplice wrapper per \func{open}, usare direttamente quest'ultima avrebbe lo stesso - effetto.} viste in \secref{sec:file_open}; in particolare viene impostato + effetto.} viste in sez.~\ref{sec:file_open}; in particolare viene 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 di dati, essi sono associati allo stesso inode). @@ -3861,8 +3864,8 @@ Quando il nome non esiste il segmento pu \const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file) lunghezza nulla. Dato che un segmento di lunghezza nulla è di scarsa utilità, per impostarne la dimensione si deve usare \func{ftruncate} (vedi -\secref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}. Si -tenga presente che una volta chiamata \func{mmap} si può chiudere il file +sez.~\ref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}. +Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file descriptor (con \func{close}), senza che la mappatura ne risenta. @@ -3901,8 +3904,8 @@ descriptor che fa riferimento ad un segmento distinto da eventuali precedenti. Come esempio per l'uso di queste funzioni vediamo come è possibile riscrivere una interfaccia semplificata analoga a quella vista in -\secref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il -codice, riportato in \figref{fig:ipc_posix_shmmem}, è sempre contenuto nel +fig.~\ref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il +codice, riportato in fig.~\ref{fig:ipc_posix_shmmem}, è sempre contenuto nel file \file{SharedMem.c} dei sorgenti allegati. La prima funzione (\texttt{\small 1--24}) è \func{CreateShm} che, dato un nome