mqueue /dev/mqueue mqueue defaults 0 0
\end{verbatim}
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
+code di messaggi che iniziano con una ``\texttt{/}''. Le opzioni di mount
accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono
rispettivamente di impostare l'utente, il gruppo ed i permessi associati al
filesystem.
Apre una coda di messaggi POSIX impostandone le caratteristiche.
\bodydesc{La funzione restituisce il descrittore associato alla coda in caso
- di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i
+ 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
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{nella implementazione citata questo è definito come
- \ctyp{int}.} Se la coda esiste già il descrittore farà riferimento allo
-stesso oggetto, consentendo così la comunicazione fra due processi diversi.
+\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.
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
tab.~\ref{tab:file_open_flags} dei quali però \func{mq\_open} riconosce solo i
seguenti:
-\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
+\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
\func{mq\_send}.
Se la coda non esiste e la si vuole creare si deve specificare
\const{O\_CREAT}, in tal caso occorre anche specificare i permessi di
-creazione con l'argomento \param{mode}; 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}.
+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}.
\begin{figure}[!htb]
\footnotesize \centering
\end{figure}
Per la creazione della coda i campi della struttura che devono essere
-specificati sono \var{mq\_msgsize} e \var{mq\_maxmsg}, che indicano
-rispettivamente la dimensione massima di un messaggio ed il numero massimo di
-messaggi che essa può contenere. 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}. Qualora si
-specifichi per \param{attr} un puntatore nullo gli attributi della coda
-saranno impostati ai valori predefiniti.
+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.
Quando l'accesso alla coda non è più necessario si può chiudere il relativo
descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
Chiude 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 \errval{EBADF} o
+\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}
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 pipe e
-fifo).
+fifo). La sola differenza fra code di messaggi POSIX 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.
-La sola differenza fra code di messaggi POSIX 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 in precedenza 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:
+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}
\param{abs\_timeout}.
- \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ in caso di
+ \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ per un
errore; nel quel caso \var{errno} assumerà i valori:
\begin{errlist}
\item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
\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:file_asyncronous_io} a proposito
-dell'uso della stessa struttura per l'invio dei segnali usati per l'I/O
-asincrono.
-
-% TODO la notifica non è più limitata al solo uso dei segnali, adesso si
-% possono anche usare i thread, correggere!.
+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
+\textit{timer}.
Attraverso questa struttura si possono impostare le modalità con cui viene
-effettuata la notifica; in particolare il campo \var{sigev\_notify} deve
-essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato
- sui \itindex{thread} \textit{thread}, specificato tramite il valore
- \const{SIGEV\_THREAD}, non è implementato.} ed il campo \var{sigev\_signo}
-deve indicare il valore del segnale che sarà inviato al processo. Inoltre il
-campo \var{sigev\_value} è il puntatore ad una struttura \struct{sigval\_t}
-(definita in fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore
-del segnale un valore numerico o un indirizzo,\footnote{per il suo uso si
- riveda la trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei
- segnali real-time.} posto che questo sia installato nella forma estesa vista
-in sez.~\ref{sec:sig_sigaction}.
+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
+\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\_t} (definita in
+fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale
+un valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
+ trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali
+ \textit{real-time}.} posto che questo sia installato nella forma estesa
+vista in sez.~\ref{sec:sig_sigaction}.
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. 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.\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.
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
La memoria condivisa è stato il primo degli oggetti di IPC POSIX inserito nel
kernel ufficiale; il supporto a questo tipo di oggetti è realizzato attraverso
il filesystem \texttt{tmpfs}, uno speciale filesystem che mantiene tutti i
-suoi contenuti in memoria,\footnote{il filesystem \texttt{tmpfs} è diverso da
- un normale RAM disk, anch'esso disponibile attraverso il filesystem
- \texttt{ramfs}, proprio perché realizza una interfaccia utilizzabile anche
- per la memoria condivisa; esso infatti non ha dimensione fissa, ed usa
- direttamente la cache interna del kernel (che viene usata anche per la
- shared memory in stile SysV). In più i suoi contenuti, essendo trattati
- direttamente dalla memoria virtuale \index{memoria~virtuale} possono essere
- salvati sullo swap automaticamente.} che viene attivato abilitando l'opzione
+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 le
\acr{glibc}\footnote{le funzioni sono state introdotte con le glibc-2.2.}
richiedono di compilare i programmi con l'opzione \code{-lrt}; inoltre è
La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
prototipo è:
-\begin{prototype}{mqueue.h}
-{int shm\_open(const char *name, int oflag, mode\_t mode)}
+\begin{functions}
+ \headdecl{sys/mman.h}
+ \headdecl{sys/stat.h}
+ \headdecl{fcntl.h}
-Apre un segmento di memoria condivisa.
+ \funcdecl{int shm\_open(const char *name, int oflag, mode\_t mode)}
+
+ Apre un segmento di memoria condivisa.
-\bodydesc{La funzione restituisce un file descriptor positivo in caso di
- successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
- stessi valori riportati da \func{open}.}
-\end{prototype}
+ \bodydesc{La funzione restituisce un file descriptor positivo in caso di
+ successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
+ stessi valori riportati da \func{open}.}
+\end{functions}
La funzione apre un segmento di memoria condivisa identificato dal nome
-\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo nome
-può essere specificato in forma standard solo facendolo iniziare per \file{/}
-e senza ulteriori \file{/}, Linux supporta comunque nomi generici, che
-verranno interpretati prendendo come radice \file{/dev/shm}.\footnote{occorre
- pertanto evitare di specificare qualcosa del tipo \file{/dev/shm/nome}
- all'interno di \param{name}, perché questo comporta, da parte delle funzioni
- di libreria, il tentativo di accedere a \file{/dev/shm/dev/shm/nome}.}
+\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo
+nome può essere specificato in forma standard solo facendolo iniziare per
+``\file{/}'' e senza ulteriori ``\file{/}''. Linux supporta comunque nomi
+generici, che verranno interpretati prendendo come radice
+\file{/dev/shm}.\footnote{occorre pertanto evitare di specificare qualcosa del
+ tipo \file{/dev/shm/nome} all'interno di \param{name}, perché questo
+ comporta, da parte delle funzioni di libreria, il tentativo di accedere a
+ \file{/dev/shm/dev/shm/nome}.}
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
Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file
descriptor (con \func{close}), senza che la mappatura ne risenta.
-
Come per i file, quando si vuole effettivamente rimuovere segmento di memoria
condivisa, occorre usare la funzione \funcd{shm\_unlink}, il cui prototipo è:
-\begin{prototype}{mqueue.h}
+\begin{prototype}{sys/mman.h}
{int shm\_unlink(const char *name)}
Rimuove un segmento di memoria condivisa.