X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=48cc7b89ae2b35f627671433bce6fc2ff4b0027c;hp=520793d20023a7457032fe6a94bf03e261c7f1b1;hb=beece18eba2dcc2a9b915dab61277df8685a3da6;hpb=c53a9c94d93ca614b786db4f49176a4659e453e8 diff --git a/ipc.tex b/ipc.tex index 520793d..48cc7b8 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1,6 +1,6 @@ %% ipc.tex %% -%% Copyright (C) 2000-2013 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2014 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -200,9 +200,9 @@ Un programma che deve essere eseguito come \textit{CGI} deve rispondere a delle caratteristiche specifiche, esso infatti non viene lanciato da una shell, ma dallo stesso web server, alla richiesta di una specifica URL, che di solito ha la forma: -\begin{Verbatim} +\begin{Example} http://www.sito.it/cgi-bin/programma?argomento -\end{Verbatim} +\end{Example} ed il risultato dell'elaborazione deve essere presentato (con una intestazione che ne descrive il \textit{mime-type}) sullo \textit{standard output}, in modo che il server web possa reinviarlo al browser che ha effettuato la richiesta, @@ -690,9 +690,9 @@ stringa di richiesta dalla \textit{fifo} nota (che a questo punto si bloccherà tutte le volte che non ci sono richieste). Dopo di che, una volta terminata la stringa (\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per ricavare la frase da inviare, si procederà (\texttt{\small - 42--46}) all'apertura della \textit{fifo} per la risposta, che poi -\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si chiude -la \textit{fifo} di risposta che non serve più. + 42--46}) all'apertura della \textit{fifo} per la risposta, che poi +(\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si +chiude la \textit{fifo} di risposta che non serve più. Il codice del client è invece riportato in fig.~\ref{fig:ipc_fifo_client}, anche in questo caso si è omessa la gestione delle opzioni e la funzione che @@ -1422,7 +1422,7 @@ file; il suo prototipo è: \var{msg\_qbytes} oltre il limite \const{MSGMNB} senza essere amministratore. \end{errlist} - ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato + ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato generico.} \end{funcproto} @@ -1839,7 +1839,6 @@ dei \ids{PID} da parte dei processi, un client eseguito in un momento successivo potrebbe ricevere un messaggio non indirizzato a lui. - \subsection{I semafori} \label{sec:ipc_sysv_sem} @@ -1974,7 +1973,6 @@ quanto riguarda gli altri campi invece: effettuata, viene inizializzato a zero. \end{itemize*} - \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{.80\textwidth} @@ -2079,10 +2077,9 @@ 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}. - \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{.80\textwidth} + \begin{minipage}[c]{0.80\textwidth} \includestruct{listati/semun.h} \end{minipage} \normalsize @@ -2318,7 +2315,7 @@ 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}} +\begin{basedescript}{\desclabelwidth{1.8cm}} \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 @@ -2410,7 +2407,7 @@ 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} + \centering \includegraphics[width=12cm]{img/semtruct} \caption{Schema della struttura di un insieme di semafori.} \label{fig:ipc_sem_schema} \end{figure} @@ -2605,8 +2602,6 @@ delle pagine di swap ad uso del meccanismo del \textit{copy on write} significa che caso di scrittura sul segmento quando non c'è più memoria disponibile, si avrà l'emissione di un \signal{SIGSEGV}. -% TODO verificare i privilegi necessari per SHM_HUGETLB - Infine l'argomento \param{size} specifica la dimensione del segmento di memoria condivisa; il valore deve essere specificato in byte, ma verrà comunque arrotondato al multiplo superiore di \const{PAGE\_SIZE}. Il valore @@ -2635,7 +2630,7 @@ norma, significa insieme a dei semafori. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.80\textwidth} \includestruct{listati/shmid_ds.h} \end{minipage} \normalsize @@ -2652,7 +2647,7 @@ campo \var{shm\_perm} viene inizializzato come illustrato in sez.~\ref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte relativamente ai permessi di accesso; per quanto riguarda gli altri campi invece: -\begin{itemize} +\begin{itemize*} \item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene inizializzato al valore di \param{size}. \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del @@ -2666,7 +2661,7 @@ invece: creato il segmento, viene inizializzato al \ids{PID} del processo chiamante. \item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati al segmento viene inizializzato a zero. -\end{itemize} +\end{itemize*} Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti di memoria condivisa esistono una serie di limiti imposti dal sistema. Alcuni @@ -2786,7 +2781,7 @@ si ha a cuore la portabilità. Questi comandi aggiuntivi sono: sez.~\ref{sec:proc_mem_lock} fino al kernel 2.6.9 solo l'amministratore poteva utilizzare questa capacità,\footnote{che richiedeva la \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal dal kernel - 2.6.10 anche gli utenti normali possono farlo fina al limite massimo + 2.6.10 anche gli utenti normali possono farlo fino al limite massimo determinato da \const{RLIMIT\_MEMLOCK} (vedi sez.~\ref{sec:sys_resource_limit}). \item[\const{SHM\_UNLOCK}] Disabilita il \itindex{memory~locking} @@ -2833,7 +2828,6 @@ il suo prototipo è: per \param{shmaddr} o il valore \val{NULL} indicando \const{SHM\_REMAP}. \end{errlist} ed inoltre \errval{ENOMEM} nel suo significato generico. - } \end{funcproto} @@ -2906,14 +2900,14 @@ l'argomento \param{shmaddr} non può essere nullo. In caso di successo la funzione \func{shmat} aggiorna anche i seguenti campi della struttura \struct{shmid\_ds}: -\begin{itemize} +\begin{itemize*} \item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene impostato al tempo corrente. \item il \ids{PID} \var{shm\_lpid} dell'ultimo processo che ha operato sul segmento viene impostato a quello del processo corrente. \item il numero \var{shm\_nattch} di processi agganciati al segmento viene aumentato di uno. -\end{itemize} +\end{itemize*} Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa agganciato ad un processo viene ereditato da un figlio attraverso una @@ -3347,7 +3341,7 @@ alternativi. La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare dei \textsl{file di lock} (per i quali è stata anche riservata una opportuna directory, \file{/var/lock}, nella standardizzazione del \textit{Filesystem - Hyerarchy Standard}). Per questo si usa la caratteristica della funzione + Hierarchy Standard}). Per questo si usa la caratteristica della funzione \func{open} (illustrata in sez.~\ref{sec:file_open_close}) che prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non toglie che in alcune implementazioni questa tecnica possa non funzionare; in @@ -3530,12 +3524,14 @@ contenuto di un file nella memoria di un processo, e che, quando viene usato il flag \const{MAP\_SHARED}, le modifiche effettuate al contenuto del file vengono viste da tutti i processi che lo hanno mappato. Utilizzare questa tecnica per creare una memoria condivisa fra processi diversi è estremamente -inefficiente, in quanto occorre passare attraverso il disco. Però abbiamo -visto anche che se si esegue la mappatura con il flag \const{MAP\_ANONYMOUS} -la regione mappata non viene associata a nessun file, anche se quanto scritto -rimane in memoria e può essere riletto; allora, dato che un processo figlio -mantiene nel suo spazio degli indirizzi anche le regioni mappate, esso sarà -anche in grado di accedere a quanto in esse è contenuto. +inefficiente, in quanto occorre passare attraverso il disco. + +Però abbiamo visto anche che se si esegue la mappatura con il flag +\const{MAP\_ANONYMOUS} la regione mappata non viene associata a nessun file, +anche se quanto scritto rimane in memoria e può essere riletto; allora, dato +che un processo figlio mantiene nel suo spazio degli indirizzi anche le +regioni mappate, esso sarà anche in grado di accedere a quanto in esse è +contenuto. In questo modo diventa possibile creare una memoria condivisa fra processi diversi, purché questi abbiano almeno un progenitore comune che ha effettuato @@ -3599,66 +3595,64 @@ Data la assoluta genericità delle specifiche, il comportamento delle funzioni è subordinato in maniera quasi completa alla relativa implementazione, tanto che Stevens in \cite{UNP2} cita questo caso come un esempio della maniera standard usata dallo standard POSIX per consentire implementazioni non -standardizzabili. Nel caso di Linux, sia per quanto riguarda la memoria -condivisa ed i semafori, che per quanto riguarda le code di messaggi, tutto -viene creato usando come radici delle opportune directory (rispettivamente -\file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si faccia riferimento a -sez.~\ref{sec:ipc_posix_shm}, sez.~\ref{sec:ipc_posix_sem} e -sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni -sono considerati come un \itindsub{pathname}{assoluto} \textit{pathname} -assoluto (comprendente eventuali sottodirectory) rispetto a queste radici. +standardizzabili. + +Nel caso di Linux, sia per quanto riguarda la memoria condivisa ed i semafori, +che per le code di messaggi, tutto viene creato usando come radici delle +opportune directory (rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per +i dettagli si faccia riferimento a sez.~\ref{sec:ipc_posix_shm}, +sez.~\ref{sec:ipc_posix_sem} e sez.~\ref{sec:ipc_posix_mq}). I nomi +specificati nelle relative funzioni devono essere nella forma di un +\textit{pathname} assoluto (devono cioè iniziare con ``\texttt{/}'') e +corrisponderanno ad altrettanti file creati all'interno di queste directory; +per questo motivo detti nomi non possono contenere altre ``\texttt{/}'' oltre +quella iniziale. Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti nell'albero dei file, e possono essere maneggiati con le usuali funzioni e -comandi di accesso ai file, che funzionano come su dei file normali; questo +comandi di accesso ai file, che funzionano come su dei file normali. Questo però è vero nel caso di Linux, che usa una implementazione che lo consente, non è detto che altrettanto valga per altri kernel. In particolare, come si -può facilmente verificare con uno \cmd{strace}, sia per la memoria condivisa -che per le code di messaggi le system call utilizzate da Linux sono le stesse -di quelle dei file, essendo detti oggetti realizzati come tali in appositi -filesystem. +può facilmente verificare con il comando \cmd{strace}, sia per la memoria +condivisa che per le code di messaggi varie \textit{system call} utilizzate da +Linux corrispondono in realtà a quelle ordinarie dei file, essendo detti +oggetti realizzati come tali in appositi filesystem. In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai permessi dei file, ed il controllo di accesso segue esattamente la stessa semantica (quella illustrata in sez.~\ref{sec:file_access_control}), e non quella particolare (si ricordi quanto visto in sez.~\ref{sec:ipc_sysv_access_control}) che viene usata per gli oggetti del -SysV-IPC. Per quanto riguarda l'attribuzione dell'utente e del gruppo +SysV-IPC. Per quanto riguarda l'attribuzione dell'utente e del gruppo proprietari dell'oggetto alla creazione di quest'ultimo essa viene effettuata secondo la semantica SysV: corrispondono cioè a \ids{UID} e \ids{GID} effettivi del processo che esegue la creazione. -\subsection{Code di messaggi} +\subsection{Code di messaggi Posix} \label{sec:ipc_posix_mq} Le code di messaggi POSIX sono supportate da Linux a partire dalla versione -2.6.6-rc1 del kernel,\footnote{l'implementazione è dovuta a Michal Wronski e - Krzysztof Benedyczak, e le relative informazioni si possono trovare su - \url{http://www.geocities.com/wronski12/posix_ipc/index.html}.} In generale, -come le corrispettive del \textit{SysV-IPC}, le code di messaggi sono poco -usate, dato che i socket, nei casi in cui sono sufficienti, sono più comodi, e -che in casi più complessi la comunicazione può essere gestita direttamente con -mutex (o semafori) e memoria condivisa con tutta la flessibilità che occorre. +2.6.6 del kernel. In generale, come le corrispettive del \textit{SysV-IPC}, le +code di messaggi sono poco usate, dato che i socket, nei casi in cui sono +sufficienti, sono più comodi, e che in casi più complessi la comunicazione può +essere gestita direttamente con mutex (o semafori) e memoria condivisa con +tutta la flessibilità che occorre. Per poter utilizzare le code di messaggi, oltre ad utilizzare un kernel -superiore al 2.6.6 (o precedente, se sono stati opportunamente applicati i -relativi patch) occorre utilizzare la libreria \file{libmqueue}\footnote{i - programmi che usano le code di messaggi cioè devono essere compilati - aggiungendo l'opzione \code{-lmqueue} al comando \cmd{gcc}; in - corrispondenza all'inclusione del supporto nel kernel ufficiale anche - \file{libmqueue} è stata inserita nella \acr{glibc}, a partire dalla - versione 2.3.4 delle medesime.} che contiene le funzioni dell'interfaccia -POSIX.\footnote{in realtà l'implementazione è realizzata tramite delle - opportune chiamate ad \func{ioctl} sui file del filesystem speciale su cui - vengono mantenuti questi oggetti di IPC.} +superiore al 2.6.6 occorre utilizzare la libreria \file{librt} che contiene le +funzioni dell'interfaccia POSIX ed i programmi che usano le code di messaggi +devono essere compilati aggiungendo l'opzione \code{-lrt} al comando +\cmd{gcc}. In corrispondenza all'inclusione del supporto nel kernel ufficiale +le funzioni di libreria sono state inserite nella \acr{glibc}, e sono +disponibili a partire dalla versione 2.3.4 delle medesime. La libreria inoltre richiede la presenza dell'apposito filesystem di tipo -\texttt{mqueue} montato su \file{/dev/mqueue}; questo può essere fatto -aggiungendo ad \conffile{/etc/fstab} una riga come: -\begin{verbatim} +\texttt{mqueue} montato sulla directory \file{/dev/mqueue}; questo può essere +fatto aggiungendo ad \conffile{/etc/fstab} una riga come: +\begin{FileExample}[label=/etc/fstab] mqueue /dev/mqueue mqueue defaults 0 0 -\end{verbatim} +\end{FileExample} ed esso sarà utilizzato come radice sulla quale vengono risolti i nomi delle code di messaggi che iniziano con una ``\texttt{/}''. Le opzioni di mount accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono @@ -3666,54 +3660,63 @@ rispettivamente di impostare l'utente, il gruppo ed i permessi associati al filesystem. -La funzione che permette di aprire (e crearla se non esiste ancora) una coda -di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è: -\begin{functions} - \headdecl{mqueue.h} - - \funcdecl{mqd\_t mq\_open(const char *name, int oflag)} - - \funcdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode, +La funzione di sistema che permette di aprire (e crearla se non esiste ancora) +una coda di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è: + +\begin{funcproto}{ +\fhead{fcntl.h} +\fhead{sys/stat.h} +\fhead{mqueue.h} +\fdecl{mqd\_t mq\_open(const char *name, int oflag)} +\fdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode, struct mq\_attr *attr)} - - Apre una coda di messaggi POSIX impostandone le caratteristiche. - - \bodydesc{La funzione restituisce il descrittore associato alla coda in caso - di successo e -1 per un errore; nel quel caso \var{errno} assumerà i - valori: - \begin{errlist} - \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al - alla memoria secondo quanto specificato da \param{oflag}. - \item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e - \const{O\_EXCL} ma la coda già esiste. - \item[\errcode{EINVAL}] il file non supporta la funzione, o si è - specificato \const{O\_CREAT} con una valore non nullo di \param{attr} e - valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}. - \item[\errcode{ENOENT}] non si è specificato \const{O\_CREAT} ma la coda - non esiste. - \end{errlist} - ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT}, - \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE}. + +\fdesc{Apre una coda di messaggi POSIX impostandone le caratteristiche.} } -\end{functions} + +{La funzione ritorna il descrittore associato alla coda in caso di successo e + $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCES}] il processo non ha i privilegi per accedere alla + coda secondo quanto specificato da \param{oflag} oppure \const{name} + contiene più di una ``\texttt{/}''. + \item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e \const{O\_EXCL} + ma la coda già esiste. + \item[\errcode{EINVAL}] il file non supporta la funzione, o si è specificato + \const{O\_CREAT} con una valore non nullo di \param{attr} e valori non + validi dei campi \var{mq\_maxmsg} e \var{mq\_msgsize}; questi valori + devono essere positivi ed inferiori ai limiti di sistema se il processo + non ha privilegi amministrativi, inoltre \var{mq\_maxmsg} non può comunque + superare \const{HARD\_MAX}. + \item[\errcode{ENOENT}] non si è specificato \const{O\_CREAT} ma la coda non + esiste o si è usato il nome ``\texttt{/}''. + \item[\errcode{ENOSPC}] lo spazio è insufficiente, probabilmente per aver + superato il limite di \texttt{queues\_max}. + \end{errlist} + ed inoltre \errval{EMFILE}, \errval{ENAMETOOLONG}, \errval{ENFILE}, + \errval{ENOMEM} ed nel loro significato generico. } +\end{funcproto} La funzione apre la coda di messaggi identificata dall'argomento \param{name} restituendo il descrittore ad essa associato, del tutto analogo ad un file descriptor, con l'unica differenza che lo standard prevede un apposito tipo -\type{mqd\_t}.\footnote{nel caso di Linux si tratta in effetti proprio di un - normale file descriptor; pertanto, anche se questo comportamento non è - portabile, lo si può tenere sotto osservazione con le funzioni dell'I/O - multiplexing (vedi sez.~\ref{sec:file_multiplexing}) come possibile - alternativa all'uso dell'interfaccia di notifica di \func{mq\_notify} (che - vedremo a breve).} Se la coda esiste già il descrittore farà riferimento -allo stesso oggetto, consentendo così la comunicazione fra due processi -diversi. +\type{mqd\_t}. Nel caso di Linux si tratta in effetti proprio di un normale +file descriptor; pertanto, anche se questo comportamento non è portabile, lo +si può tenere sotto osservazione con le funzioni dell'I/O multiplexing (vedi +sez.~\ref{sec:file_multiplexing}) come possibile alternativa all'uso +dell'interfaccia di notifica di \func{mq\_notify} (che vedremo a breve). + +Se il nome indicato fa riferimento ad una coda di messaggi già esistente, il +descrittore ottenuto farà riferimento allo stesso oggetto, pertanto tutti i +processi che hanno usato \func{mq\_open} su quel nome otterranno un +riferimento alla stessa coda. Diventa così immediato costruire un canale di +comunicazione fra detti processi. La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che possono essere specificati per \param{oflag}, che deve essere specificato come maschera binaria; i valori possibili per i vari bit sono quelli visti in -sez.~\ref{sec:file_open_close} dei quali però \func{mq\_open} riconosce solo i -seguenti: +sez.~\ref{sec:file_open_close} (per questo occorre includere \texttt{fcntl.h}) +dei quali però \func{mq\_open} riconosce solo i seguenti: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} \item[\const{O\_RDONLY}] Apre la coda solo per la ricezione di messaggi. Il processo potrà usare il descrittore con \func{mq\_receive} ma non con @@ -3745,15 +3748,17 @@ Se la coda non esiste e la si vuole creare si deve specificare creazione con l'argomento \param{mode};\footnote{fino al 2.6.14 per un bug i valori della \textit{umask} del processo non venivano applicati a questi permessi.} i valori di quest'ultimo sono identici a quelli usati per -\func{open}, anche se per le code di messaggi han senso solo i permessi di -lettura e scrittura. Oltre ai permessi di creazione possono essere specificati -anche gli attributi specifici della coda tramite l'argomento \param{attr}; -quest'ultimo è un puntatore ad una apposita struttura \struct{mq\_attr}, la -cui definizione è riportata in fig.~\ref{fig:ipc_mq_attr}. +\func{open} (per questo occorre includere \texttt{sys/stat.h}), anche se per +le code di messaggi han senso solo i permessi di lettura e scrittura. + +Oltre ai permessi di creazione possono essere specificati anche gli attributi +specifici della coda tramite l'argomento \param{attr}; quest'ultimo è un +puntatore ad una apposita struttura \struct{mq\_attr}, la cui definizione è +riportata in fig.~\ref{fig:ipc_mq_attr}. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.90\textwidth} \includestruct{listati/mq_attr.h} \end{minipage} \normalsize @@ -3766,51 +3771,101 @@ Per la creazione della coda i campi della struttura che devono essere specificati sono \var{mq\_maxmsg} e \var{mq\_msgsize}, che indicano rispettivamente il numero massimo di messaggi che può contenere e la dimensione massima di un messaggio. Il valore dovrà essere positivo e minore -dei rispettivi limiti di sistema \const{MQ\_MAXMSG} e \const{MQ\_MSGSIZE}, -altrimenti la funzione fallirà con un errore di \errcode{EINVAL}. -Se \param{attr} è un puntatore nullo gli attributi della coda saranno -impostati ai valori predefiniti. +dei rispettivi limiti di sistema altrimenti la funzione fallirà con un errore +di \errcode{EINVAL}. Se \param{attr} è un puntatore nullo gli attributi della +coda saranno impostati ai valori predefiniti. + +I suddetti limiti di sistema sono impostati attraverso altrettanti file in +\texttt{/proc/sys/fs/mqueue}, in particolare i file che controllano i valori +dei limiti sono: +\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}} +\item[\sysctlfile{fs/mqueue/msg\_max}] Indica il valore massimo del numero di + messaggi in una coda e agisce come limite superiore per il valore di + \var{attr->mq\_maxmsg} in \func{mq\_open}. Il suo valore di default è 10. Il + valore massimo è \const{HARD\_MAX} che vale \code{(131072/sizeof(void *))}, + ed il valore minimo 1 (ma era 10 per i kernel precedenti il 2.6.28). Questo + limite viene ignorato per i processi con privilegi amministrativi (più + precisamente con la \itindex{capability} \textit{capability} + \const{CAP\_SYS\_RESOURCE}) ma \const{HARD\_MAX} resta comunque non + superabile. + +\item[\sysctlfile{fs/mqueue/msgsize\_max}] Indica il valore massimo della + dimensione in byte di un messaggio sulla coda ed agisce come limite + superiore per il valore di \var{attr->mq\_msgsize} in \func{mq\_open}. Il + suo valore di default è 8192. Il valore massimo è 1048576 ed il valore + minimo 128 (ma per i kernel precedenti il 2.6.28 detti limiti erano + rispettivamente \const{INT\_MAX} e 8192). Questo limite viene ignorato dai + processi con privilegi amministrativi (con la \itindex{capability} + \textit{capability} \const{CAP\_SYS\_RESOURCE}). + +\item[\sysctlfile{fs/mqueue/queues\_max}] Indica il numero massimo di code di + messaggi creabili in totale sul sistema, il valore di default è 256 ma si + può usare un valore qualunque fra $0$ e \const{INT\_MAX}. Il limite non + viene applicato ai processi con privilegi amministrativi (cioè con la + \itindex{capability} \textit{capability} \const{CAP\_SYS\_RESOURCE}). + +\end{basedescript} + +Infine sulle code di messaggi si applica il limite imposto sulla risorsa +\const{RLIMIT\_MSGQUEUE} (vedi sez.~\ref{sec:sys_resource_limit}) che indica +lo spazio massimo (in byte) occupabile dall'insieme di tutte le code di +messaggi appartenenti ai processi di uno stesso utente, che viene identificato +in base al \textit{real user ID} degli stessi. Quando l'accesso alla coda non è più necessario si può chiudere il relativo descrittore con la funzione \funcd{mq\_close}, il cui prototipo è: -\begin{prototype}{mqueue.h} -{int mq\_close(mqd\_t mqdes)} -Chiude la coda \param{mqdes}. - -\bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore; - nel quel caso \var{errno} assumerà i valori \errval{EBADF} o - \errval{EINTR}.} -\end{prototype} +\begin{funcproto}{ +\fhead{mqueue.h} +\fdecl{int mq\_close(mqd\_t mqdes)} -La funzione è analoga a \func{close},\footnote{in Linux, dove le code sono - implementate come file su un filesystem dedicato, è esattamente la stessa - funzione.} dopo la sua esecuzione il processo non sarà più in grado di usare -il descrittore della coda, ma quest'ultima continuerà ad esistere nel sistema -e potrà essere acceduta con un'altra chiamata a \func{mq\_open}. All'uscita di -un processo tutte le code aperte, così come i file, vengono chiuse -automaticamente. Inoltre se il processo aveva agganciato una richiesta di -notifica sul descrittore che viene chiuso, questa sarà rilasciata e potrà -essere richiesta da qualche altro processo. +\fdesc{Chiude una coda di messaggi.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori \errval{EBADF} o \errval{EINTR} nel + loro significato generico. +} +\end{funcproto} +La funzione è analoga a \func{close},\footnote{su Linux, dove le code sono + implementate come file su un filesystem dedicato, è esattamente la stessa + funzione, per cui non esiste una \textit{system call} autonoma e la funzione + viene rimappata su \func{close} dalle \acr{glibc}.} dopo la sua esecuzione +il processo non sarà più in grado di usare il descrittore della coda, ma +quest'ultima continuerà ad esistere nel sistema e potrà essere acceduta con +un'altra chiamata a \func{mq\_open}. All'uscita di un processo tutte le code +aperte, così come i file, vengono chiuse automaticamente. Inoltre se il +processo aveva agganciato una richiesta di notifica sul descrittore che viene +chiuso, questa sarà rilasciata e potrà essere richiesta da qualche altro +processo. Quando si vuole effettivamente rimuovere una coda dal sistema occorre usare la -funzione \funcd{mq\_unlink}, il cui prototipo è: -\begin{prototype}{mqueue.h} -{int mq\_unlink(const char *name)} +funzione di sistema \funcd{mq\_unlink}, il cui prototipo è: -Rimuove una coda di messaggi. - -\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di - errore; nel quel caso \var{errno} assumerà gli stessi valori riportati da - \func{unlink}.} -\end{prototype} +\begin{funcproto}{ +\fhead{mqueue.h} +\fdecl{int mq\_unlink(const char *name)} + +\fdesc{Rimuove una coda di messaggi.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà gli uno dei valori: + \begin{errlist} + \item[\errcode{EACCES}] non si hanno i permessi per cancellare la coda. + \item[\errcode{ENAMETOOLONG}] il nome indicato è troppo lungo. + \item[\errcode{ENOENT}] non esiste una coda con il nome indicato. + \end{errlist} +} +\end{funcproto} Anche in questo caso il comportamento della funzione è analogo a quello di -\func{unlink} per i file,\footnote{di nuovo l'implementazione di Linux usa - direttamente \func{unlink}.} la funzione rimuove la coda \param{name}, così -che una successiva chiamata a \func{mq\_open} fallisce o crea una coda -diversa. +\func{unlink} per i file, la funzione rimuove la coda \param{name} (ed il +relativo file sotto \texttt{/dev/mqueue}), così che una successiva chiamata a +\func{mq\_open} fallisce o crea una coda diversa. + +% TODO, verificare se mq_unlink è davvero una system call indipendente. Come per i file ogni coda di messaggi ha un contatore di riferimenti, per cui la coda non viene effettivamente rimossa dal sistema fin quando questo non si @@ -3820,141 +3875,163 @@ di essa. Allo stesso modo una coda ed i suoi contenuti resteranno disponibili all'interno del sistema anche quando quest'ultima non è aperta da nessun processo (questa è una delle differenze più rilevanti nei confronti di \textit{pipe} e \textit{fifo}). La sola differenza fra code di messaggi POSIX -e file normali è che, essendo il filesystem delle code di messaggi virtuale e +e file normali è che, essendo il filesystem delle code di messaggi virtuale, e basato su oggetti interni al kernel, il suo contenuto viene perduto con il riavvio del sistema. Come accennato ad ogni coda di messaggi è associata una struttura \struct{mq\_attr}, che può essere letta e modificata attraverso le due funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono: -\begin{functions} - \headdecl{mqueue.h} - - \funcdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)} - Legge gli attributi di una coda di messaggi POSIX. - - \funcdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat, + +\begin{funcproto}{ +\fhead{mqueue.h} +\fdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)} +\fdesc{Legge gli attributi di una coda di messaggi POSIX.} +\fdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat, struct mq\_attr *omqstat)} - Modifica gli attributi di una coda di messaggi POSIX. - - \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in - caso di errore; nel quel caso \var{errno} assumerà i valori \errval{EBADF} - o \errval{EINVAL}.} -\end{functions} +\fdesc{Modifica gli attributi di una coda di messaggi POSIX.} +} + +{Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà i valori \errval{EBADF} + o \errval{EINVAL} nel loro significato generico. +} +\end{funcproto} La funzione \func{mq\_getattr} legge i valori correnti degli attributi della -coda nella struttura puntata da \param{mqstat}; di questi l'unico relativo -allo stato corrente della coda è \var{mq\_curmsgs} che indica il numero di -messaggi da essa contenuti, gli altri indicano le caratteristiche generali -della stessa. +coda \param{mqdes} nella struttura \struct{mq\_attr} puntata +da \param{mqstat}; di questi l'unico relativo allo stato corrente della coda è +\var{mq\_curmsgs} che indica il numero di messaggi da essa contenuti, gli +altri indicano le caratteristiche generali della stessa impostate in fase di +apertura. La funzione \func{mq\_setattr} permette di modificare gli attributi di una -coda tramite i valori contenuti nella struttura puntata da \param{mqstat}, ma -può essere modificato solo il campo \var{mq\_flags}, gli altri campi vengono -ignorati. In particolare i valori di \var{mq\_maxmsg} e \var{mq\_msgsize} -possono essere specificati solo in fase ci creazione della coda. Inoltre i -soli valori possibili per \var{mq\_flags} sono 0 e \const{O\_NONBLOCK}, per -cui alla fine la funzione può essere utilizzata solo per abilitare o -disabilitare la modalità non bloccante. L'argomento \param{omqstat} viene -usato, quando diverso da \val{NULL}, per specificare l'indirizzo di una -struttura su cui salvare i valori degli attributi precedenti alla chiamata -della funzione. - -Per inserire messaggi su di una coda sono previste due funzioni, -\funcd{mq\_send} e \funcd{mq\_timedsend}, i cui prototipi sono: -\begin{functions} - \headdecl{mqueue.h} - - \funcdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len, - unsigned int msg\_prio)} - Esegue l'inserimento di un messaggio su una coda. - - \funcdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t - msg\_len, unsigned msg\_prio, const struct timespec *abs\_timeout)} - Esegue l'inserimento di un messaggio su una coda entro il tempo - \param{abs\_timeout}. +coda (indicata da \param{mqdes}) tramite i valori contenuti nella struttura +\struct{mq\_attr} puntata da \param{mqstat}, ma può essere modificato solo il +campo \var{mq\_flags}, gli altri campi vengono comunque ignorati. + +In particolare i valori di \var{mq\_maxmsg} e \var{mq\_msgsize} possono essere +specificati solo in fase ci creazione della coda. Inoltre i soli valori +possibili per \var{mq\_flags} sono 0 e \const{O\_NONBLOCK}, per cui alla fine +la funzione può essere utilizzata solo per abilitare o disabilitare la +modalità non bloccante. L'argomento \param{omqstat} viene usato, quando +diverso da \val{NULL}, per specificare l'indirizzo di una struttura su cui +salvare i valori degli attributi precedenti alla chiamata della funzione. + +Per inserire messaggi su di una coda sono previste due funzioni di sistema, +\funcd{mq\_send} e \funcd{mq\_timedsend}. In realtà su Linux la \textit{system + call} è soltanto \func{mq\_timedsend}, mentre \func{mq\_send} viene +implementata come funzione di libreria che si appoggia alla +precedente. Inoltre \func{mq\_timedsend} richiede che sia definita la macro +\macro{\_XOPEN\_SOURCE} ad un valore pari ad almeno \texttt{600} o la macro +\macro{\_POSIX\_C\_SOURCE} ad un valore uguale o maggiore di \texttt{200112L}. +I rispettivi prototipi sono: - - \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ per un - errore; nel quel caso \var{errno} assumerà i valori: - \begin{errlist} +\begin{funcproto}{ +\fhead{mqueue.h} +\fdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len, + unsigned int msg\_prio)} +\fdesc{Esegue l'inserimento di un messaggio su una coda.} +\fhead{mqueue.h} +\fhead{time.h} +\fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t + msg\_len, unsigned int msg\_prio,\\ +\phantom{int mq\_timedsend(}const struct timespec *abs\_timeout)} +\fdesc{Esegue l'inserimento di un messaggio su una coda entro un tempo + specificato} +} + +{Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la coda è piena. - \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len} - eccede il limite impostato per la coda. + \item[\errcode{EBADF}] si specificato un file descriptor non valido. \item[\errcode{EINVAL}] si è specificato un valore nullo per \param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o un valore non valido per \param{abs\_timeout}. + \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len} + eccede il limite impostato per la coda. \item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato - effettuato entro il tempo stabilito. - \end{errlist} - ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR}.} -\end{functions} + effettuato entro il tempo stabilito (solo \func{mq\_timedsend}). + \end{errlist} + ed inoltre \errval{EBADF}, \errval{EINTR} nel suo significato generico. } +\end{funcproto} -Entrambe le funzioni richiedono un puntatore al testo del messaggio -nell'argomento \param{msg\_ptr} e la relativa lunghezza in \param{msg\_len}. +Entrambe le funzioni richiedono un puntatore ad un buffer in memoria +contenente il testo del messaggio da inserire nella coda \param{mqdes} +nell'argomento \param{msg\_ptr}, e la relativa lunghezza in \param{msg\_len}. Se quest'ultima eccede la dimensione massima specificata da \var{mq\_msgsize} le funzioni ritornano immediatamente con un errore di \errcode{EMSGSIZE}. -L'argomento \param{msg\_prio} indica la priorità dell'argomento; i messaggi di -priorità maggiore vengono inseriti davanti a quelli di priorità inferiore (e -quindi saranno riletti per primi). A parità del valore della priorità il -messaggio sarà inserito in coda a tutti quelli con la stessa priorità. Il -valore della priorità non può eccedere il limite di sistema -\const{MQ\_PRIO\_MAX}, che nel caso è pari a 32768. +L'argomento \param{msg\_prio} indica la priorità dell'argomento, che, essendo +definito come \ctyp{unsigned int}, è sempre un intero positivo. I messaggi di +priorità maggiore vengono inseriti davanti a quelli di priorità inferiore, e +quindi saranno riletti per primi. A parità del valore della priorità il +messaggio sarà inserito in coda a tutti quelli che hanno la stessa priorità +che quindi saranno letti con la politica di una \textit{fifo}. Il valore della +priorità non può eccedere il limite di sistema \const{MQ\_PRIO\_MAX}, che al +momento è pari a 32768. Qualora la coda sia piena, entrambe le funzioni si bloccano, a meno che non -sia stata selezionata in fase di apertura la modalità non -bloccante,\footnote{o si sia impostato il flag \const{O\_NONBLOCK} sul file - descriptor della coda.} nel qual caso entrambe ritornano \errcode{EAGAIN}. -La sola differenza fra le due funzioni è che la seconda, passato il tempo -massimo impostato con l'argomento \param{abs\_timeout},\footnote{deve essere - specificato un tempo assoluto tramite una struttura \struct{timespec} (vedi - fig.~\ref{fig:sys_timespec_struct}) indicato in numero di secondi e - nanosecondi a partire dal 1 gennaio 1970.} ritorna comunque con un errore di -\errcode{ETIMEDOUT}, se invece il tempo è già scaduto al momento della -chiamata e la coda è vuota la funzione ritorna immediatamente. +sia stata selezionata in fase di apertura della stessa la modalità non +bloccante o non si sia impostato il flag \const{O\_NONBLOCK} sul file +descriptor della coda, nel qual caso entrambe ritornano con un codice di +errore di \errcode{EAGAIN}. + +La sola differenza fra le due funzioni è che \func{mq\_timedsend}, passato il +tempo massimo impostato con l'argomento \param{abs\_timeout}, ritorna comunque +con un errore di \errcode{ETIMEDOUT}, se invece il tempo è già scaduto al +momento della chiamata e la coda è piena la funzione ritorna +immediatamente. Il valore di \param{abs\_timeout} deve essere specificato come +tempo assoluto tramite una struttura \struct{timespec} (vedi +fig.~\ref{fig:sys_timespec_struct}) indicato in numero di secondi e +nanosecondi a partire dal 1 gennaio 1970. Come per l'inserimento, anche per l'estrazione dei messaggi da una coda sono -previste due funzioni, \funcd{mq\_receive} e \funcd{mq\_timedreceive}, i cui -prototipi sono: -\begin{functions} - \headdecl{mqueue.h} - - \funcdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t - msg\_len, unsigned int *msg\_prio)} - Effettua la ricezione di un messaggio da una coda. - - \funcdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t - msg\_len, unsigned int *msg\_prio, const struct timespec *abs\_timeout)} - Effettua la ricezione di un messaggio da una coda entro il tempo - \param{abs\_timeout}. - - \bodydesc{Le funzioni restituiscono il numero di byte del messaggio in caso - di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i - valori: - \begin{errlist} +previste due funzioni di sistema, \funcd{mq\_receive} e +\funcd{mq\_timedreceive}. Anche in questo caso su Linux soltanto +\func{mq\_timedreceive} è effettivamente, una \textit{system call} e per +usarla devono essere definite le opportune macro come per +\func{mq\_timedsend}. I rispettivi prototipi sono: + +\begin{funcproto}{ +\fhead{mqueue.h} +\fdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t + msg\_len, unsigned int *msg\_prio)} +\fdesc{Effettua la ricezione di un messaggio da una coda.} +\fhead{mqueue.h} +\fhead{time.h} +\fdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t + msg\_len,\\ +\phantom{ssize\_t mq\_timedreceive(}unsigned int *msg\_prio, const struct timespec +*abs\_timeout)} +\fdesc{Riceve un messaggio da una coda entro un limite di tempo.} +} +{Entrambe le funzioni ritornano il numero di byte del messaggio in caso di + successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei + valori: + \begin{errlist} \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la coda è vuota. - \item[\errcode{EMSGSIZE}] la lunghezza del messaggio sulla coda eccede il - valore \param{msg\_len} specificato per la ricezione. \item[\errcode{EINVAL}] si è specificato un valore nullo per \param{msg\_ptr}, o un valore non valido per \param{abs\_timeout}. + \item[\errcode{EMSGSIZE}] la lunghezza del messaggio sulla coda eccede il + valore \param{msg\_len} specificato per la ricezione. \item[\errcode{ETIMEDOUT}] la ricezione del messaggio non è stata effettuata entro il tempo stabilito. - \end{errlist} - ed inoltre \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o - \errval{EINVAL}.} -\end{functions} + \end{errlist} + ed inoltre \errval{EBADF} o \errval{EINTR} nel loro significato generico. } +\end{funcproto} -La funzione estrae dalla coda il messaggio a priorità più alta, o il più -vecchio fra quelli della stessa priorità. Una volta ricevuto il messaggio -viene tolto dalla coda e la sua dimensione viene restituita come valore di -ritorno.\footnote{si tenga presente che 0 è una dimensione valida e che la - condizione di errore è restituita dal valore -1; Stevens in \cite{UNP2} fa - notare che questo è uno dei casi in cui vale ciò che lo standard - \textsl{non} dice, una dimensione nulla infatti, pur non essendo citata, non - viene proibita.} +La funzione estrae dalla coda \param{mqdes} il messaggio a priorità più alta, +o il più vecchio fra quelli della stessa priorità. Una volta ricevuto il +messaggio viene tolto dalla coda e la sua dimensione viene restituita come +valore di ritorno; si tenga presente che 0 è una dimensione valida e che la +condizione di errore è indicata soltanto da un valore di +$-1$.\footnote{Stevens in \cite{UNP2} fa notare che questo è uno dei casi in + cui vale ciò che lo standard \textsl{non} dice, una dimensione nulla + infatti, pur non essendo citata, non viene proibita.} Se la dimensione specificata da \param{msg\_len} non è sufficiente a contenere il messaggio, entrambe le funzioni, al contrario di quanto avveniva nelle code @@ -3975,8 +4052,6 @@ selezionare quale messaggio estrarre con delle condizioni sulla priorità, a differenza di quanto avveniva con le code di messaggi di SysV che permettono invece la selezione in base al valore del campo \var{mtype}. -% TODO inserire i dati di /proc/sys/fs/mqueue - Qualora la coda sia vuota entrambe le funzioni si bloccano, a meno che non si sia selezionata la modalità non bloccante; in tal caso entrambe ritornano immediatamente con l'errore \errcode{EAGAIN}. Anche in questo caso la sola @@ -3996,39 +4071,48 @@ superare in parte questo problema. Una caratteristica specifica delle code di messaggi POSIX è la possibilità di usufruire di un meccanismo di notifica asincrono; questo può essere attivato usando la funzione \funcd{mq\_notify}, il cui prototipo è: -\begin{prototype}{mqueue.h} -{int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)} -Attiva il meccanismo di notifica per la coda \param{mqdes}. - -\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di - errore; nel quel caso \var{errno} assumerà i valori: - \begin{errlist} - \item[\errcode{EBUSY}] c'è già un processo registrato per la notifica. +\begin{funcproto}{ +\fhead{mqueue.h} +\fdecl{int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)} + +\fdesc{Attiva il meccanismo di notifica per una coda.} +} + +{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{EBADF}] il descrittore non fa riferimento ad una coda di messaggi. - \end{errlist}} -\end{prototype} + \item[\errcode{EBUSY}] c'è già un processo registrato per la notifica. + \item[\errcode{EINVAL}] si è richiesto un meccanismo di notifica invalido + o specificato nella notifica con i segnali il valore di un segnale non + esistente. + \end{errlist} + ed inoltre \errval{ENOMEM} nel suo significato generico. + +} +\end{funcproto} Il meccanismo di notifica permette di segnalare in maniera asincrona ad un -processo la presenza di dati sulla coda, in modo da evitare la necessità di -bloccarsi nell'attesa. Per far questo un processo deve registrarsi con la -funzione \func{mq\_notify}, ed il meccanismo è disponibile per un solo -processo alla volta per ciascuna coda. +processo la presenza di dati sulla coda indicata da \param{mqdes}, in modo da +evitare la necessità di bloccarsi nell'attesa. Per far questo un processo deve +registrarsi con la funzione \func{mq\_notify}, ed il meccanismo è disponibile +per un solo processo alla volta per ciascuna coda. -Il comportamento di \func{mq\_notify} dipende dal valore dell'argomento -\param{notification}, che è un puntatore ad una apposita struttura +Il comportamento di \func{mq\_notify} dipende dai valori passati con +l'argomento \param{notification}, che è un puntatore ad una apposita struttura \struct{sigevent}, (definita in fig.~\ref{fig:struct_sigevent}) introdotta dallo standard POSIX.1b per gestire la notifica di eventi; per altri dettagli -si può vedere quanto detto in sez.~\ref{sec:sig_timer_adv} a proposito -dell'uso della stessa struttura per la notifica delle scadenze dei +su di essa si può rivedere quanto detto in sez.~\ref{sec:sig_timer_adv} a +proposito dell'uso della stessa struttura per la notifica delle scadenze dei \textit{timer}. Attraverso questa struttura si possono impostare le modalità con cui viene effettuata la notifica nel campo \var{sigev\_notify}, che può assumere i -valori di tab.~\ref{tab:sigevent_sigev_notify}.\footnote{la pagina di manuale - riporta soltanto i primi tre (inizialmente era possibile solo - \const{SIGEV\_SIGNAL}).} Il metodo consigliato è quello di usare +valori di tab.~\ref{tab:sigevent_sigev_notify}; fra questi la pagina di +manuale riporta soltanto i primi tre, ed inizialmente era possibile solo +\const{SIGEV\_SIGNAL}. Il metodo consigliato è quello di usare \const{SIGEV\_SIGNAL} usando il campo \var{sigev\_signo} per indicare il quale segnale deve essere inviato al processo. Inoltre il campo \var{sigev\_value} è un puntatore ad una struttura \struct{sigval} (definita in @@ -4042,12 +4126,12 @@ La funzione registra il processo chiamante per la notifica se \param{notification} punta ad una struttura \struct{sigevent} opportunamente inizializzata, o cancella una precedente registrazione se è \val{NULL}. Dato che un solo processo alla volta può essere registrato, la funzione fallisce -con \errcode{EBUSY} se c'è un altro processo già registrato.\footnote{questo - significa anche che se si registra una notifica con \const{SIGEV\_NONE} il - processo non la riceverà, ma impedirà anche che altri possano registrarsi - per poterlo fare.} Si tenga presente inoltre che alla chiusura del -descrittore associato alla coda (e quindi anche all'uscita del processo) ogni -eventuale registrazione di notifica presente viene cancellata. +con \errcode{EBUSY} se c'è un altro processo già registrato. Questo significa +anche che se si registra una notifica con \const{SIGEV\_NONE} il processo non +la riceverà, ma impedirà anche che altri possano registrarsi per poterlo fare. +Si tenga presente inoltre che alla chiusura del descrittore associato alla +coda (e quindi anche all'uscita del processo) ogni eventuale registrazione di +notifica presente viene cancellata. La notifica del segnale avviene all'arrivo di un messaggio in una coda vuota (cioè solo se sulla coda non ci sono messaggi) e se non c'è nessun processo @@ -4062,8 +4146,8 @@ la coda diventa disponibile per una ulteriore registrazione. Questo comporta che se si vuole mantenere il meccanismo di notifica occorre ripetere la registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore del segnale di notifica. A differenza della situazione simile che si aveva con -i segnali non affidabili,\footnote{l'argomento è stato affrontato in - \ref{sec:sig_semantics}.} questa caratteristica non configura una +i segnali non affidabili (l'argomento è stato affrontato in +\ref{sec:sig_semantics}) questa caratteristica non configura una \itindex{race~condition} \textit{race condition} perché l'invio di un segnale avviene solo se la coda è vuota; pertanto se si vuole evitare di correre il rischio di perdere eventuali ulteriori segnali inviati nel lasso di tempo che @@ -4074,13 +4158,12 @@ L'invio del segnale di notifica avvalora alcuni campi di informazione restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in fig.~\ref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al valore del \ids{PID} del processo che ha emesso il segnale, \var{si\_uid} -all'userid effettivo, \var{si\_code} a \const{SI\_MESGQ}, e \var{si\_errno} a -0. Questo ci dice che, se si effettua la ricezione dei messaggi usando -esclusivamente il meccanismo di notifica, è possibile ottenere le informazioni -sul processo che ha inserito un messaggio usando un gestore per il segnale in -forma estesa.\footnote{di nuovo si faccia riferimento a quanto detto al - proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}.} - +all'\textsl{user-ID} effettivo, \var{si\_code} a \const{SI\_MESGQ}, e +\var{si\_errno} a 0. Questo ci dice che, se si effettua la ricezione dei +messaggi usando esclusivamente il meccanismo di notifica, è possibile ottenere +le informazioni sul processo che ha inserito un messaggio usando un gestore +per il segnale in forma estesa, di nuovo si faccia riferimento a quanto detto +al proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}. \subsection{Memoria condivisa} @@ -4093,18 +4176,19 @@ suoi contenuti in memoria, che viene attivato abilitando l'opzione \texttt{CONFIG\_TMPFS} in fase di compilazione del kernel. Per potere utilizzare l'interfaccia POSIX per la memoria condivisa la -\acr{glibc}\footnote{le funzioni sono state introdotte con la versione 2.2.} -richiede di compilare i programmi con l'opzione \code{-lrt}; inoltre è -necessario che in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs}; -questo di norma viene fatto aggiungendo una riga del tipo di: -\begin{verbatim} +\acr{glibc} (le funzioni sono state introdotte con la versione 2.2) richiede +di compilare i programmi con l'opzione \code{-lrt}; inoltre è necessario che +in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs}; questo di norma +viene fatto aggiungendo una riga del tipo di: +\begin{FileExample}[label=/etc/fstab] tmpfs /dev/shm tmpfs defaults 0 0 -\end{verbatim} -ad \conffile{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs} -dove si vuole, per usarlo come RAM disk, con un comando del tipo: -\begin{verbatim} +\end{FileExample} +ad \conffile{/etc/fstab}. In realtà si può montare un filesystem +\texttt{tmpfs} dove si vuole, per usarlo come RAM disk, con un comando del +tipo: +\begin{Example} mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs -\end{verbatim} +\end{Example} Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e \texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne @@ -4398,7 +4482,7 @@ Si tenga presente che la funzione può sempre essere interrotta da un segnale (nel qual caso si avrà un errore di \const{EINTR}) e che questo avverrà comunque, anche se si è richiesta la semantica BSD installando il relativo gestore con \const{SA\_RESTART} (vedi sez.~\ref{sec:sig_sigaction}) per -riavviare le system call interrotte. +riavviare le \textit{system call} interrotte. Della funzione \func{sem\_wait} esistono due varianti che consentono di gestire diversamente le modalità di attesa in caso di risorsa occupata, la @@ -4927,11 +5011,12 @@ testo alla terminazione di quest'ultimo. % 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: for now it's break Berlin sources Let's an accidental feature fs % LocalWords: Larry Wall Escape the Hell William ipctestid Identifier segment % LocalWords: violation dell'I SIGINT setter Fri Dec Sleeping seconds ECHILD % LocalWords: SysV capability short RESOURCE INFO UNDEFINED EFBIG semtimedop -% LocalWords: scan +% LocalWords: scan HUGETLB huge page NORESERVE copy RLIMIT MEMLOCK REMAP +% LocalWords: readmon Hierarchy defaults queues MSGQUEUE %%% Local Variables: