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à.
 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)}.
 
 
 \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ù
 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
 
 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},
 
 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
 
 \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.
 
 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}
 
 
 \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 è
 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
 
 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}
 
     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
 
 
 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
 
 %%% Local Variables: 
 %%% mode: latex