From: Simone Piccardi Date: Sun, 12 May 2013 16:59:16 +0000 (+0000) Subject: Finita revisione semafori SysV IPC X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=f3d0e3e138ce281770f730e22538ae849301f06f;p=gapil.git Finita revisione semafori SysV IPC --- diff --git a/ipc.tex b/ipc.tex index cd29ca7..1f9226d 100644 --- a/ipc.tex +++ b/ipc.tex @@ -355,7 +355,7 @@ chiama \funcd{popen} ed il suo prototipo è: \end{funcproto} La funzione crea una \textit{pipe}, esegue una \func{fork} creando un nuovo -processe nel quale invoca il programma \param{command} attraverso la shell (in +processo nel quale invoca il programma \param{command} attraverso la shell (in sostanza esegue \file{/bin/sh} con il flag \code{-c}). L'argomento \param{type} deve essere una delle due stringhe \verb|"w"| o \verb|"r"|, per richiedere che la \textit{pipe} restituita come valore di @@ -1020,7 +1020,7 @@ problema del \textit{SysV-IPC}. 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 se ne sconsiglia assolutamente l'uso nei nuovi programmi, considerato che è ormai -disponibile una revisione completa dei meccamismi di IPC fatta secondo quanto +disponibile una revisione completa dei meccanismi di IPC fatta secondo quanto indicato dallo standard POSIX.1b, che presenta una realizzazione più sicura ed una interfaccia più semplice, che tratteremo in sez.~\ref{sec:ipc_posix}. @@ -1161,7 +1161,7 @@ numero di tutti gli oggetti presenti nel \textit{SysV-IPC}, ed il cui default l'identificatore assuma tutti i valori possibili. In fig.~\ref{fig:ipc_sysv_idtest} è riportato il codice di un semplice -programma di test che si limita a creare un oggetto di ICP (specificato con +programma di test che si limita a creare un oggetto di IPC (specificato con una opzione a riga di comando), stamparne il numero di identificatore, e cancellarlo, il tutto un numero di volte specificato tramite una seconda opzione. La figura non riporta il codice di selezione delle opzioni, che @@ -1326,7 +1326,7 @@ Una coda di messaggi è costituita da una \itindex{linked~list} \textit{linked ricerca.} I nuovi messaggi vengono inseriti in coda alla lista e vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si è riportato uno schema semplificato con cui queste strutture vengono mantenute dal kernel. Lo schema -illustrato in realta è una semplificazione di quello usato fino ai kernel +illustrato in realtà è una semplificazione di quello usato fino ai kernel della serie 2.2. A partire della serie 2.4 la gestione delle code di messaggi è effettuata in maniera diversa (e non esiste una struttura \struct{msqid\_ds} nel kernel), ma abbiamo mantenuto lo schema precedente dato che illustra in @@ -1458,7 +1458,7 @@ per \param{cmd} sono: A questi tre valori, che sono quelli previsti dallo standard, su Linux se ne affiancano altri tre (\const{IPC\_INFO}, \const{MSG\_STAT} e -\const{MSG\_INFO}) introdotti ad uso del programma \cmd{icps} per ottenere le +\const{MSG\_INFO}) introdotti ad uso del programma \cmd{ipcs} per ottenere le informazioni generali relative alle risorse usate dalle code di messaggi. Questi potranno essere modificati o rimossi in favore dell'uso di \texttt{/proc}, per cui non devono essere usati e non li tratteremo. @@ -2059,8 +2059,9 @@ anche la loro inizializzazione, è \funcd{semctl}; il suo prototipo è: tre argomenti ed un valore nullo quando usata con quattro e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EACCES}] i permessi assegnati al semaforo non consentono - l'operazione richiesta. + \item[\errcode{EACCES}] i permessi assegnati al semaforo non consentono + l'operazione di lettura o scrittura richiesta e non si hanno i privilegi + di amministratore. \item[\errcode{EIDRM}] l'insieme di semafori è stato cancellato. \item[\errcode{EPERM}] si è richiesto \const{IPC\_SET} o \const{IPC\_RMID} ma il processo non è né il creatore né il proprietario del semaforo e @@ -2106,9 +2107,9 @@ situazione. Come già accennato sia il comportamento della funzione che il numero di argomenti 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 \errcode{EINVAL}, per questo argomento sono i -seguenti: +\param{cmd}, che specifica l'azione da intraprendere. Per questo argomento i +valori validi, quelli cioè che non causano un errore di \errcode{EINVAL}, sono +i seguenti: \begin{basedescript}{\desclabelwidth{1.6cm}\desclabelstyle{\nextlinelabel}} \item[\const{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiandone i valori nella struttura \struct{semid\_ds} posta all'indirizzo specificato @@ -2135,30 +2136,29 @@ seguenti: \item[\const{GETNCNT}] Restituisce come valore di ritorno della funzione il numero di processi in attesa che il semaforo \param{semnum} dell'insieme \param{semid} venga incrementato (corrispondente al campo \var{semncnt} di - \struct{sem}); va invocata con tre argomenti. Occorre avere il permesso di + \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. \item[\const{GETPID}] Restituisce come valore di ritorno della funzione il \ids{PID} dell'ultimo processo che ha compiuto una operazione sul semaforo \param{semnum} dell'insieme \param{semid} (corrispondente al campo - \var{sempid} di \struct{sem}); va invocata con tre argomenti. Occorre avere + \var{sempid} di \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. \item[\const{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 \struct{sem}); va invocata con tre + (corrispondente al campo \var{semval} di \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. \item[\const{GETZCNT}] Restituisce come valore di ritorno della funzione il numero di processi in attesa che il valore del semaforo \param{semnum} dell'insieme \param{semid} diventi nullo (corrispondente al campo - \var{semncnt} di \struct{sem}); va invocata con tre argomenti. Occorre avere - il permesso di lettura. + \var{semncnt} di \struct{sem}). Va invocata con tre argomenti. Occorre + avere il permesso di lettura. \item[\const{SETALL}] Inizializza il valore di tutti i semafori dell'insieme, aggiornando il campo \var{sem\_ctime} di \struct{semid\_ds}. I valori devono essere passati nel vettore indicato da \param{arg.array}. Si devono avere i - privilegi di scrittura sul semaforo. L'argomento \param{semnum} viene - ignorato. + privilegi di scrittura. L'argomento \param{semnum} viene ignorato. \item[\const{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di - \struct{semid\_ds}. Si devono avere i privilegi di scrittura sul semaforo. + \struct{semid\_ds}. Si devono avere i privilegi di scrittura. \end{basedescript} Come per \func{msgctl} esistono tre ulteriori valori, \const{IPC\_INFO}, @@ -2200,52 +2200,92 @@ 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 \funcd{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[\errcode{EACCES}] il processo non ha i privilegi per eseguire - l'operazione richiesta. - \item[\errcode{EIDRM}] l'insieme di semafori è stato cancellato. - \item[\errcode{ENOMEM}] si è richiesto un \const{SEM\_UNDO} ma il sistema - non ha le risorse per allocare la struttura di ripristino. +vengono effettuate con la funzione di sistema \funcd{semop}, il cui prototipo +è: + +\begin{funcproto}{ +\fhead{sys/types.h} +\fhead{sys/ipc.h} +\fhead{sys/sem.h} +\fdecl{int semop(int semid, struct sembuf *sops, unsigned nsops)} +\fdesc{Esegue operazioni ordinarie su un semaforo o un insieme di semafori.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{E2BIG}] l'argomento \param{nsops} è maggiore del numero + massimo di operazioni \const{SEMOPM}. + \item[\errcode{EACCES}] il processo non ha i permessi per eseguire + l'operazione richiesta e non ha i privilegi di amministratore. \item[\errcode{EAGAIN}] un'operazione comporterebbe il blocco del processo, ma si è specificato \const{IPC\_NOWAIT} in \var{sem\_flg}. + \item[\errcode{EFBIG}] il valore del campo \var{sem\_num} è negativo o + maggiore o uguale al numero di semafori dell'insieme. + \item[\errcode{EIDRM}] l'insieme di semafori è stato cancellato. \item[\errcode{EINTR}] la funzione, bloccata in attesa dell'esecuzione dell'operazione, viene interrotta da un segnale. - \item[\errcode{E2BIG}] l'argomento \param{nsops} è maggiore del numero - massimo di operazioni \const{SEMOPM}. + \item[\errcode{ENOMEM}] si è richiesto un \const{SEM\_UNDO} ma il sistema + non ha le risorse per allocare la struttura di ripristino. \item[\errcode{ERANGE}] per alcune operazioni il valore risultante del semaforo viene a superare il limite massimo \const{SEMVMX}. \end{errlist} - ed inoltre \errval{EFAULT} ed \errval{EINVAL}. -} -\end{functions} - - -%TODO manca semtimedop, trattare qui, referenziata in -%sez.~\ref{sec:sig_gen_beha}. + ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato + generico.} +\end{funcproto} 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 +\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 \struct{sembuf} nell'argomento \param{sops}. Le operazioni richieste vengono -effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante. +effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante, +ed in tal caso vengono eseguite nella sequenza passata nel +vettore \param{sops}. + +Con lo standard POSIX.1-2001 è stata introdotta una variante di \func{semop} +che consente di specificare anche un tempo massimo di attesa. La nuova +funzione di sistema, disponibile a partire dal kernel 2.4.22 e dalle +\acr{glibc} 2.3.3, ed utilizzabile solo dopo aver definito la macro +\macro{\_GNU\_SOURCE}, è \funcd{semtimedop}, ed il suo prototipo è: + +\begin{funcproto}{ +\fhead{sys/types.h} +\fhead{sys/ipc.h} +\fhead{sys/sem.h} +\fdecl{int semtimedop(int semid, struct sembuf *sops, unsigned nsops, + struct timespec *timeout)} +\fdesc{Esegue operazioni ordinarie su un semaforo o un insieme di semafori.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EAGAIN}] l'operazione comporterebbe il blocco del processo, + ma si è specificato \const{IPC\_NOWAIT} in \var{sem\_flg} oppure si è + atteso oltre quanto indicato da \param{timeout}. + \end{errlist} + e gli altri valori già visti per \func{semop}, con lo stesso significato.} +\end{funcproto} + +Rispetto a \func{semop} la funzione consente di specificare un tempo massimo +di attesa, indicato con una struttura \struct{timespec} (vedi +fig.~\ref{fig:sys_timespec_struct}), per le operazioni che verrebbero +bloccate. Alla scadenza di detto tempo la funzione ritorna comunque con un +errore di \errval{EAGAIN} senza che nessuna delle operazioni richieste venga +eseguita. + +Si tenga presente che la precisione della temporizzazione è comunque limitata +dalla risoluzione dell'orologio di sistema, per cui il tempo di attesa verrà +arrotondato per eccesso. In caso si passi un valore \val{NULL} +per \param{timeout} il comportamento di \func{semtimedop} è identico a quello +di \func{semop}. + \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{.80\textwidth} \includestruct{listati/sembuf.h} \end{minipage} \normalsize @@ -2254,65 +2294,73 @@ effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante. \label{fig:ipc_sembuf} \end{figure} -Il contenuto di ciascuna operazione deve essere specificato attraverso una -opportuna struttura \struct{sembuf} (la cui definizione è riportata in +Come indicato il contenuto di ciascuna operazione deve essere specificato +attraverso una struttura \struct{sembuf} (la cui definizione è riportata in fig.~\ref{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. +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}. +riferimento l'operazione. Si ricordi che i semafori sono numerati come gli +elementi di un vettore, per cui il primo semaforo di un insieme 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 \const{IPC\_NOWAIT} e -\const{SEM\_UNDO}. Impostando \const{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 \errcode{EAGAIN}. Impostando \const{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: +\const{SEM\_UNDO}. Impostando \const{IPC\_NOWAIT} si fa si che in tutti quei +casi in cui l'esecuzione di una operazione richiederebbe di porre il processo +vada nello stato di \textit{sleep}, invece di bloccarsi \func{semop} ritorni +immediatamente (abortendo così le eventuali operazioni restanti) con un errore +di \errcode{EAGAIN}. Impostando \const{SEM\_UNDO} si richiede invece che +l'operazione in questione venga registrata, in modo che il valore del semaforo +possa essere ripristinato all'uscita del processo. + +Infine \var{sem\_op} è il campo che controlla qual'è l'operazione che viene +eseguita e determina in generale il comportamento della chiamata a +\func{semop}. I casi possibili per il valore di questo campo sono tre: \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 \errcode{ERANGE} qualora si sia superato il - limite \const{SEMVMX}) ed il processo non viene bloccato in nessun caso. - Specificando \const{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$] In questo caso il valore viene aggiunto al valore + corrente di \var{semval} per il semaforo indicato. Questa operazione non + causa mai un blocco del processo, ed eventualmente \func{semop} ritorna + immediatamente con un errore di \errcode{ERANGE} qualora si sia superato il + limite \const{SEMVMX}. Se l'operazione ha successo si passa immediatamente + alla successiva. Specificando \const{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 \const{IPC\_NOWAIT} la - funzione ritorna con un errore di \errcode{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: +\item[\var{sem\_op} $=0$] Nel caso \var{semval} sia zero l'operazione ha + successo immediato, e o si passa alla successiva o \func{semop} ritorna con + successo se questa era l'ultima. Se \var{semval} è diverso da zero il + comportamento è controllato da \var{sem\_flg}, se è stato impostato + \const{IPC\_NOWAIT} \func{semop} ritorna immediatamente abortendo tutte le + operazioni con un errore di \errcode{EAGAIN}, altrimenti viene incrementato + \var{semzcnt} di uno ed il processo viene bloccato fintanto che non si + verifica 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 \errcode{EIDRM}. + decrementato di uno, l'operazione ha successo e si passa alla successiva, + oppure \func{semop} ritorna con successo se questa era l'ultima. + \item l'insieme di semafori viene rimosso, nel qual caso \func{semop} + ritorna abortendo tutte le operazioni con un errore di \errcode{EIDRM}. \item il processo chiamante riceve un segnale, nel qual caso \var{semzcnt} - viene decrementato di uno e \func{semop} ritorna un errore di - \errcode{EINTR}. + viene decrementato di uno e \func{semop} ritorna abortendo tutte le + operazioni con un errore di \errcode{EINTR}. \end{itemize*} - Al processo chiamante è richiesto il privilegio di lettura dell'insieme dei - semafori. + Al processo chiamante è richiesto soltanto il privilegio di lettura + dell'insieme dei semafori. -\item[\var{sem\_op}$<0$] Nel caso in cui \var{semval} è maggiore o uguale del +\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 \const{SEM\_UNDO} viene anche + positiva o nulla) i valori vengono sommati e l'operazione ha successo e si + passa alla successiva, oppure \func{semop} ritorna con successo se questa + era l'ultima. Qualora si sia impostato \const{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 \const{IPC\_NOWAIT} la funzione ritorna con un - errore di \errcode{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: + negativo) se si è impostato \const{IPC\_NOWAIT} \func{semop} ritorna + immediatamente abortendo tutte le operazioni con un errore di + \errcode{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 @@ -2320,39 +2368,46 @@ possibili: impostato \const{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 \errcode{EIDRM}. + ritorna abortendo tutte le operazioni con un errore di \errcode{EIDRM}. \item il processo chiamante riceve un segnale, nel qual caso \var{semncnt} - viene decrementato di uno e \func{semop} ritorna un errore di - \errcode{EINTR}. + viene decrementato di uno e \func{semop} ritorna abortendo tutte le + operazioni con un errore di \errcode{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 il campo \var{sempid} per -ogni semaforo modificato al valore del \ids{PID} del processo chiamante; -inoltre vengono pure aggiornati al tempo corrente i campi \var{sem\_otime} e -\var{sem\_ctime}. +Qualora si sia usato \func{semtimedop} alle condizioni di errore precedenti si +aggiunge anche quella di scadenza del tempo di attesa indicato +con \param{timeout} che farà abortire la funzione, qualora resti bloccata +troppo a lungo nell'esecuzione delle operazioni richieste, con un errore di +\errcode{EAGAIN}. + +In caso di successo (sia per \func{semop} che per \func{semtimedop}) per ogni +semaforo modificato verrà aggiornato il campo \var{sempid} al valore del +\ids{PID} del processo chiamante; inoltre verranno 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 -\const{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura -\kstruct{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 passano inalterate nell'esecuzione di -una \func{exec} (altrimenti non si avrebbe ripristino). +semafori possono restare occupati, abbiamo visto come \func{semop} (e +\func{semtimedop}) permetta di attivare un meccanismo di ripristino attraverso +l'uso del flag \const{SEM\_UNDO}. Il meccanismo è implementato tramite una +apposita struttura \kstruct{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 passano +inalterate nell'esecuzione di una \func{exec} (altrimenti non si avrebbe +ripristino). Tutto questo però ha un problema di fondo. Per capire di cosa si tratta occorre fare riferimento all'implementazione usata in Linux, che è riportata in maniera semplificata nello schema di fig.~\ref{fig:ipc_sem_schema}. Si è presa come riferimento l'architettura usata fino al kernel 2.2.x che è più -semplice (ed illustrata in dettaglio in \cite{tlk}); nel kernel 2.4.x la +semplice (ed illustrata in dettaglio in \cite{tlk}). Nel kernel 2.4.x la struttura del \textit{SysV-IPC} è stata modificata, ma le definizioni relative -a queste strutture restano per compatibilità.\footnote{in particolare con le - vecchie versioni delle librerie del C, come le libc5.} +a queste strutture restano per compatibilità (in particolare con le vecchie +versioni delle librerie del C, come le \acr{libc5}). \begin{figure}[!htb] \centering \includegraphics[width=13cm]{img/semtruct} @@ -2364,16 +2419,15 @@ Alla creazione di un nuovo insieme viene allocata una nuova strutture \struct{semid\_ds} ed il relativo vettore di strutture \struct{sem}. Quando si richiede una operazione viene anzitutto verificato che tutte le operazioni possono avere successo; se una di esse comporta il blocco del processo il -kernel crea una struttura \kstruct{sem\_queue} che viene aggiunta in fondo alla -coda di attesa associata a ciascun insieme di semafori\footnote{che viene - referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last} - di \struct{semid\_ds}.}. - -Nella struttura viene memorizzato il riferimento alle operazioni richieste -(nel campo \var{sops}, che è un puntatore ad una struttura \struct{sembuf}) e -al processo corrente (nel campo \var{sleeper}) poi quest'ultimo viene messo -stato di attesa e viene invocato lo \itindex{scheduler} scheduler per passare -all'esecuzione di un altro processo. +kernel crea una struttura \kstruct{sem\_queue} che viene aggiunta in fondo +alla coda di attesa associata a ciascun insieme di semafori, che viene +referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last} di +\struct{semid\_ds}. Nella struttura viene memorizzato il riferimento alle +operazioni richieste (nel campo \var{sops}, che è un puntatore ad una +struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper}) +poi quest'ultimo viene messo stato di attesa e viene invocato lo +\itindex{scheduler} \textit{scheduler} per passare all'esecuzione di un altro +processo. Se invece tutte le operazioni possono avere successo queste vengono eseguite immediatamente, dopo di che il kernel esegue una scansione della coda di @@ -2389,21 +2443,18 @@ contiene (nel vettore puntato dal campo \var{semadj}) un valore di aggiustamento per ogni semaforo cui viene sommato l'opposto del valore usato per l'operazione. -%TODO verificare queste strutture \kstruct{sem\_queue} e \kstruct{sem\_undo} - -Queste strutture sono mantenute in due liste,\footnote{rispettivamente - attraverso i due campi \var{id\_next} e \var{proc\_next}.} una associata -all'insieme di cui fa parte il semaforo, che viene usata per invalidare le -strutture se questo viene cancellato o per azzerarle se si è eseguita una -operazione con \func{semctl}; l'altra associata al processo che ha eseguito -l'operazione;\footnote{attraverso il campo \var{semundo} di - \kstruct{task\_struct}, come mostrato in \ref{fig:ipc_sem_schema}.} quando un -processo termina, la lista ad esso associata viene scandita e le operazioni -applicate al semaforo. Siccome un processo può accumulare delle richieste di -ripristino per semafori differenti chiamate attraverso diverse chiamate a -\func{semop}, si pone il problema di come eseguire il ripristino dei semafori -all'uscita del processo, ed in particolare se questo può essere fatto -atomicamente. +Queste strutture sono mantenute in due liste (rispettivamente attraverso i due +campi \var{id\_next} e \var{proc\_next}) una associata all'insieme di cui fa +parte il semaforo, che viene usata per invalidare le strutture se questo viene +cancellato o per azzerarle se si è eseguita una operazione con \func{semctl}, +l'altra associata al processo che ha eseguito l'operazione, attraverso il +campo \var{semundo} di \kstruct{task\_struct}, come mostrato in +\ref{fig:ipc_sem_schema}. Quando un processo termina, la lista ad esso +associata viene scandita e le operazioni applicate al semaforo. Siccome un +processo può accumulare delle richieste di ripristino per semafori differenti +attraverso diverse chiamate a \func{semop}, si pone il problema di come +eseguire il ripristino dei semafori all'uscita del processo, ed in particolare +se questo può essere fatto atomicamente. Il punto è cosa succede quando una delle operazioni previste per il ripristino non può essere eseguita immediatamente perché ad esempio il semaforo è @@ -2499,20 +2550,20 @@ problemi, usando il \itindex{file~locking} \textit{file locking}. \label{sec:ipc_sysv_shm} Il terzo oggetto introdotto dal \textit{SysV-IPC} è quello dei segmenti di -memoria condivisa. La funzione che permette di ottenerne uno è \funcd{shmget}, -ed il suo prototipo è: -\begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/ipc.h} - \headdecl{sys/shm.h} - - \funcdecl{int shmget(key\_t key, int size, int flag)} - - Restituisce l'identificatore di una memoria condivisa. - - \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1 - in caso di errore, nel qual caso \var{errno} assumerà i valori: - \begin{errlist} +memoria condivisa. La funzione di sistema che permette di ottenerne uno è +\funcd{shmget}, ed il suo prototipo è: + +\begin{funcproto}{ +\fhead{sys/types.h} +\fhead{sys/ipc.h} +\fhead{sys/shm.h} +\fdecl{int shmget(key\_t key, int size, int flag)} +\fdesc{Ottiene o crea una memoria condivisa.} +} + +{La funzione ritorna l'identificatore (un intero positivo) in caso di successo + e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} \item[\errcode{ENOSPC}] si è superato il limite (\const{SHMMNI}) sul numero di segmenti di memoria nel sistema, o cercato di allocare un segmento le cui dimensioni fanno superare il limite di sistema (\const{SHMALL}) per @@ -2522,10 +2573,11 @@ ed il suo prototipo è: già esiste \param{size} è maggiore delle sue dimensioni. \item[\errcode{ENOMEM}] il sistema non ha abbastanza memoria per poter contenere le strutture per un nuovo segmento di memoria condivisa. - \end{errlist} - ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST}, - \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.} -\end{functions} + \end{errlist} + ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST}, + \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.} +\end{funcproto} + La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed identico è l'uso degli argomenti \param{key} e \param{flag} per cui non @@ -4766,7 +4818,7 @@ testo alla terminazione di quest'ultimo. % LocalWords: FortuneServer FortuneParse FortuneClient pid libgapil LD librt % LocalWords: PATH linker pathname ps tmp killall fortuned crash socket domain % LocalWords: socketpair BSD sys protocol sv EAFNOSUPPORT EPROTONOSUPPORT AF -% LocalWords: EOPNOTSUPP SOCK Process Comunication ipc perm key exec +% LocalWords: EOPNOTSUPP SOCK Process Comunication ipc perm key exec pipefd SZ % LocalWords: header ftok proj stat libc SunOS glibc XPG dell'inode number uid % LocalWords: cuid cgid gid tab MSG shift group umask seq MSGMNI SEMMNI SHMMNI % LocalWords: shmmni msgmni sem sysctl IPCMNI IPCTestId msgget EACCES EEXIST @@ -4788,7 +4840,7 @@ testo alla terminazione di quest'ultimo. % LocalWords: dtime lpid cpid nattac shmall shmmax SHMLBA SHMSEG EOVERFLOW brk % LocalWords: memory shmat shmdt void shmaddr shmflg SVID RND RDONLY rounded % LocalWords: SIGSEGV nattch exit SharedMem ShmCreate memset fill ShmFind home -% LocalWords: ShmRemove DirMonitor DirProp chdir GaPiL shmptr ipcs NFS +% LocalWords: ShmRemove DirMonitor DirProp chdir GaPiL shmptr ipcs NFS SETPIPE % LocalWords: ComputeValues ReadMonitor touch SIGTERM dirmonitor unlink fcntl % LocalWords: LockFile UnlockFile CreateMutex FindMutex LockMutex SETLKW GETLK % LocalWords: UnlockMutex RemoveMutex ReadMutex UNLCK WRLCK RDLCK mapping MAP @@ -4801,17 +4853,19 @@ testo alla terminazione di quest'ultimo. % LocalWords: EBUSY sigev SIGNAL signo value sigval siginfo all'userid MESGQ % LocalWords: Konstantin Knizhnik futex tmpfs ramfs cache shared swap CONFIG % LocalWords: lrt blocks PAGECACHE TRUNC CLOEXEC mmap ftruncate munmap FindShm -% LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED has +% LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED has fclose % LocalWords: ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait % LocalWords: process getvalue sval execve pshared ENOSYS heap PAGE destroy it % LocalWords: xffffffff Arrays owner perms Queues used bytes messages device % LocalWords: Cannot find such Segments getter Signal MSGMAXSIZE been stable % LocalWords: for now it's break Berlin sources Let's an accidental feature % LocalWords: Larry Wall Escape the Hell William ipctestid Identifier segment -% LocalWords: violation dell'I SIGINT setter Fri Dec Sleeping seconds +% LocalWords: violation dell'I SIGINT setter Fri Dec Sleeping seconds ECHILD %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: +% LocalWords: SysV capability short RESOURCE INFO UNDEFINED EFBIG semtimedop +% LocalWords: scan