Aggiunte sugli IPC generici (controllo di accesso) e messa una vecchia
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index bdbdf2c13d9068e85617b49f2ff16cc321cf416e..261de58ac9e57599f89f96c98bc551b1af6d8141 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -6,26 +6,24 @@ Uno degli aspetti fondamentali della programmazione in un sistema unix-like 
 la comunicazione fra processi. In questo capitolo affronteremo solo i
 meccanismi più elementari che permettono di mettere in comunicazione processi
 diversi, come quelli tradizionali che coinvolgono \textit{pipe} e
-\textit{fifo} e i meccanismi di intercomunicazione di System V.
+\textit{fifo} e i meccanismi di intercomunicazione di System V e quelli POSIX.
 
 Tralasceremo invece tutte le problematiche relative alla comunicazione
 attraverso la rete (e le relative interfacce) che saranno affrontate in
-dettaglio in un secondo tempo.  Non affronteremo invece meccanismi più
+dettaglio in un secondo tempo.  Non affronteremo neanche meccanismi più
 complessi ed evoluti come le RPC (\textit{Remote Procedure Calls}) e CORBA
 (\textit{Common Object Request Brocker Architecture}) che in genere sono
 implementati con un ulteriore livello sopra i meccanismi elementari.
 
 
-
 \section{La comunicazione fra processi tradizionale}
 \label{sec:ipc_unix}
 
-Il primo meccanismo di comunicazione fra processi usato dai sistemi unix-like,
-e quello che viene correntemente usato di più, è quello delle \textit{pipe},
-che sono una delle caratteristiche peculiari del sistema, in particolar modo
-dell'interfaccia a linea di comando. In questa sezione descriveremo le sue
-basi, le funzioni che ne gestiscono l'uso e le varie forme in cui si è
-evoluto.
+Il primo meccanismo di comunicazione fra processi introdotto nei sistemi Unix,
+è quello delle cosiddette \textit{pipe}; esse costituiscono una delle
+caratteristiche peculiari del sistema, in particolar modo dell'interfaccia a
+linea di comando. In questa sezione descriveremo le sue basi, le funzioni che
+ne gestiscono l'uso e le varie forme in cui si è evoluto.
 
 
 \subsection{Le \textit{pipe} standard}
@@ -33,39 +31,36 @@ evoluto.
 
 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 uno speciale tipo di file descriptor, più precisamente una coppia
-di file descriptor,\footnote{si tenga presente che le pipe sono oggetti creati
-  dal kernel e non risiedono su disco.}  su cui da una parte si scrive e da
-un'altra si legge. Si viene così a costituire un canale di comunicazione
-tramite i due file descriptor, nella forma di un \textsl{tubo} (da cui il
-nome) in cui in genere un processo immette dati che poi arriveranno ad un
-altro.
-
-La funzione che permette di creare una pipe è appunto \func{pipe}; il suo
-prototipo è:
+sostanza di una 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
+due file descriptor, nella forma di un \textsl{tubo} (da cui il nome)
+attraverso cui fluiscono i dati.
+
+La funzione che permette di creare questa speciale coppia di file descriptor
+associati ad una \textit{pipe} è appunto \func{pipe}, ed il suo prototipo è:
 \begin{prototype}{unistd.h}
 {int pipe(int filedes[2])} 
   
-Crea una coppia di file descriptor associati ad una pipe.
+Crea una coppia di file descriptor associati ad una \textit{pipe}.
   
   \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
     errore, nel qual caso \var{errno} potrà assumere i valori \macro{EMFILE},
     \macro{ENFILE} e \macro{EFAULT}.}
 \end{prototype}
 
-La funzione restituisce una coppia di file descriptor nell'array
-\param{filedes}; il primo aperto in lettura ed il secondo in scrittura. Il
-concetto di funzionamento di una pipe è relativamente semplice, quello che si
+La funzione restituisce la coppia di file descriptor nell'array
+\param{filedes}; il primo è aperto in lettura ed il secondo in scrittura. Come
+accennato concetto di funzionamento di una pipe è semplice: quello che si
 scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
-nel file descriptor aperto in lettura, da cui può essere riletto.
-
-I file descriptor infatti non sono connessi a nessun file reale, ma ad un
-buffer nel kernel, la cui dimensione è specificata dalla costante
-\macro{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 capi della pipe, associati a ciascun file
-descriptor, con le frecce che indicano la direzione del flusso dei dati
-attraverso la pipe.
+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 dalla costante \macro{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
+capi della pipe, associati a ciascun file descriptor, con le frecce che
+indicano la direzione del flusso dei dati.
 
 \begin{figure}[htb]
   \centering
@@ -74,12 +69,12 @@ attraverso la pipe.
   \label{fig:ipc_pipe_singular}
 \end{figure}
 
-Chiaramente creare una pipe all'interno di un processo non serve a niente; se
-però ricordiamo quanto esposto in \secref{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
+Chiaramente creare una pipe all'interno di un singolo processo non serve a
+niente; se però ricordiamo quanto esposto in \secref{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
 capo della pipe, l'altro può leggere.
 
@@ -92,16 +87,17 @@ capo della pipe, l'altro pu
 \end{figure}
 
 Tutto ciò ci mostra come sia immediato realizzare un meccanismo di
-comunicazione fra processi attraverso una pipe, utilizzando le ordinarie
-proprietà dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
+comunicazione fra processi attraverso una pipe, utilizzando le proprietà
+ordinarie dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
   in \cite{APUE} riporta come limite anche il fatto che la comunicazione è
-  unidirezionale, in realtà questo è un limite facilmente superabile usando
+  unidirezionale, ma in realtà questo è un limite facilmente superabile usando
   una coppia di pipe.} limite nell'uso delle pipe. È necessario infatti che i
 processi possano condividere i file descriptor della pipe, e per questo essi
-devono comunque derivare da uno stesso processo padre che ha aperto la pipe,
-o, più comunemente, essere nella relazione padre/figlio.
+devono comunque essere \textsl{parenti} (dall'inglese \textit{siblings}), cioè
+o derivare da uno stesso processo padre in cui è avvenuta la creazione della
+pipe, o, più comunemente, essere nella relazione padre/figlio.
 
-A differenza di quanto avviene con i file normali la lettura da una pipe può
+A differenza di quanto avviene con i file normali, la lettura da una pipe può
 essere bloccante (qualora non siano presenti dati), inoltre se si legge da una
 pipe il cui capo in scrittura è stato chiuso, si avrà la ricezione di un EOF
 (vale a dire che la funzione \func{read} ritornerà restituendo 0).  Se invece
@@ -122,14 +118,14 @@ da altri processi.
 \subsection{Un esempio dell'uso delle pipe}
 \label{sec:ipc_pipe_use}
 
-Per capire meglio il funzionamento di una pipe faremo un esempio di quello che
+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. Realizzaremo il programma nella forma di 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 parametro di input.
+di un'altro. Realizzeremo il programma di esempio nella forma di 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 parametro di input.
 
 Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
 delle caratteristiche specifiche, esso infatti non viene lanciato da una
@@ -143,13 +139,13 @@ che ne descrive il mime-type) sullo standard output, in modo che il web-server
 possa reinviarlo al browser che ha effettuato la richiesta, che in questo modo
 è in grado di visualizzarlo opportunamente.
 
-Per fare questo useremo in sequenza i programmi \cmd{barcode} e \cmd{gs}, il
-primo infatti è in grado di generare immagini postscript di 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 direzione del flusso
-dei dati è data dalle frecce continue.
+Per realizzare quanto voluto useremo in sequenza i programmi \cmd{barcode} e
+\cmd{gs}, il primo infatti è in grado di generare immagini postscript di
+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
+direzione del flusso dei dati è data dalle frecce continue.
 
 \begin{figure}[htb]
   \centering
@@ -168,7 +164,8 @@ 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.
+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
@@ -187,7 +184,7 @@ nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 int main(int argc, char *argv[], char *envp[])
 {
     ...
-    /* create two pipes to handle process communication */
+    /* create two pipes, pipein and pipeout, to handle communication */
     if ( (retval = pipe(pipein)) ) {
         WriteMess("input pipe creation error");
         exit(0);        
@@ -207,14 +204,14 @@ int main(int argc, char *argv[], char *envp[])
         dup2(pipein[0], STDIN_FILENO);   /* remap stdin to pipe read end */
         close(pipeout[0]);
         dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */
-        execlp("barcode", "barcode", size, NULL); //"-o", "-",  NULL);
+        execlp("barcode", "barcode", size, NULL);
     } 
     close(pipein[0]);                    /* close input side of input pipe */
     write(pipein[1], argv[1], strlen(argv[1]));  /* write parameter to pipe */
     close(pipein[1]);                    /* closing write end */
     waitpid(pid, NULL, 0);               /* wait child completion */
     /* Second fork: use child to run ghostscript */
-    if ( (pid = fork()) == -1) {          /* on error exit */
+    if ( (pid = fork()) == -1) {
         WriteMess("child creation error");
         exit(0);
     }
@@ -243,7 +240,7 @@ La prima operazione del programma (\texttt{\small 4--12}) 
 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
+richiesta.\footnote{la funzione \func{WriteMess} non è riportata in
   \secref{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
@@ -374,26 +371,27 @@ approccio diverso. Una possibilit
 programma, \cmd{epstopsf}, per convertire in PDF un file EPS (che può essere
 generato da \cmd{barcode} utilizzando lo switch \cmd{-E}).  Utilizzando un PDF
 al posto di un EPS \cmd{gs} esegue la conversione rispettando le dimensioni
-originarie del codice a barre e produce un JPEG delle dimensioni adeguate.
-
-Questo però ci porta a scontrarci con una caratteristica peculiare delle pipe,
-che a prima vista non è evidente. Per poter effettuare la conversione di un
-PDF infatti è necessario, per la struttura del formato, dover eseguire delle
-\func{lseek} sul file da convertire; se si esegue \cmd{gs} su un file normale
-non ci sono problemi, ma una pipe però è rigidamente sequenziale, ed il
-tentativo di eseguire detta operazione su una pipe comporta l'immediato
-fallimento con un errore di \macro{ESPIPE}.  Questo ci dice che in generale la
-concatenazione di vari programmi funzionerà soltanto quando tutti prevedono
-una lettura sequenziale del loro input.
-
-Per questo motivo si è dovuto utilizzare una strada diversa, che prevede la
-conversione attraverso \cmd{gs} del PS in un altro formato intermedio, il
-PPM,\footnote{il \textit{Portable PixMap file format} è un formato usato
-  spesso come formato intermedio per effettuare conversioni, è estremamente
-  inefficiente, ma molto facile da manipolare dato che usa caratteri ASCII per
-  memorizzare le immagini.} dal quale poi si può ottenere un'immagine di
-dimensioni corrette attraverso vari programmi di manipolazione (\cmd{pnmcrop},
-\cmd{pnmmargin}) che può essere infine trasformata in PNG (con \cmd{pnm2png}).
+originarie del codice a barre e produce un JPEG di dimensioni corrette.
+
+Questo approccio però non funziona, per via di una delle caratteristiche
+principali delle pipe. Per poter effettuare la conversione di un PDF infatti è
+necessario, per la struttura del formato, potersi spostare (con \func{lseek})
+all'interno del file da convertire; se si eseguela conversione con \cmd{gs} su
+un file regolare non ci sono problemi, una pipe però è rigidamente
+sequenziale, e l'uso di \func{lseek} su di essa fallisce sempre con un errore
+di \macro{ESPIPE}, rendendo impossibile la conversione.  Questo ci dice che in
+generale la concatenazione di vari programmi funzionerà soltanto quando tutti
+prevedono una lettura sequenziale del loro input.
+
+Per questo motivo si è dovuto utilizzare un procedimento diverso, eseguendo
+prima la conversione (sempre con \cmd{gs}) del PS in un altro formato
+intermedio, il PPM,\footnote{il \textit{Portable PixMap file format} è un
+  formato usato spesso come formato intermedio per effettuare conversioni, è
+  infatti molto facile da manipolare, dato che usa caratteri ASCII per
+  memorizzare le immagini, anche se per questo è estremamente inefficiente.}
+dal quale poi si può ottenere un'immagine di dimensioni corrette attraverso
+vari programmi di manipolazione (\cmd{pnmcrop}, \cmd{pnmmargin}) che può
+essere infine trasformata in PNG (con \cmd{pnm2png}).
 
 In questo caso però occorre eseguire in sequenza ben quattro comandi diversi,
 inviando l'output di ciascuno all'input del successivo, per poi ottenere il
@@ -472,7 +470,7 @@ Alla fine tutto quello che resta da fare 
 primo processo della catena, che nel caso è \cmd{barcode}, e scrivere
 (\texttt{\small 23}) la stringa del codice a barre sulla pipe, che è collegata
 al suo standard input, infine si può eseguire (\texttt{\small 24--27}) un
-ciclo, che chiuda, nell'ordine inverso rispetto a quello in cui le si sono
+ciclo che chiuda, nell'ordine inverso rispetto a quello in cui le si sono
 create, tutte le pipe create con \func{pclose}.
 
 
@@ -512,52 +510,400 @@ nel qual caso l'apertura del capo in lettura avr
 l'altro capo è aperto, mentre l'apertura del capo in scrittura restituirà
 l'errore di \macro{ENXIO} fintanto che non verrà aperto il capo in lettura.
 
-In Linux\footnote{lo standard POSIX lascia indefinito questo comportamento.} è
-possibile aprire le fifo anche in lettura/scrittura, operazione che avrà
-sempre successo immediato qualunque sia la modalità di apertura (bloccante e
-non bloccante); questo può essere utilizzato per aprire comunque una fifo in
-scrittura anche se non ci sono ancora processi il lettura; è possibile anche
-usare la fifo all'interno di un solo processo, nel qual caso però occorre
-stare molto attenti alla possibili deadlock.\footnote{se si cerca di leggere
-  da una fifo che non contiene dati si avrà un deadlock immediato, dato che il
-  processo si blocca e non potrà quindi mai eseguire le funzioni di
-  scrittura.}
+In Linux è possibile aprire le fifo anche in lettura/scrittura,\footnote{lo
+  standard POSIX lascia indefinito il comportamento in questo caso.}
+operazione che avrà sempre successo immediato qualunque sia la modalità di
+apertura (bloccante e non bloccante); questo può essere utilizzato per aprire
+comunque una fifo in scrittura anche se non ci sono ancora processi il
+lettura; è possibile anche usare la fifo all'interno di un solo processo, nel
+qual caso però occorre stare molto attenti alla possibili
+deadlock.\footnote{se si cerca di leggere da una fifo che non contiene dati si
+  avrà un deadlock immediato, dato che il processo si blocca e non potrà
+  quindi mai eseguire le funzioni di scrittura.}
+
+Per la loro caratteristica di essere accessibili attraverso il filesystem, è
+piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle
+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 \macro{PIPE\_BUF} (si ricordi quanto detto in
+\secref{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:
+\begin{itemize}
+\item Da parte dei comandi di shell, per evitare la creazione di file
+  temporanei quando si devono inviare i dati di uscita di un processo
+  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}).
+\end{itemize}
+
+Nel primo caso quello che si fa è creare tante fifo, da usare come standard
+input, quanti sono i processi a cui i vogliono inviare i dati, questi ultimi
+saranno stati posti in esecuzione ridirigendo lo standard input dalle fifo, si
+potrà poi eseguire il processo che fornisce l'output replicando quest'ultimo,
+con il comando \cmd{tee}, sulle varie fifo.
+
+Il secondo caso è relativamente semplice qualora si debba comunicare con un
+processo alla volta (nel qual caso basta usare due fifo, una per leggere ed
+una per scrivere), le cose diventano invece molto più complesse quando si
+vuole effettuare una comunicazione fra il server ed un numero imprecisato di
+client; se il primo infatti può ricevere le richieste attraverso una fifo
+``nota'', per le risposte non si può fare altrettanto, dato che, per 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 da Stevens in \cite{APUE}, in cui le risposte vengono inviate su
+fifo temporanee identificate dal \acr{pid} dei client, ma in ogni caso il
+sistema è macchinoso e continua ad avere vari inconvenienti\footnote{lo stesso
+  Stevens nota come sia impossibile per il server sapere se un client è andato
+  in crash, con la possibilità di far restare le fifo temporanee sul
+  filesystem, come sia necessario intercettare \macro{SIGPIPE} dato che un
+  client può terminare dopo aver fatto una richiesta, ma prima che la risposta
+  sia inviata, e come occorra gestire il caso in cui non ci sono client attivi
+  (e la lettura dalla fifo nota restituisca al serve un end-of-file.}; in
+generale infatti l'interfaccia delle 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.
+
 
 
-  
 \section{La comunicazione fra processi di System V}
 \label{sec:ipc_sysv}
 
-Benché le pipe (e le fifo) siano ancora ampiamente usate, esse presentano
-numerosi limiti, il principale dei quali è che il meccanismo di comunicazione
-è rigidamente sequenziale; una situazione in cui un processo scrive qualcosa
-che molti altri devono poter leggere non può essere implementata con una pipe.
+Benché le pipe e le fifo siano ancora ampiamente usate, esse scontano il
+limite fondamentale che il meccanismo di comunicazione che forniscono è
+rigidamente sequenziale: una situazione in cui un processo scrive qualcosa che
+molti altri devono poter leggere non può essere implementata con una pipe.
 
-Per superarne i vari limiti, nello sviluppo di System V vennero introdotti una
-serie di nuovi oggetti di comunicazione e relative interfacce id
-programmazione che garantissero una maggiore flessibilità; in questa sezione
-esamineremo quello che viene ormai chiamato il \textsl{Sistema di
-  comunicazione inter-processo} di System V , più comunemente noto come
+Per questo nello sviluppo di System V vennero introdotti una serie di nuovi
+oggetti per la comunicazione fra processi ed una nuova interfaccia di
+programmazione, che fossero in grado di garantire una maggiore flessibilità.
+In questa sezione esamineremo come Linux supporta quello che viene ormai
+chiamato il \textsl{Sistema di comunicazione inter-processo} di System V, o
 \textit{System V IPC (Inter-Process Comunication)}.
+
+
+
+\subsection{Considerazioni generali}
+\label{sec:ipc_sysv_generic}
+
+La principale caratteristica del sistema di IPC di System V è quella di essere
+basato su oggetti permanenti che risiedono nel kernel. Questi, a differenza di
+quanto avviene per i file descriptor, non mantengono un contatore dei
+riferimenti, e non vengono cancellati dal sistema una volta che non sono più
+in uso. Questo comporta che, al contrario di quanto avviene per pipe e fifo,
+la memoria allocata per questi oggetti non viene rilasciata automaticamente,
+ed essi devono essere cancellati esplicitamente, altrimenti resteranno attivi
+fino al riavvio del sistema.
+
+Gli oggetti usati nel System V IPC vengono creati direttamente dal kernel, e
+sono accessibili solo specificando il relativo \textsl{identificatore}. Questo
+è il numero progressivo che il kernel assengna a ciascuno di essi quanto
+vengono creati (il prodedimento è simile a quello con cui si assegna il
+\acr{pid} ai processi). 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à, ne utilizzare un qualche valore statico, si pone perciò
+il problema di come processi diversi possono accedere allo stesso oggetto.
+
+Per risolvere il problema il kernel associa a ciascun oggetto una struttura
+\var{ipc\_perm}; questa contiene una \textsl{chiave}, identificata da una
+variabile del tipo primitivo \type{key\_t}, che viene specificata in fase di
+creazione e tramite la quale è possibile ricavare l'identificatore. La
+struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
+contiene anche le varie proprietà associate all'oggetto. 
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm ]{}
+struct ipc_perm
+{
+    key_t key;                        /* Key.  */
+    uid_t uid;                        /* Owner's user ID.  */
+    gid_t gid;                        /* Owner's group ID.  */
+    uid_t cuid;                       /* Creator's user ID.  */
+    gid_t cgid;                       /* Creator's group ID.  */
+    unsigned short int mode;          /* Read/write permission.  */
+    unsigned short int seq;           /* Sequence number.  */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{ipc\_perm}, come definita in \file{sys/ipc.h}.} 
+  \label{fig:ipc_ipc_perm}
+\end{figure}
+
+Usando la stessa chiave due processi diversi possono ricavare l'identificatore
+associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è
+come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
+sono \textsl{parenti} la soluzione è relativamente semplice, in tal caso
+infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un
+nuovo oggetto nel processo padre, l'idenficatore così ottenuto sarà
+disponibile in tutti i figli, e potrà essere passato come parametro attraverso
+una \func{exec}.
+
+Però quando i processi non sono \textsl{parenti} (come capita tutte le volte
+che si ha a che fare con un sistema client-server) tutto questo non è
+possibile; si potebbe comunque salvare l'identificatore su un file noto, ma
+questo ovviamente comporta lo svantaggio di doverselo andare a rileggere.  Una
+alternativa più efficace è quella che i programmi usino un valore comune per
+la chiave (che ad esempio può essere dichiarato in un header comune), ma c'è
+sempre il rischio che questa chiave possa essere stata già utilizzata da
+qualcun altro.  Dato che non esiste una convenzione su come assegnare queste
+chiavi in maniera univoca l'interfaccia mette a disposizione una funzione,
+\func{ftok}, che permette di ottenere una chiave specificando il nome di un
+file ed un numero di versione; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  
+  \funcdecl{key\_t ftok(const char *pathname, int proj\_id)}
+  
+  Restituisce una chiave per identificare un oggetto del System V IPC.
+  
+  \bodydesc{La funzione restituisce la chiave in caso di successo e -1
+  altrimenti, nel qual caso \var{errno} viene settata ad uno dei possibili
+  codici di errore di \func{stat}.}
+\end{functions}
+
+La funzione determina un valore della chiave sulla base di \param{pathname},
+che deve specificare il pathname di un file effettivamente esistente e di un
+numero di progetto \param{proj\_id)}, che di norma viene specificato come
+carattere, dato che ne vengono utilizzati solo gli 8 bit meno
+significativi.\footnote{nelle libc4 e libc5, come avviene in SunOS,
+  l'argomento \param{proj\_id)} è dichiarato tipo \ctyp{char}, le \acr{glibc}
+  han modificato il prototipo, ma vengono lo stesso utilizzati gli 8 bit meno
+  significativi.}
+
+Il problema è che anche così non c'è la sicurezza che il valore della chiave
+sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
+con i 16 bit meno significativi 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 device su cui è il file. Diventa
+perciò relativamente facile ottenere delle collisioni, specie se i file sono
+su dispositivi con lo stesso \textit{minor number}, come \file{/dev/hda1} e
+\file{/dev/sda1}.
+
+In genere quello che si fa è utilizzare un file comune usato dai programmi che
+devono comunicare (ad esempio un haeder, o uno dei programmi che devono usare
+l'oggetto in questione), utilizzando il numero di progetto per ottere le
+chiavi che interessano. In ogni caso occorre sempre controllare, prima di
+creare un oggetto, che la chiave non sia già stata utilizzata. Se questo va
+bene in fase di creazione, le cose possono complicarsi per i programmi che
+devono solo accedere, in quanto, a parte gli eventuali controlli sugli altri
+attributi di \var{ipc\_perm}, non esiste una modalità semplice per essere
+sicuri della validità di una certa chiave.
+
+Questo è, insieme al fatto che gli oggetti sono permanenti e devono essere
+cancellati esplicitamente, il principale problema del sistema di IPC di System
+V. Non esiste infatti una modalità chiara per 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}.
+
+
+\subsection{Il controllo di accesso}
+\label{sec:ipc_sysv_access_control}
+
+Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in
+\var{ipc\_perm} ulteriori informazioni, come gli identificatori del creatore
+(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, simile
+a quello che si ha per i file (vedi \secref{sec:file_perm_overview}).  
+
+Benché il controllo di accesso relativo agli oggetti di intercomunicazione sia
+molto simile a quello dei file, restano delle importanti differenze. La prima
+è che il permesso di esecuzione non esiste (e viene ignorato), per cui si può
+parlare solo di permessi di lettura e scrittura (nel caso dei semafori poi
+quest'ultimo è più propriamente il permesso di modificarne lo stato). 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 simboliche ivi definite occorrerà includere il file
+  \file{sys/stat.h}, alcuni sistemi definiscono le costanti \macro{MSG\_R}
+  (\texttt{0400}) e \macro{MSG\_W} (\texttt{0200}) per indicare i permessi
+  base di lettura e scrittura per il proprietario, da utilizzare, con gli
+  opportuni shift, pure per il gruppo e gli altri, in Linux, visto la loro
+  scarsa utilità, queste costanti non sono definite.} e come per i file
+definiscono gli accessi per il proprietario, il suo gruppo e tutti gli altri.
+
+Si tenga presente che per gli oggetti di IPC han senso solo i permessi di
+lettura e scrittura, quelli di esecuzione vengono ignorati. Quando l'oggetto
+viene creato i campi \var{cuid} e \var{uid} di \var{ipc\_perm} ed i campi
+\var{cgid} e \var{gid} vengono settati rispettivamente al valore dell'userid e
+del groupid effettivo del processo che ha chiamato la funzione, ma mentre i
+campi \var{uid} e \var{gid} possono essere cambiati, \var{cuid} e \var{cgid}
+restano sempre gli stessi.
+
+Il controllo di accesso è effettuato a due livelli. Il primo è nelle funzioni
+che richiedono l'identificatore di un oggetto data la chiave, che specificano
+tutte un argomento \param{flag}.  In tal caso quando viene effettuata la
+ricerca di una chiave, se \param{flag} specifica dei permessi, questi vengono
+controllati e l'identificatore viene restituito solo se essi corrispondono a
+quelli dell'oggetto. Se sono presenti dei permessi non presenti in \var{mode}
+l'accesso sarà invece negato. Questo però è di utilità indicativa, dato che è
+sempre possibile specificare un valore nullo per \param{flag}, nel qual caso
+il controllo avrà sempre successo.
+
+Il secondo livello è quello delle varie funzioni che accedono (in lettura o
+scrittura) all'oggetto. In tal caso lo schema dei controlli è simile a quello
+dei file, ed avviene secondo questa sequenza:
+\begin{enumerate}
+\item se il processo ha i privilegi di amministatore l'accesso è sempre
+  consentito. 
+\item se l'userid effettivo del processo corrisponde o al valore del campo
+  \var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario
+  in \var{mode} è appropriato\footnote{per appropriato si intende che è
+    settato il permesso di scrittura per le operazioni di scrittura e quello
+    di lettura per le operazioni di lettura.} l'accesso è consentito.
+\item se il groupid effettivo del processo corrisponde o al
+  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 
+\end{enumerate}
+
+
 
 \subsection{Code di messaggi}
-\label{sec:ipc_messque}
+\label{sec:ipc_sysv_mq}
 
 Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
-messaggi.
+messaggi.  Le code di messaggi sono oggetti analoghi alle pipe o alle fifo,
+anche se la loro struttura è diversa. La funzione che permette di ottenerne
+una è \func{msgget} ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+  
+  \funcdecl{int msgget(key\_t key, int flag)}
+  
+  Restituisce l'identificatore di una cosa di messaggi.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} viene settato ad uno dei
+    valori: 
+  \begin{errlist}
+  \item[\macro{EACCES}] Il processo chiamante non ha i provilegi per accedere
+  alla coda richiesta.  
+  \item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
+  esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}. 
+  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+  \item[\macro{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
+    di messaggi specificando una chiave che non esiste e \macro{IPC\_CREAT}
+    non era specificato.
+  \item[\macro{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
+    stato il limite massimo del sistema.
+  \end{errlist}
+  ed inoltre \macro{ENOMEM}.
+}
+\end{functions}
+
+Le funzione (come le analoghe che si usano per gli altri oggetti) serve sia a
+ottenere l'identificatore di una coda di messaggi esistente, che a crearne una
+nuova. L'argomento \param{key} specifica la chiave che è associata
+all'oggetto, eccetto il caso in cui si specifichi il valore
+\macro{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
+associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
+farvi riferimento solo attraverso l'identificatore.
+
+Se invece si specifica un valore diverso da \macro{IPC\_PRIVATE}\footnote{in
+  Linux questo significa un valore diverso da zero.} l'effetto della funzione
+dipende dal valore di \param{flag}, se questo è nullo la funzione si limita ad
+effettuare una ricerca sugli oggetti esistenti, restituendo l'identificatore
+se trova una corrispondenza, o fallendo con un errore di \macro{ENOENT} se non
+esiste o di \macro{EACCESS} se si sono specificati dei permessi non validi.
+
+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 \macro{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}.
+Se si imposta anche il bit corrispondente a \macro{IPC\_EXCL} la funzione avrà
+successo solo se l'oggetto non esiste già, fallendo con un errore di
+\macro{EEXIST} altrimenti.
+
+
+
+Una coda di messaggi è costituita da una \textit{linked list} in cui nuovi
+messaggi vengono inseriti in coda e letti dalla cima, con una struttura del
+tipo di quella illustrata in 
+
+
+
 
 \subsection{Semafori}
-\label{sec:ipc_semaph}
+\label{sec:ipc_sysv_sem}
 
 Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori.
+Un semaforo è uno speciale contatore che permette di controllare l'accesso a
+risorse condivise. La funzione che permette di ottenere un insieme di semafori
+è \func{semget} ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semget(key\_t key, int nsems, int flag)}
+  
+  Restituisce l'identificatore di un semaforo.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} viene settato agli stessi
+    valori visti per \func{msgget}.}
+\end{functions}
+
+La funzione è 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 \param{nsems} permette di
+specificare quanti semfori deve contenere l'insieme qualora se ne richieda la
+creazione, e deve essere nullo quando si effettua una richiesta
+dell'identificatore di un insieme già esistente.
+
 
 
 \subsection{Memoria condivisa}
-\label{sec:ipc_shar_mem}
+\label{sec:ipc_sysv_shm}
 
 Il terzo oggetto introdotto dal \textit{System V IPC} è quello della memoria
-condivisa.
+condivisa. La funzione che permette di ottenerne uno è \func{shmget} ed il suo
+prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/shm.h}
+  
+  \funcdecl{int shmget(key\_t key, int size, int flag)}
+  
+  Restituisce l'identificatore di una memoria condivisa.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} viene settato agli stessi
+    valori visti per \func{msgget}.}
+\end{functions}
+
+La funzione, come per \func{semget}, è del tutto analoga a \func{msgget}, ed
+identico è l'uso degli argomenti \param{key} e \param{flag}. L'argomento
+
+
+
+\section{La comunicazione fra processi di POSIX}
+\label{sec:ipc_posix}
+
+Lo standard POSIX.1b ha introdotto dei nuovi meccanismi di comunicazione,
+rifacendosi a quelli di System V, introducendo una nuova interfaccia che
+evitasse i principali problemi evidenziati in coda a
+\secref{sec:ipc_sysv_generic}.  
+
+
+
 
 %%% Local Variables: 
 %%% mode: latex