Andato avanti sui semafori, introduzione generale ai concetti base.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 6ecd5b161ddb4e9888c93d8b49a4885e941dd77e..a7cb5768702723fc39aeafb1b03b17e5da4ae6ca 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1314,8 +1314,10 @@ invece:
 \item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
   rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
   messaggio sulla coda, sono inizializzati a 0.
 \item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
   rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
   messaggio sulla coda, sono inizializzati a 0.
-\item il campo \var{msg\_ctime} viene inizializzato al tempo corrente.
-\item il campo \var{msg\_qbytes} viene inizializzato al valore preimpostato
+\item il campo \var{msg\_ctime}, che esprime il tempo di creazione della coda,
+  viene inizializzato al tempo corrente.
+\item il campo \var{msg\_qbytes} che esprime la dimensione massima del
+  contenuto della coda (in byte) viene inizializzato al valore preimpostato
   del sistema (\macro{MSGMNB}).
 \item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
   primo e ultimo messaggio sono inizializzati a \macro{NULL} e
   del sistema (\macro{MSGMNB}).
 \item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
   primo e ultimo messaggio sono inizializzati a \macro{NULL} e
@@ -1342,7 +1344,7 @@ prototipo 
   \begin{errlist}
   \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
     non ha i privilegi di lettura sulla coda.
   \begin{errlist}
   \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
     non ha i privilegi di lettura sulla coda.
-  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+  \item[\macro{EIDRM}] La coda richiesta è stata cancellata.
   \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
     il processo non ha i privilegi, o si è richiesto di aumentare il valore di
     \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
   \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
     il processo non ha i privilegi, o si è richiesto di aumentare il valore di
     \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
@@ -1615,8 +1617,9 @@ A ciascun insieme di semafori 
 riportata in \figref{fig:ipc_semid_sd}, 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
 riportata in \figref{fig:ipc_semid_sd}, 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}, per
-quanto riguarda gli altri campi invece:
+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:
 \begin{itemize*}
 \item il campo \var{sem\_nsems}, che esprime il numero di semafori
   nell'insieme, viene inizializzato al valore di \param{nsems}.
 \begin{itemize*}
 \item il campo \var{sem\_nsems}, che esprime il numero di semafori
   nell'insieme, viene inizializzato al valore di \param{nsems}.
@@ -1645,24 +1648,146 @@ struct semid_ds
   \label{fig:ipc_semid_sd}
 \end{figure}
 
   \label{fig:ipc_semid_sd}
 \end{figure}
 
+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 sono
+accessibili e modificabili al solito attraverso \func{sysctl} o scrivendo
+direttamente nel file \file{/proc/sys/kernel/sem}.
+
 \begin{table}[htb]
   \footnotesize
   \centering
 \begin{table}[htb]
   \footnotesize
   \centering
-  \begin{tabular}[c]{|c|r|l|l|}
+  \begin{tabular}[c]{|c|r|p{8cm}|}
     \hline
     \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
     \hline
     \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \macro{SEMMNI}&   16& Numero massimo di insiemi di semafori. \\
-    \macro{SEMMAX}& 8192& .\\
-    \macro{SEMMNB}&16384& .\\
+    \macro{SEMMNI}&          128 & Numero massimo di insiemi di semafori. \\
+    \macro{SEMMSL}&          250 & Numero massimo di semafori per insieme.\\
+    \macro{SEMMNS}&\macro{SEMMNI}*\macro{SEMMSL}& Numero massimo di semafori
+                                   nel sistema .\\
+    \macro{SEMVMX}&        32767 & Massimo valore per un semaforo.\\
+    \macro{SEMOPM}&           32 & Massimo numero di operazioni per chiamata a
+                                   \func{semop}. \\
+    \macro{SEMMNU}&\macro{SEMMNS}& Massimo numero di strutture di ripristino.\\
+    \macro{SEMUME}&\macro{SEMOPM}& Massimo numero di voci di ripristino.\\
+    \macro{SEMAEM}&\macro{SEMVMX}& valore massimo per l'aggiustamento
+                                   all'uscita. \\
     \hline
   \end{tabular}
   \caption{Valori delle costanti associate ai limiti degli insiemi di
     \hline
   \end{tabular}
   \caption{Valori delle costanti associate ai limiti degli insiemi di
-    semafori.} 
+    semafori, definite in \file{linux/sem.h}.} 
   \label{tab:ipc_sem_limits}
 \end{table}
 
   \label{tab:ipc_sem_limits}
 \end{table}
 
+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}).
+
+Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a
+seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione
+del codice. In questo modo l'accesso ad una risorsa condivisa da più processi
+può essere controllato, associando ad essa un semaforo che consente di
+assicurare che non più di un processo alla volta possa usarla.
+
+Il concetto di semaforo è uno dei concetti base nella programmazione ed è
+assolutamente generico, così come del tutto generali sono modalità con cui lo
+si utilizza. Un processo che deve accedere ad una risorsa eseguirà un
+controllo del semaforo: se questo è positivo il suo valore sarà decrementato,
+indicando che si è consumato una unità della risorsa, ed il processo potrà
+proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta
+completate le operazioni volute, reincrementando il semaforo.
+
+Se al momento del controllo il valore del semaforo è nullo, siamo invece in
+una situazione in cui la risorsa non è disponibile, ed il processo si
+bloccherà in stato di \textit{sleep} fin quando chi la sta utilizzando non la
+rilascerà, incrementando il valore del semaforo. Non appena il semaforo torna
+positivo, indicando che la risorsa è disponibile, il processo sarà svegliato,
+e si potrà operare come nel caso precedente (decremento del semaforo, accesso
+alla risorsa, incremento del semaforo).
+
+Per poter implementare questo tipo di logica le operazioni di controllo e
+decremento del contatore associato al semaforo devono essere atomiche,
+pertanto una realizzazione di un oggetto di questo tipo è necessariamente
+demandata al kernel. La forma più semplice di semaforo è quella del
+\textsl{semaforo binaria}, o \textit{mutex}, in cui un valore diverso da zero
+(normalmente 1) indica la libertà di accesso, e un valore nullo l'occupazione
+della risorsa; in generale però si possono usare semafori con valori interi,
+utilizzando il valore del contatore come indicatore del ``numero di risorse''
+ancora disponibili.
+
+Purtroppo l'implementazione effettuata nel sistema di intercomunicazione di
+System V complica inutilmente questo schema elementare: anzittutto non è
+possibile definire un singolo semaforo, ma se ne deve creare per forza un
+insieme, specificando il numero di semafori che esso deve contenere con
+l'argomento \param{nsem} di \func{semget}.
+
+Ma i difetti maggiori dei semafori nel System V IPC sono due: il primo è che
+non esiste una funzione che permetta di creare ed inizializzare un semaforo in
+un'unica operazione atomica; occorre prima creare l'insieme con \func{semget}
+e poi inizializzarlo con \func{semctl}.  
+
+Il secondo è che essendo i semafori delle risorse globali di sistema, che non
+vengono cancellate quando nessuno le usa più, ci si trova a dover affrontare
+esplicitamente il caso in cui un processo termina per un qualche errore,
+lasciando un semaforo occupato, che resterà tale per sempre, a meno di non
+rimediare la situazione con opportune operazioni di ripristino.
+
+Come accennato una volta creato l'insieme di semafori per l'inizializzazione
+dei valori occorre ricorrere ad una funzione separata, \func{semctl}, che è
+quella che effettua le operazioni di controllo; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semctl(int semid, int semnum, int cmd, ...)}
+  
+  Esegue le operazioni di controllo su un semaforo o un insieme di semafori.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+    errore, nel qual caso \var{errno} viene settato a:
+    \begin{errlist}
+    \item[\macro{EACCES}] Il processo non ha i privilegi per eseguire
+      l'operazione richiesta.
+    \item[\macro{EIDRM}] L'insieme di semafori è stato cancellato.
+    \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+      il processo non ha  privilegi sufficienti ad eseguire l'operazione.
+    \item[\macro{ERANGE}] Si è richiesto \macro{SETALL} \macro{SETVAL} ma il
+      valore a cui si vuole impostare il semaforo è minore di zero o maggiore
+      di \macro{SEMVMX}.
+  \end{errlist}
+  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione può avere tre o quattro parametri, a seconda dell'operazione
+specificata con \param{cmd}
+
+
+
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct sembuf
+{
+  unsigned short int sem_num;   /* semaphore number */
+  short int sem_op;             /* semaphore operation */
+  short int sem_flg;            /* operation flag */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{sembuf}, usata per le operazioni sui
+    semafori.}
+  \label{fig:ipc_sembuf}
+\end{figure}
+