Aggiunto programmino di test.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 53e51b96794fba1fef5518a80372a80e32c3f938..ed2d49267e852aa29b90c8141c9bca17c9a69791 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -584,8 +584,8 @@ molti altri devono poter leggere non pu
 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 quello che viene ormai chiamato il
-\textsl{Sistema di comunicazione inter-processo} di System V, o
+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)}.
 
 
@@ -597,31 +597,33 @@ La principale caratteristica del sistema di IPC di System V 
 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.
+in uso. 
+
+Questo comporta due problemi: il primo è che, al contrario di quanto avviene
+per pipe e fifo, la memoria allocata per questi oggetti non viene rilasciata
+automaticamente quando nessuno li vuole più utilizzare, ed essi devono essere
+cancellati esplicitamente, se non si vuole che restino attivi fino al riavvio
+del sistema. Il secondo è che, dato che non c'è un contatore di riferimenti,
+essi possono essere cancellati anche se ci sono dei processi che li stanno
+utilizzando, con tutte le conseguenze (negative) del caso.
 
 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.
+è un numero progressivo (un po' come il \acr{pid} dei processi) che il kernel
+assegna a ciascuno di essi quanto vengono creati (sul prodedimento di
+assegnazione torneremo in \secref{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à, 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, come gli
-identificatori del creatore (\var{cuid} e \var{cgid}) e del proprietario
-(\var{uid} e \var{gid}), e le modalità di accesso (\var{mode}) che ne
-specifica i permessi, che sono analoghi a quelli usati per i file (vedi
-\secref{sec:file_perm_overview}). 
+contiene anche le varie proprietà associate all'oggetto. 
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -705,12 +707,217 @@ 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}.
+Questo è, insieme al fatto che gli oggetti sono permanenti e non mantengono un
+contatore di riferimenti per la cancellazione automatica, 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{itemize}
+\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 se il permesso per gli altri è appropriato l'accesso è consentito.
+\end{itemize}
+solo se tutti i controlli elencati falliscono l'accesso è negato. Si noti che
+a differenza di quanto avviene per i permessi dei file, fallire in uno dei
+passi elencati non comporta il fallimento dell'accesso. Un'altra differenza è
+che per gli oggetti di IPC il valore di \var{umask} (si ricordi quanto esposto
+in \secref{sec:file_umask}) non ha alcun effetto.
+
+
+\subsection{Gli identificatori ed il loro utilizzo}
+\label{sec:ipc_sysv_id_use}
+
+L'unico campo di \var{ipc\_perm} del quale non abbiamo ancora parlato è
+\var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico
+``\textit{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.
+
+Quando il sistema si avvia, alla creazione di ogni nuovo oggetto di IPC viene
+assegnato un numero progressivo, pari al numero di oggetti di quel tipo
+esistenti. Se il comportamente fosse sempre questo sarebbe identico a quello
+usato nell'assegnazione dei file descriptor nei processi, ed i valori degli
+identificatori tenderebbero ad essere riutilizzati spesso e restare di piccole
+dimensioni ed inferiori al numero massimo di oggetti diponibili.
+
+Questo va benissimo nel caso dei file descriptor, che sono locali ad un
+processo, ma qui il comportamento varrebbe per tutto il sistema, e per
+processi del tutto scorrelati fra loro. Così si potrebbero avere situazioni
+come quella in cui un server esce e cancella le sue code di messaggi, ed il
+relativo identificatore viene immediatamente assegnato a quelle di un altro
+server partito subito dopo, con la possibilità che i client del primo non
+facciano in tempo ad accorgersi dell'avvenuto, e finiscano con l'interagire
+con gli oggetti del secondo, con conseguenze imprevedibili.
+
+Proprio per evitare questo tipo di situazioni il sistema usa il valore di
+\var{req} per provvedere un meccanismo che porti gli identificatori ad
+assumere tutti i valori possibili, rendendo molto più lungo il periodo in cui
+un identificatore può venire riutilizzato.
+
+Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino
+  al kernel 2.2.x questo numero, ed altri limiti relativi al \textit{System V
+    IPC}, potevano essere cambiati solo con una ricompilazione del kernel,
+  andando a modificare le costanti definite nei relativi haeder file.  A
+  partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo
+  scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
+  \file{/proc/sys/kernel} o con \texttt{syscntl}.} e per ciascuno di essi
+viene mantenuto in \var{seq} un numero di sequenza progressivo che viene
+incrementato di uno ogni volta che l'oggetto viene cancellato. Quando
+l'oggetto viene creato usando uno spazio che era già stato utilizzato in
+precedenza per restituire l'identificatore al numero di oggetti presenti viene
+sommato il valore di \var{seq} moltiplicato per il numero massimo di oggetti
+di quel tipo,\footnote{questo vale fino ai kernel della serie 2.2.x, dalla
+  serie 2.4.x viene usato lo stesso fattore per tutti gli oggetti, esso è dato
+  dalla costante \macro{IPCMNI}, definita in \file{include/linux/ipc.h}, che
+  indica il limite massimo per il numero di oggetti di IPC, il cui valore è
+  32768.}  si evita così il riutilizzo degli stessi numeri, e si fa sì che
+l'identificatore assuma tutti i valori possibili.
+
+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. 
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+    ...
+    switch (type) {
+    case 'q':   /* Message Queue */
+        debug("Message Queue Try\n");
+        for (i=0; i<n; i++) {
+            id = msgget(IPC_PRIVATE, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            msgctl(id, IPC_RMID, NULL);
+        }
+        break;
+    case 's':   /* Semaphore */
+        debug("Semaphore\n");
+        for (i=0; i<n; i++) {
+            id = semget(IPC_PRIVATE, 1, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            semctl(id, 0, IPC_RMID);
+        }
+        break;
+    case 'm':   /* Shared Memory */
+        debug("Shared Memory\n");
+        for (i=0; i<n; i++) {
+            id = shmget(IPC_PRIVATE, 1000, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            shmctl(id, IPC_RMID, NULL);
+        }
+        break;
+    default:    /* should not reached */
+        return -1;
+    }
+    return 0;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del programma di test per l'assegnazione degli
+    identificatori degli oggetti di IPC \file{IPCTestId.c}.}
+  \label{fig:ipc_sysv_idtest}
+\end{figure}
+
+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
+\var{n} al numero di volte che si vuole effettuare il ciclo di creazione,
+stampa, cancellazione. I valori di default sono per l'uso delle code di
+messaggi e un ciclo di 10 volte. Se si lancia il comando si otterrà qualcosa
+del tipo:
+\begin{verbatim}
+piccardi@gont sources]$ ./ipctestid
+Identifier Value 0 
+Identifier Value 32768 
+Identifier Value 65536 
+Identifier Value 98304 
+Identifier Value 131072 
+Identifier Value 163840 
+Identifier Value 196608 
+Identifier Value 229376 
+Identifier Value 262144 
+Identifier Value 294912 
+\end{verbatim}%$
+il che ci mostra che abbiamo un kernel della serie 2.4.x nel quale non avevamo
+ancora usato nessuna coda di messaggi. Se ripetiamo il comando otterremo
+ancora:
+\begin{verbatim}
+[piccardi@gont sources]$ ./ipctestid
+Identifier Value 327680 
+Identifier Value 360448 
+Identifier Value 393216 
+Identifier Value 425984 
+Identifier Value 458752 
+Identifier Value 491520 
+Identifier Value 524288 
+Identifier Value 557056 
+Identifier Value 589824 
+Identifier Value 622592 
+\end{verbatim}%$
+che ci mostra come il valore di \var{seq} sia in effetti una quantità
+mantenuta staticamente all'interno del sistema.
 
 
 \subsection{Code di messaggi}
@@ -753,35 +960,30 @@ 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. 
+associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
+farvi riferimento solo attraverso l'identificatore.
 
-Se invece si specifica un valore 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} altrimenti.
+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, con gli stessi valori e significati di quelli riportati in
-\secref{tab:file_mode_flags}.\footnote{per usare i quali però occorrerà
-  includere il file \file{sys/stat.h}.} 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.
+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.
 
-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.
 
 
-
-
-Esse sono infatti costituite da una \textit{linked list} in cui nuovi messaggi
-vengono inseriti in coda e letti dalla cima.
-
+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
 
 
 
@@ -835,7 +1037,7 @@ prototipo 
     valori visti per \func{msgget}.}
 \end{functions}
 
-La funzione, come per \func{semget}, è del tutto analoga a \func{msgget}, ed
+La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed
 identico è l'uso degli argomenti \param{key} e \param{flag}. L'argomento
 
 
@@ -850,6 +1052,21 @@ evitasse i principali problemi evidenziati in coda a
 
 
 
+\subsection{Considerazioni generali}
+\label{sec:ipc_posix_generic}
+
+
+
+\subsection{Code di messaggi}
+\label{sec:ipc_posix_mq}
+
+
+\subsection{Semafori}
+\label{sec:ipc_posix_sem}
+
+
+\subsection{Memoria condivisa}
+\label{sec:ipc_sysv_shm}
 
 %%% Local Variables: 
 %%% mode: latex