X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=ipc.tex;h=172ea58b1bf6e130f37bde8a4da074040c5d4720;hb=b89b7fbeeba4fab9f8990dd8373cdc41c7052eeb;hp=11e9c26d445e4190779e99c344d2ecc985bf629d;hpb=ee41e8b34dd560d230966160fb3eb748defc3e46;p=gapil.git diff --git a/ipc.tex b/ipc.tex index 11e9c26..172ea58 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1,6 +1,6 @@ %% ipc.tex %% -%% Copyright (C) 2000-2009 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2010 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", @@ -190,7 +190,6 @@ fig.~\ref{fig:ipc_barcodepage_code} abbiamo riportato il corpo del programma, il cui codice completo è disponibile nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti. - \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} @@ -656,24 +655,26 @@ verificata) che si facciano le prove direttamente nella directory dei sorgenti (dove di norma vengono creati sia i programmi che la libreria), il comando da dare sarà \code{export LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare il server, facendogli leggere una decina di frasi, con: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./fortuned -n10 -\end{verbatim} +\end{Verbatim} +%$ Avendo usato \func{daemon} per eseguire il server in background il comando ritornerà immediatamente, ma potremo verificare con \cmd{ps} che in effetti il programma resta un esecuzione in background, e senza avere associato un terminale di controllo (si ricordi quanto detto in sez.~\ref{sec:sess_daemon}): -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ps aux ... piccardi 27489 0.0 0.0 1204 356 ? S 01:06 0:00 ./fortuned -n10 piccardi 27492 3.0 0.1 2492 764 pts/2 R 01:08 0:00 ps aux -\end{verbatim}%$ +\end{Verbatim} +%$ e si potrà verificare anche che in \file{/tmp} è stata creata la fifo di ascolto \file{fortune.fifo}. A questo punto potremo interrogare il server con il programma client; otterremo così: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./fortune Linux ext2fs has been stable for a long time, now it's time to break it -- Linuxkongreß '95 in Berlin @@ -692,7 +693,8 @@ Let's call it an accidental feature. [piccardi@gont sources]$ ./fortune Linux ext2fs has been stable for a long time, now it's time to break it -- Linuxkongreß '95 in Berlin -\end{verbatim}%$ +\end{Verbatim} +%$ e ripetendo varie volte il comando otterremo, in ordine casuale, le dieci frasi tenute in memoria dal server. @@ -962,7 +964,7 @@ nullo, nel qual caso l'identificatore sar Il secondo livello di controllo è quello delle varie funzioni che accedono direttamente (in lettura o scrittura) all'oggetto. In tal caso lo schema dei controlli è simile a quello dei file, ed avviene secondo questa sequenza: -\begin{itemize} +\begin{itemize*} \item se il processo ha i privilegi di amministratore l'accesso è sempre consentito. \item se l'user-ID effettivo del processo corrisponde o al valore del campo @@ -974,7 +976,7 @@ controlli valore del campo \var{cgid} o a quello del campo \var{gid} ed il permesso per il gruppo in \var{mode} è appropriato l'accesso è consentito. \item se il permesso per gli altri è appropriato l'accesso è consentito. -\end{itemize} +\end{itemize*} solo se tutti i controlli elencati falliscono l'accesso è negato. Si noti che a differenza di quanto avviene per i permessi dei file, fallire in uno dei passi elencati non comporta il fallimento dell'accesso. Un'ulteriore @@ -1058,25 +1060,27 @@ inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e stampa, cancellazione. I valori di default sono per l'uso delle code di messaggi e un ciclo di 5 volte. Se si lancia il comando si otterrà qualcosa del tipo: -\begin{verbatim} +\begin{Verbatim} piccardi@gont sources]$ ./ipctestid Identifier Value 0 Identifier Value 32768 Identifier Value 65536 Identifier Value 98304 Identifier Value 131072 -\end{verbatim}%$ +\end{Verbatim} +%$ il che ci mostra che abbiamo un kernel della serie 2.4.x nel quale non avevamo ancora usato nessuna coda di messaggi. Se ripetiamo il comando otterremo ancora: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./ipctestid Identifier Value 163840 Identifier Value 196608 Identifier Value 229376 Identifier Value 262144 Identifier Value 294912 -\end{verbatim}%$ +\end{Verbatim} +%$ che ci mostra come il valore di \var{seq} sia in effetti una quantità mantenuta staticamente all'interno del sistema. @@ -1182,9 +1186,8 @@ file \procrelfile{/proc/sys/kernel}{msgmax}, \procrelfile{/proc/sys/kernel}{msgmnb} e \procrelfile{/proc/sys/kernel}{msgmni} di \file{/proc/sys/kernel/}. - \begin{figure}[htb] - \centering \includegraphics[width=15cm]{img/mqstruct} + \centering \includegraphics[width=13cm]{img/mqstruct} \caption{Schema della struttura di una coda messaggi.} \label{fig:ipc_mq_schema} \end{figure} @@ -1271,7 +1274,7 @@ prototipo Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}. - \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma processo @@ -1326,7 +1329,7 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo Invia un messaggio sulla coda \param{msqid}. - \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso + \bodydesc{La funzione restituisce 0, e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EACCES}] non si hanno i privilegi di accesso sulla coda. @@ -1334,13 +1337,11 @@ messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo \item[\errcode{EAGAIN}] il messaggio non può essere inviato perché si è superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti sulla coda, e si è richiesto \const{IPC\_NOWAIT} in \param{flag}. - \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. \item[\errcode{EINVAL}] si è specificato un \param{msgid} invalido, o un valore non positivo per \param{mtype}, o un valore di \param{msgsz} maggiore di \const{MSGMAX}. \end{errlist} - ed inoltre \errval{EFAULT} ed \errval{ENOMEM}. -} + ed inoltre \errval{EFAULT}, \errval{EINTR} ed \errval{ENOMEM}. } \end{functions} La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il @@ -2903,13 +2904,14 @@ il mutex, prima di uscire. Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando le funzioni di libreria occorre definire opportunamente \code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./dirmonitor ./ -\end{verbatim}%$ +\end{Verbatim} +%$ ed avendo usato \func{daemon} il comando ritornerà immediatamente. Una volta che il server è in esecuzione, possiamo passare ad invocare il client per verificarne i risultati, in tal caso otterremo: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./readmon Ci sono 68 file dati Ci sono 3 directory @@ -2919,12 +2921,13 @@ Ci sono 0 socket Ci sono 0 device a caratteri Ci sono 0 device a blocchi Totale 71 file, per 489831 byte -\end{verbatim}%$ +\end{Verbatim} +%$ ed un rapido calcolo (ad esempio con \code{ls -a | wc} per contare i file) ci permette di verificare che il totale dei file è giusto. Un controllo con \cmd{ipcs} ci permette inoltre di verificare la presenza di un segmento di memoria condivisa e di un semaforo: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ipcs ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status @@ -2936,12 +2939,13 @@ key semid owner perms nsems ------ Message Queues -------- key msqid owner perms used-bytes messages -\end{verbatim}%$ +\end{Verbatim} +%$ Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova}, potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o l'eventuale altro intervallo impostato per la rilettura dei dati) avremo: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./readmon Ci sono 69 file dati Ci sono 3 directory @@ -2951,18 +2955,20 @@ Ci sono 0 socket Ci sono 0 device a caratteri Ci sono 0 device a blocchi Totale 72 file, per 489887 byte -\end{verbatim}%$ +\end{Verbatim} +%$ A questo punto possiamo far uscire il server inviandogli un segnale di \const{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto ripetendo la lettura, otterremo un errore: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ./readmon Cannot find shared memory: No such file or directory -\end{verbatim}%$ +\end{Verbatim} +%$ e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione visti in precedenza sono stati regolarmente cancellati: -\begin{verbatim} +\begin{Verbatim} [piccardi@gont sources]$ ipcs ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status @@ -2972,8 +2978,8 @@ key semid owner perms nsems ------ Message Queues -------- key msqid owner perms used-bytes messages -\end{verbatim}%$ - +\end{Verbatim} +%$ %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta @@ -3271,7 +3277,7 @@ POSIX prendono come primo argomento una stringa che indica uno di questi nomi; lo standard è molto generico riguardo l'implementazione, ed i nomi stessi possono avere o meno una corrispondenza sul filesystem; tutto quello che è richiesto è che: -\begin{itemize} +\begin{itemize*} \item i nomi devono essere conformi alle regole che caratterizzano i \itindex{pathname} \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX} byte e terminati da un carattere nullo. @@ -3280,7 +3286,7 @@ richiesto nome dipende dall'implementazione. \item l'interpretazione di ulteriori \texttt{/} presenti nel nome dipende dall'implementazione. -\end{itemize} +\end{itemize*} Data la assoluta genericità delle specifiche, il comportamento delle funzioni è subordinato in maniera quasi completa alla relativa @@ -3349,7 +3355,7 @@ aggiungendo ad \conffile{/etc/fstab} una riga come: 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. @@ -3368,14 +3374,13 @@ di messaggi POSIX 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 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{EINTR}] la funzione è stata interrotta da un segnale. \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}. @@ -3383,22 +3388,28 @@ di messaggi POSIX non esiste. \end{errlist} ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT}, - \errval{EMFILE} ed \errval{ENFILE}.} + \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE}. +} \end{functions} 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}. @@ -3426,13 +3437,14 @@ per i file normali. 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 @@ -3446,13 +3458,13 @@ fig.~\ref{fig:ipc_mq_attr}. \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 è: @@ -3461,8 +3473,8 @@ 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} @@ -3502,15 +3514,13 @@ coda rester 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). - -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. +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. -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} @@ -3559,22 +3569,20 @@ Per inserire messaggi su di una coda sono previste due funzioni, \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 coda è piena. \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len} eccede il limite impostato per la coda. - \item[\errcode{ENOMEM}] il kernel non ha memoria sufficiente. Questo - errore può avvenire quando l'inserimento del messaggio \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{ETIMEDOUT}] l'inserimento del messaggio non è stato effettuato entro il tempo stabilito. \end{errlist} - ed inoltre \errval{EBADF} ed \errval{EINTR}.} + ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR}.} \end{functions} Entrambe le funzioni richiedono un puntatore al testo del messaggio @@ -3596,7 +3604,7 @@ bloccante,\footnote{o si sia impostato il flag \const{O\_NONBLOCK} sul file 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_timeval_struct}) indicato in numero di secondi e + 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. @@ -3704,32 +3712,36 @@ 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 -\struct{sigevent}, (definita in fig.~\ref{fig:file_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. +\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 +\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 @@ -3771,17 +3783,9 @@ forma estesa.\footnote{di nuovo si faccia riferimento a quanto detto al 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 è @@ -3805,24 +3809,29 @@ questo caso 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 @@ -3866,10 +3875,9 @@ sez.~\ref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}. 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. @@ -4302,7 +4310,7 @@ Qualora il semaforo debba essere condiviso dai \itindex{thread} \textit{thread-shared semaphore}), occorrerà che \param{sem} sia l'indirizzo di una variabile visibile da tutti i \itindex{thread} \textit{thread}, si dovrà usare cioè una variabile globale o una variabile allocata dinamicamente -nello \itindex{heap} heap. +nello \itindex{heap} \textit{heap}. Qualora il semaforo debba essere condiviso fra più processi (nel qual caso si parla di \textit{process-shared semaphore}) la sola scelta possibile per @@ -4320,9 +4328,8 @@ utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e \func{sem\_post}. Si tenga presente però che inizializzare due volte lo stesso semaforo può dar luogo ad un comportamento indefinito. - Una volta che non si intenda più utilizzare un semaforo anonimo questo può -essere eliminato da sistema; per far questo di deve utilizzare una apposita +essere eliminato dal sistema; per far questo di deve utilizzare una apposita funzione, \funcd{sem\_destroy}, il cui prototipo è: \begin{functions} \headdecl{semaphore.h}