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.
+di un programma. 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
abbiamo descritto, dato che non è possibile definire un singolo semaforo, ma
se ne deve creare per forza un insieme. Ma questa in definitiva è solo una
complicazione inutile, il problema è che i semafori del System V IPC soffrono
-di altri due ben più gravi difetti.
+di altri due, ben più gravi, difetti.
-Il primo grave difetto è che non esiste una funzione che permetta di creare ed
+Il primo difetto è che non esiste una funzione che permetta di creare ed
inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme
dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si
perde così ogni possibilità di eseguire atomicamente questa operazione.
La funzione può avere tre o quattro parametri, a seconda dell'operazione
specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
\param{semid} o sul singolo semaforo di un insieme, specificato da
-\param{semnum}. Qualora la funzione operi con quattro argomenti \param{arg} è
-un argomento generico che deve essere una \var{union semun}, si è riportato la
-relativa definizione in \figref{fig:ipc_semun}.
+\param{semnum}.
+
+Qualora la funzione operi con quattro argomenti \param{arg} è
+un argomento generico, che conterrà un dato diverso a seconda dell'azione
+richiesta; per unificare l'argomento esso deve essere passato come una
+\var{union semun}, la cui definizione, con i possibili valori che può
+assumere, è riportata in \figref{fig:ipc_semun}.
\begin{figure}[!htb]
\footnotesize \centering
\label{fig:ipc_semun}
\end{figure}
-Il comportamento della funzione, come il numero di parametri, dipende dal
-valore dell'argomento \param{cmd}, che specifica l'azione da intraprendere; i
-possibili valori legali per questo argomento sono:
+Come già accennato sia il comportamento della funzione che il numero di
+parametri con cui deve essere invocata, dipendono dal valore dell'argomento
+\param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
+cioè non causano un errore di \macro{EINVAL}) per questo argomento sono i
+seguenti:
\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
\item[\macro{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il
contenuto della relativa struttura \var{semid\_ds} all'indirizzo specificato
corrispondere o al creatore o al proprietario dell'insieme, o
all'amministratore. L'argomento \param{semnum} viene ignorato.
\item[\macro{GETALL}] Restituisce il valore corrente di ciascun semaforo
- dell'insieme (il campo \var{semval} di \var{sem}) nel vettore indicato da
- \param{arg.array}. Occorre avere il permesso di lettura. L'argomento
- \param{semnum} viene ignorato.
+ dell'insieme (corrispondente al campo \var{semval} di \var{sem}) nel vettore
+ indicato da \param{arg.array}. Occorre avere il permesso di lettura.
+ L'argomento \param{semnum} viene ignorato.
\item[\macro{GETNCNT}] Restituisce come valore di ritorno della funzione il
numero di processi in attesa che il semaforo \param{semnum} dell'insieme
- venga incrementato (il campo \var{semncnt} di \var{sem}); va invocata con
- tre argomenti. Occorre avere il permesso di lettura.
+ \param{semid} venga incrementato (corrispondente al campo \var{semncnt} di
+ \var{sem}); va invocata con tre argomenti. Occorre avere il permesso di
+ lettura.
\item[\macro{GETPID}] Restituisce come valore di ritorno della funzione il
\acr{pid} dell'ultimo processo che ha compiuto una operazione sul semaforo
- \param{semnum} dell'insieme (il campo \var{sempid} di \var{sem}); va
- invocata con tre argomenti. Occorre avere il permesso di lettura.
-\item[\macro{GETVAL}] Restituisce come valore di ritorno della funzione il il
- valore corrente del semaforo \param{semnum} dell'insieme (il campo
- \var{semval} di \var{sem}); va invocata con tre argomenti. Occorre avere il
+ \param{semnum} dell'insieme \param{semid} (corrispondente al campo
+ \var{sempid} di \var{sem}); va invocata con tre argomenti. Occorre avere il
permesso di lettura.
+\item[\macro{GETVAL}] Restituisce come valore di ritorno della funzione il il
+ valore corrente del semaforo \param{semnum} dell'insieme \param{semid}
+ (corrispondente al campo \var{semval} di \var{sem}); va invocata con tre
+ argomenti. Occorre avere il permesso di lettura.
\item[\macro{GETZCNT}] Restituisce come valore di ritorno della funzione il
numero di processi in attesa che il valore del semaforo \param{semnum}
- dell'insieme diventi nullo (il campo \var{semncnt} di \var{sem}); va
- invocata con tre argomenti. Occorre avere il permesso di lettura.
+ dell'insieme \param{semid} diventi nullo (corrispondente al campo
+ \var{semncnt} di \var{sem}); va invocata con tre argomenti. Occorre avere
+ il permesso di lettura.
\item[\macro{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
aggiornando il campo \var{sem\_ctime} di \var{semid\_ds}. I valori devono
essere passati nel vettore indicato da \param{arg.array}. Si devono avere i
\end{basedescript}
Quando si imposta il valore di un semaforo (sia che lo si faccia per tutto
-l'insieme con \macro{SETALL}, che per uno solo con \macro{SETVAL}, i processi
-in attesa su di esso reagiscono di conseguenza al cambiamento di valore.
-Inoltre la coda delle operazioni di ripristino viene cancellata per tutti i
-semafori il cui valore viene modificato.
+l'insieme con \macro{SETALL}, che per un solo semforo con \macro{SETVAL}), i
+processi in attesa su di esso reagiscono di conseguenza al cambiamento di
+valore. Inoltre la coda delle operazioni di ripristino viene cancellata per
+tutti i semafori il cui valore viene modificato.
\begin{table}[htb]
\footnotesize
\centering
- \begin{tabular}[c]{|c|p{8cm}|}
+ \begin{tabular}[c]{|c|l|}
\hline
\textbf{Operazione} & \textbf{Valore restituito} \\
\hline
\end{table}
Il valore di ritorno della funzione in caso di successo dipende
-dall'operazione richiesta; in generale esso è nullo, a meno che non si sia
-specificata una delle operazioni riportate in
-\tabref{tab:ipc_semctl_returns}, nel qual caso viene restituito il
-corrispondente campo della struttura \var{sem}.
+dall'operazione richiesta; per tutte le operazioni che richiedono quattro
+argomenti esso è sempre nullo, per le altre operazioni, elencate in
+\tabref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto,
+corrispondente al campo della struttura \var{sem} indicato nella seconda
+colonna della tabella.
+
+Le operazioni ordinarie sui semafori, come l'acquisizione o il rilascio degli
+stessi (in sostanza tutte quelle non comprese nell'uso di \func{semctl})
+vengono effettuate con la funzione \func{semop}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/sem.h}
+
+ \funcdecl{int semop(int semid, struct sembuf *sops, unsigned nsops)}
+
+ Esegue le operazioni ordinarie su un semaforo o un insieme di semafori.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \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{ENOMEM}] Si è richiesto un \macro{SEM\_UNDO} ma il sistema
+ non ha le risorse per allocare la struttura di ripristino.
+ \item[\macro{EAGAIN}] Un'operazione comporterebbe il blocco del processo,
+ ma si è specificato \macro{IPC\_NOWAIT} in \var{sem\_flg}.
+ \item[\macro{EINTR}] La funzione, bloccata in attesa dell'esecuzione
+ dell'operazione, viene interrotta da un segnale.
+ \item[\macro{E2BIG}] L'argomento \param{nsops} è maggiore del numero
+ massimo di operazioni \macro{SEMOPM}.
+ \item[\macro{ERANGE}] Per alcune operazioni il valore risultante del
+ semaforo viene a superare il limite massimo \macro{SEMVMX}.
+ \end{errlist}
+ ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+La funzione permette di eseguire un certo numero di operazioni, specificato
+dall'argomento \param{nsop}, sull'insieme di semafori \param{semid}. Le
+operazioni da eseguire vengono indicate attraverso un vettore di \param{nsop}
+strutture \var{sembuf}, il cui indirizzo è passato nell'argomento
+\param{sops}. Le operazioni richieste verranno effettivamente eseguite se e
+soltanto se è possibile effettuarle tutte quante.
\begin{figure}[!htb]
\footnotesize \centering
\label{fig:ipc_sembuf}
\end{figure}
-
-
+Il primo campo della struttura \var{sembuf}, la cui definizione è riportata in
+\figref{fig:ipc_sembuf}, serve per indicare su quale semaforo dell'insieme si
+intende eseguire l'operazione; si ricordi che i semafori sono numerati come in
+un vettore, per cui il primo semaforo corrisponde ad un valore nullo di
+\var{sem\_num}.
+
+Il campo \var{sem\_flg} è un flag, mantenuto come maschera binaria, per il
+quale possono essere impostati i due valori \macro{IPC\_NOWAIT} e
+\macro{SEM\_UNDO}. Impostando \macro{IPC\_NOWAIT} si fa si che, invece di
+bloccarsi (in tutti quei casi in cui l'esecuzione di una operazione richiede
+che il processo vada in stato di \textit{sleep}), \func{semop} ritorni
+immediatamente con un errore di \macro{EAGAIN}. Impostando \macro{SEM\_UNDO}
+si richiede invece che l'operazione venga registrata in modo che il valore del
+semaforo possa essere ripristinato all'uscita del processo.
+
+Infine \var{sem\_op} è il campo che controlla l'operazione che viene eseguita.
+Se si specifica un valore positivo questo viene aggiunto al valore corrente di
+\var{semval}; l'operazione ha sempre successo ed il processo non viene mai
+bloccato. Specificando \macro{SEM\_UNDO} si aggiorna il contatore per il
+ripristino del valore del semaforo. Al chiamate è richiesto il privilegio di
+alterazione (scrittura) sull'insieme di semafori.
+
+Se si specifica un valore nullo il processo deve avere il privilegio di
+lettura sull'insieme. Nel caso \var{semval} sia zero l'esecuzione procede
+immediatamente, altrimenti viene incrementato \var{semzcnt} di uno ed il
+processo resta in stato di \textit{sleep} fintanto che non si ha una delle
+condizioni seguenti:
+\begin{itemize*}
+\item \var{semval} diventa zero, nel qual caso \var{semzcnt} viene
+ decrementato di uno.
+\item l'insieme di semafori viene rimosso, nel qual caso \func{semop} ritorna
+ un errore di \macro{EIDRM}.
+\item il processo chiamante riceve un segnale, nel qual caso \var{semzcnt}
+ viene decrementato di uno e \func{semop} ritorna un errore di \macro{EINTR}.
+\end{itemize*}
\subsection{Memoria condivisa}
\label{sec:ipc_sysv_shm}