Andato avanti sui semafori, introduzione generale ai concetti base.
authorSimone Piccardi <piccardi@gnulinux.it>
Wed, 28 Aug 2002 23:37:05 +0000 (23:37 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Wed, 28 Aug 2002 23:37:05 +0000 (23:37 +0000)
ipc.tex
prochand.tex

diff --git a/ipc.tex b/ipc.tex
index 6ecd5b1..a7cb576 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 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
@@ -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.
-  \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
@@ -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
-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}.
@@ -1645,24 +1648,146 @@ struct semid_ds
   \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{tabular}[c]{|c|r|l|l|}
+  \begin{tabular}[c]{|c|r|p{8cm}|}
     \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
-    semafori.} 
+    semafori, definite in \file{linux/sem.h}.} 
   \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}
+
 
 
 
index 1dddefc..a45c0d6 100644 (file)
@@ -2426,9 +2426,9 @@ file, o nell'accesso a meccanismi di intercomunicazione come la memoria
 condivisa. In questi casi, se non si dispone della possibilità di eseguire
 atomicamente le operazioni necessarie, occorre che quelle parti di codice in
 cui si compiono le operazioni sulle risorse condivise (le cosiddette
-\textsl{sezioni critiche}) del programma, siano opportunamente protette da
-meccanismi di sincronizzazione (torneremo su queste problematiche di questo
-tipo in \capref{cha:IPC}).
+\textsl{sezioni critiche}\index{sezioni critiche}) del programma, siano
+opportunamente protette da meccanismi di sincronizzazione (torneremo su queste
+problematiche di questo tipo in \capref{cha:IPC}).
 
 Un caso particolare di \textit{race condition} sono poi i cosiddetti
 \textit{deadlock}, particolarmente gravi in quanto comportano spesso il blocco