X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=1502f34f3fe6cde7cf60c807c12bc45d592f15b4;hp=aa6893c01586c2841dd3244df2550eca7dec8826;hb=f67bf0a685d61f70c3536e1f258b96a658162f9e;hpb=57c1291f77a1a179e67c4506b3e05e74ad89d21e diff --git a/ipc.tex b/ipc.tex index aa6893c..1502f34 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1488,7 +1488,7 @@ argomento cioè \var{message} è una propria struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se consideriamo il caso dell'esempio in \figref{fig:ipc_msbuf}, \param{msgsz} -dovrà essere pari a \macro{LENGHT}). +dovrà essere pari a \macro{LENGTH}). \begin{figure}[!htb] \footnotesize \centering @@ -1575,7 +1575,7 @@ rimosso dalla stessa) La funzione legge un messaggio dalla coda specificata scrivendolo nel buffer indicato da \param{msgp}, che avrà un formato analogo a quello di \figref{fig:ipc_msbuf}. L'argomento \param{msgsz} indica la lunghezza massima -del testo del messaggio (equivalente al valore del parametro \macro{LENGHT} +del testo del messaggio (equivalente al valore del parametro \macro{LENGTH} nell'esempio di \figref{fig:ipc_msbuf}). Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene @@ -1644,9 +1644,9 @@ 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. +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 @@ -1705,9 +1705,9 @@ Purtroppo questa implementazione complica inutilmente lo schema elementare che 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. @@ -1854,9 +1854,13 @@ loro inizializzazione) 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 @@ -1877,9 +1881,11 @@ union semun { \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 @@ -1899,25 +1905,28 @@ possibili valori legali per questo argomento sono: 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 @@ -1929,15 +1938,15 @@ possibili valori legali per questo argomento sono: \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 semaforo 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 @@ -1953,11 +1962,52 @@ semafori il cui valore viene modificato. \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 operazioni multiple sui singoli semafori di +un insieme. La funzione richiede come primo argomento l'identificatore +\param{semid} dell'insieme su cui si vuole operare. Il numero di operazioni da +effettuare viene specificato con l'argomento \param{nsop}, mentre il loro +contenuto viene passato con un puntatore ad un vettore di strutture +\var{sembuf} nell'argomento \param{sops}. Le operazioni richieste vengono +effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante. \begin{figure}[!htb] \footnotesize \centering @@ -1977,7 +2027,107 @@ struct sembuf \label{fig:ipc_sembuf} \end{figure} +Il contenuto di ciascuna operazione deve essere specificato attraverso una +opportuna struttura \var{sembuf} (la cui definizione è riportata in +\figref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di +allocare in un opportuno vettore. La struttura permette di indicare il +semaforo su cui operare, il tipo di operazione, ed un flag di controllo. + +Il campo \var{sem\_num} serve per indicare a quale semaforo dell'insieme fa +riferimento 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 +e determina il comportamento della chiamata a \func{semop}; tre sono i casi +possibili: +\begin{basedescript}{\desclabelwidth{2.0cm}} +\item[\var{sem\_op}$>0$] In questo caso il valore di \var{sem\_op} viene + aggiunto al valore corrente di \var{semval}. La funzione ritorna + immediatamente (con un errore di \macro{ERANGE} qualora si sia superato il + limite \macro{SEMVMX}) ed il processo non viene bloccato in nessun caso. + Specificando \macro{SEM\_UNDO} si aggiorna il contatore per il ripristino + del valore del semaforo. Al processo chiamante è richiesto il privilegio di + alterazione (scrittura) sull'insieme di semafori. + +\item[\var{sem\_op}$=0$] Nel caso \var{semval} sia zero l'esecuzione procede + immediatamente. Se \var{semval} è diverso da zero il comportamento è + controllato da \var{sem\_flg}, se è stato impostato \macro{IPC\_NOWAIT} la + funzione ritorna con un errore di \macro{EAGAIN}, 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*} + Al processo chiamante è richiesto il privilegio di lettura dell'insieme dei + semafori. + +\item[\var{sem\_op}$<0$] Nel caso in cui \var{semval} è maggiore o uguale del + valore assoluto di \var{sem\_op} (se cioè la somma dei due valori resta + positiva o nulla) i valori vengono sommati e la funzione ritorna + immediatamente; qualora si sia impostato \macro{SEM\_UNDO} viene anche + aggiornato il contatore per il ripristino del valore del semaforo. In caso + contrario (quando cioè la somma darebbe luogo ad un valore di \var{semval} + negativo) se si è impostato \macro{IPC\_NOWAIT} la funzione ritorna con un + errore di \macro{EAGAIN}, altrimenti viene incrementato di uno \var{semncnt} + ed il processo resta in stato di \textit{sleep} fintanto che non si ha una + delle condizioni seguenti: + \begin{itemize*} + \item \var{semval} diventa maggiore o uguale del valore assoluto di + \var{sem\_op}, nel qual caso \var{semncnt} viene decrementato di uno, il + valore di \var{sem\_op} viene sommato a \var{semval}, e se era stato + impostato \macro{SEM\_UNDO} viene aggiornato il contatore per il + ripristino del valore del semaforo. + \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{semncnt} + viene decrementato di uno e \func{semop} ritorna un errore di + \macro{EINTR}. + \end{itemize*} + Al processo chiamante è richiesto il privilegio di alterazione (scrittura) + sull'insieme di semafori. +\end{basedescript} +In caso di successo della funzione viene aggiornato di \var{sempid} per ogni +semaforo modificato al valore del \acr{pid} del processo chiamante; inoltre +vengono pure aggiornati al tempo corrente i campi \var{sem\_otime} e +\var{sem\_ctime}. + +Dato che, come già accennato in precedenza, in caso di uscita inaspettata i +semafori possono restare occupati, abbiamo visto come \func{semop} permetta di +attivare un meccanismo di ripristino attraverso l'uso del flag +\macro{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura +\var{sem\_undo}, associata ad ogni processo per ciascun semaforo che esso ha +modificato; all'uscita i semafori modificati vengono ripristinati, e le +strutture disallocate. Per mantenere coerente il comportamento queste +strutture non vengono ereditate attraverso una \func{fork} (altrimenti si +avrebbe un doppio ripristino), mentre vengono passate nell'esecuzione di una +\func{exec} (altrimenti non si avrebbe ripristino). + +Resta comunque insoluto il problema di fondo di questo meccanismo, che non si +adatta al concetto di operazioni atomiche su un semaforo, dato che le +richieste di ripristino si accumulano attraverso diverse chiamate a +\func{semop}, cosa succede se all'uscita del processo? Si deve porre il +processo in stato di \textit{sleep} o andare avanti come se fosse stato +impostato \macro{IPC\_NOWAIT}. La scelta del kernel è quella di effettuare le +operazioni che non prevedono un blocco del processo ed ignorare +silenziosamente le altre. Questo comporta che un comportamento senza problemi +può essere garantito solo per i semafori privati. \subsection{Memoria condivisa}