X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=ddf28dcc8d0bb66d855a64b9b5ea8d228a361557;hp=e8250805478304a8b064abcac07eafcf72115768;hb=fa15a3f1ecd64efd8440e46d398fd9976abc3d25;hpb=2628363a01b26ceef927232f0c7e512141663d91 diff --git a/ipc.tex b/ipc.tex index e825080..ddf28dc 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1,6 +1,6 @@ %% ipc.tex %% -%% Copyright (C) 2000-2014 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2019 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", @@ -96,7 +96,7 @@ con le frecce che indicano la direzione del flusso dei dati. \end{figure} Della funzione di sistema esiste una seconda versione, \funcd{pipe2}, -introdotta con il kernel 2.6.27 e le \acr{glibc} 2.9 e specifica di Linux +introdotta con il kernel 2.6.27 e la \acr{glibc} 2.9 e specifica di Linux (utilizzabile solo definendo la macro \macro{\_GNU\_SOURCE}), che consente di impostare atomicamente le caratteristiche dei file descriptor restituiti, il suo prototipo è: @@ -122,7 +122,7 @@ fra \const{O\_NONBLOCK} o \const{O\_CLOEXEC} che hanno l'effetto di impostare su entrambi i file descriptor restituiti dalla funzione i relativi flag, già descritti per \func{open} in tab.~\ref{tab:open_operation_flag}, che attivano rispettivamente la modalità di accesso \textsl{non-bloccante} ed il -\textit{close-on-exec} \itindex{close-on-exec}. +\textit{close-on-exec}. Chiaramente creare una \textit{pipe} all'interno di un singolo processo non serve a niente; se però ricordiamo quanto esposto in @@ -221,21 +221,21 @@ Per realizzare quanto voluto useremo in sequenza i programmi \cmd{barcode} e \cmd{gs}, il primo infatti è in grado di generare immagini PostScript di codici a barre corrispondenti ad una qualunque stringa, mentre il secondo serve per poter effettuare la conversione della stessa immagine in formato -JPEG. Usando una \textit{pipe} potremo inviare l'output del primo sull'input del -secondo, secondo lo schema mostrato in fig.~\ref{fig:ipc_pipe_use}, in cui la -direzione del flusso dei dati è data dalle frecce continue. +JPEG. Usando una \textit{pipe} potremo inviare l'output del primo sull'input +del secondo, secondo lo schema mostrato in fig.~\ref{fig:ipc_pipe_use}, in cui +la direzione del flusso dei dati è data dalle frecce continue. Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato intermedio su un file temporaneo. Questo però non tiene conto del fatto che un \textit{CGI} può essere eseguito più volte in contemporanea, e si avrebbe una -evidente \itindex{race~condition} \textit{race condition} in caso di accesso -simultaneo a detto file da istanze diverse. Il problema potrebbe essere -superato utilizzando un sempre diverso per il file temporaneo, che verrebbe -creato all'avvio di ogni istanza, utilizzato dai sottoprocessi, e cancellato -alla fine della sua esecuzione; ma a questo punto le cose non sarebbero più -tanto semplici. L'uso di una \textit{pipe} invece permette di risolvere il -problema in maniera semplice ed elegante, oltre ad essere molto più -efficiente, dato che non si deve scrivere su disco. +evidente \textit{race condition} in caso di accesso simultaneo a detto file da +istanze diverse. Il problema potrebbe essere superato utilizzando un sempre +diverso per il file temporaneo, che verrebbe creato all'avvio di ogni istanza, +utilizzato dai sottoprocessi, e cancellato alla fine della sua esecuzione; ma +a questo punto le cose non sarebbero più tanto semplici. L'uso di una +\textit{pipe} invece permette di risolvere il problema in maniera semplice ed +elegante, oltre ad essere molto più efficiente, dato che non si deve scrivere +su disco. Il programma ci servirà anche come esempio dell'uso delle funzioni di duplicazione dei file descriptor che abbiamo trattato in @@ -366,11 +366,10 @@ La funzione restituisce il puntatore ad uno stream associato alla \textit{pipe} creata, che sarà aperto in sola lettura (e quindi associato allo \textit{standard output} del programma indicato) in caso si sia indicato \code{r}, o in sola scrittura (e quindi associato allo \textit{standard - input}) in caso di \code{w}. A partire dalla versione 2.9 delle \acr{glibc} + input}) in caso di \code{w}. A partire dalla versione 2.9 della \acr{glibc} (questa è una estensione specifica di Linux) all'argomento \param{type} può essere aggiunta la lettera ``\texttt{e}'' per impostare automaticamente il -flag di \textit{close-on-exec} \itindex{close-on-exec} sul file descriptor -sottostante (si ricordi quanto spiegato in sez.~\ref{sec:file_open_close}). +flag di \textit{close-on-exec} sul file descriptor sottostante. Lo \textit{stream} restituito da \func{popen} è identico a tutti gli effetti ai \textit{file stream} visti in sez.~\ref{sec:files_std_interface}, anche se @@ -505,19 +504,19 @@ essere in una relazione di \textsl{parentela}. Utilizzando una \textit{fifo} tutti i dati passeranno, come per le \textit{pipe}, attraverso un buffer nel kernel, senza transitare dal -filesystem. Il fatto che siano associate ad un \itindex{inode} -\textit{inode} presente sul filesystem serve infatti solo a fornire un punto -di accesso per i processi, che permetta a questi ultimi di accedere alla -stessa \textit{fifo} senza avere nessuna relazione, con una semplice -\func{open}. Il comportamento delle funzioni di lettura e scrittura è identico -a quello illustrato per le \textit{pipe} in sez.~\ref{sec:ipc_pipes}. +filesystem. Il fatto che siano associate ad un \textit{inode} presente sul +filesystem serve infatti solo a fornire un punto di accesso per i processi, +che permetta a questi ultimi di accedere alla stessa \textit{fifo} senza avere +nessuna relazione, con una semplice \func{open}. Il comportamento delle +funzioni di lettura e scrittura è identico a quello illustrato per le +\textit{pipe} in sez.~\ref{sec:ipc_pipes}. Abbiamo già trattato in sez.~\ref{sec:file_mknod} le funzioni \func{mknod} e \func{mkfifo} che permettono di creare una \textit{fifo}. Per utilizzarne una -un processo non avrà che da aprire il relativo \index{file!speciali} file -speciale o in lettura o scrittura; nel primo caso il processo sarà collegato -al capo di uscita della \textit{fifo}, e dovrà leggere, nel secondo al capo di -ingresso, e dovrà scrivere. +un processo non avrà che da aprire il relativo file speciale o in lettura o +scrittura; nel primo caso il processo sarà collegato al capo di uscita della +\textit{fifo}, e dovrà leggere, nel secondo al capo di ingresso, e dovrà +scrivere. Il kernel alloca un singolo buffer per ciascuna \textit{fifo} che sia stata aperta, e questa potrà essere acceduta contemporaneamente da più processi, sia @@ -539,9 +538,8 @@ una \textit{fifo} in scrittura anche se non ci sono ancora processi il lettura. Infine è possibile anche usare la \textit{fifo} all'interno di un solo processo, nel qual caso però occorre stare molto attenti alla possibili situazioni di stallo: se si cerca di leggere da una \textit{fifo} che non -contiene dati si avrà infatti un \itindex{deadlock} \textit{deadlock} -immediato, dato che il processo si blocca e quindi non potrà mai eseguire le -funzioni di scrittura. +contiene dati si avrà infatti un \textit{deadlock} immediato, dato che il +processo si blocca e quindi non potrà mai eseguire le funzioni di scrittura. Per la loro caratteristica di essere accessibili attraverso il filesystem, è piuttosto frequente l'utilizzo di una \textit{fifo} come canale di @@ -649,7 +647,7 @@ due volte, prima in lettura e poi in scrittura, per evitare di dover gestire all'interno del ciclo principale il caso in cui il server è in ascolto ma non ci sono client che effettuano richieste. Si ricordi infatti che quando una \textit{fifo} è aperta solo dal capo in lettura, l'esecuzione di \func{read} -ritorna con zero byte (si ha cioè una condizione di end-of-file). +ritorna con zero byte (si ha cioè una condizione di \textit{end-of-file}). Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque client non apre a sua volta la \textit{fifo} nota in scrittura per effettuare @@ -739,7 +737,7 @@ scrittura e l'apertura si sarebbe bloccata indefinitamente. Verifichiamo allora il comportamento dei nostri programmi, in questo, come in altri esempi precedenti, si fa uso delle varie funzioni di servizio, che sono -state raccolte nella libreria \file{libgapil.so}, per poter usare quest'ultima +state raccolte nella libreria \file{libgapil.so}, e per poterla usare occorrerà definire la variabile di ambiente \envvar{LD\_LIBRARY\_PATH} in modo che il linker dinamico possa accedervi. @@ -821,21 +819,21 @@ presenta il problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti \textsl{socket locali} (o \textit{Unix domain socket}). Tratteremo in generale i socket in cap.~\ref{cha:socket_intro}, nell'ambito dell'interfaccia che essi forniscono per la programmazione di rete, e vedremo -anche (in~sez.~\ref{sec:sock_sa_local}) come si possono utilizzare i -\index{file!speciali} file speciali di tipo socket, analoghi a quelli -associati alle \textit{fifo} (si rammenti sez.~\ref{sec:file_file_types}) cui -si accede però attraverso quella medesima interfaccia; vale però la pena -esaminare qui una modalità di uso dei socket locali che li rende -sostanzialmente identici ad una \textit{pipe} bidirezionale. +anche (in~sez.~\ref{sec:sock_sa_local}) come si possono utilizzare i file +speciali di tipo socket, analoghi a quelli associati alle \textit{fifo} (si +rammenti sez.~\ref{sec:file_file_types}) cui si accede però attraverso quella +medesima interfaccia; vale però la pena esaminare qui una modalità di uso dei +socket locali che li rende sostanzialmente identici ad una \textit{pipe} +bidirezionale. La funzione di sistema \funcd{socketpair}, introdotta da BSD ma supportata in genere da qualunque sistema che fornisca l'interfaccia dei socket ed inclusa in POSIX.1-2001, consente infatti di creare una coppia di file descriptor connessi fra loro (tramite un socket, appunto) senza dover ricorrere ad un -\index{file!speciali} file speciale sul filesystem. I descrittori sono del -tutto analoghi a quelli che si avrebbero con una chiamata a \func{pipe}, con -la sola differenza è che in questo caso il flusso dei dati può essere -effettuato in entrambe le direzioni. Il prototipo della funzione è: +file speciale sul filesystem. I descrittori sono del tutto analoghi a quelli +che si avrebbero con una chiamata a \func{pipe}, con la sola differenza è che +in questo caso il flusso dei dati può essere effettuato in entrambe le +direzioni. Il prototipo della funzione è: \begin{funcproto}{ \fhead{sys/types.h} @@ -865,11 +863,11 @@ connettere i due descrittori, ma in questo caso i soli valori validi che possono essere specificati sono rispettivamente \const{AF\_UNIX}, \const{SOCK\_STREAM} e \val{0}. -A partire dal kernel 2.6.27 la funzione supporta anche l'uso dei flag -\const{SOCK\_NONBLOCK} e \const{SOCK\_CLOEXEC} (trattati in -sez.~\ref{sec:sock_type}) nell'indicazione del tipo di socket, con effetto -identico agli analoghi \const{O\_CLOEXEC} e \const{O\_NONBLOCK} di una -\func{open} (vedi tab.~\ref{tab:open_operation_flag}). +A partire dal kernel 2.6.27 la funzione supporta nell'indicazione del tipo di +socket anche i due flag \const{SOCK\_NONBLOCK} e \const{SOCK\_CLOEXEC} +(trattati in sez.~\ref{sec:sock_type}), con effetto identico agli analoghi +\const{O\_CLOEXEC} e \const{O\_NONBLOCK} di una \func{open} (vedi +tab.~\ref{tab:open_operation_flag}). L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe} può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei socket @@ -947,7 +945,7 @@ mantiene varie proprietà ed informazioni associate all'oggetto. \end{minipage} \normalsize \caption{La struttura \structd{ipc\_perm}, come definita in - \headfile{sys/ipc.h}.} + \headfiled{sys/ipc.h}.} \label{fig:ipc_ipc_perm} \end{figure} @@ -955,7 +953,7 @@ Usando la stessa chiave due processi diversi possono ricavare l'identificatore associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi sono \textsl{imparentati} la soluzione è relativamente semplice, in tal caso -infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un +infatti si può usare il valore speciale \constd{IPC\_PRIVATE} per creare un nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà disponibile in tutti i figli, e potrà essere passato come argomento attraverso una \func{exec}. @@ -995,13 +993,12 @@ meno significativi. Il problema è che anche così non c'è la sicurezza che il valore della chiave sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)} -con i 16 bit meno significativi \itindex{inode} dell'inode del file -\param{pathname} (che vengono ottenuti attraverso \func{stat}, da cui derivano -i possibili errori), e gli 8 bit meno significativi del numero del dispositivo -su cui è il file. Diventa perciò relativamente facile ottenere delle -collisioni, specie se i file sono su dispositivi con lo stesso -\itindex{minor~number} \textit{minor number}, come \file{/dev/hda1} e -\file{/dev/sda1}. +con i 16 bit meno significativi dell'inode del file \param{pathname} (che +vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori), +e gli 8 bit meno significativi del numero del dispositivo su cui è il file. +Diventa perciò relativamente facile ottenere delle collisioni, specie se i +file sono su dispositivi con lo stesso \textit{minor number}, come +\file{/dev/hda1} e \file{/dev/sda1}. In genere quello che si fa è utilizzare un file comune usato dai programmi che devono comunicare (ad esempio un header comune, o uno dei programmi che devono @@ -1047,8 +1044,8 @@ il proprietario, il suo gruppo e tutti gli altri. Se però si vogliono usare le costanti simboliche di tab.~\ref{tab:file_mode_flags} occorrerà includere anche il file -\headfile{sys/stat.h}; alcuni sistemi definiscono le costanti \const{MSG\_R} -(il valore ottale \texttt{0400}) e \const{MSG\_W} (il valore ottale +\headfile{sys/stat.h}; alcuni sistemi definiscono le costanti \constd{MSG\_R} +(il valore ottale \texttt{0400}) e \constd{MSG\_W} (il valore ottale \texttt{0200}) per indicare i permessi base di lettura e scrittura per il proprietario, da utilizzare, con gli opportuni shift, pure per il gruppo e gli altri. In Linux, visto la loro scarsa utilità, queste costanti non sono @@ -1074,9 +1071,8 @@ 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*} -\item se il processo ha i privilegi di amministratore (più precisamente la - capacità \itindex{capability} \const{CAP\_IPC\_OWNER}) l'accesso è sempre - consentito. +\item se il processo ha i privilegi di amministratore (più precisamente + \const{CAP\_IPC\_OWNER}) l'accesso è sempre consentito. \item se l'\ids{UID} effettivo del processo corrisponde o al valore del campo \var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario in \var{mode} è appropriato\footnote{per appropriato si intende che è @@ -1091,7 +1087,7 @@ 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 differenza rispetto a quanto avviene per i file è che per gli oggetti di IPC -il valore di \itindex{umask} \textit{umask} (si ricordi quanto esposto in +il valore di \textit{umask} (si ricordi quanto esposto in sez.~\ref{sec:file_perm_management}) non ha alcun significato. @@ -1131,7 +1127,7 @@ Il sistema dispone sempre di un numero fisso di oggetti di IPC, fino al kernel relativi al \textit{SysV-IPC}) solo con una ricompilazione del kernel. A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo scrivendo sui file \sysctlrelfile{kernel}{shmmni}, -\sysctlrelfile{kernel}{msgmni} e \sysctlrelfile{kernel}{sem} di +\sysctlrelfile{kernel}{msgmni} e \sysctlrelfiled{kernel}{sem} di \file{/proc/sys/kernel} o con l'uso di \func{sysctl}. \begin{figure}[!htb] @@ -1154,7 +1150,7 @@ numero di oggetti presenti viene sommato il valore corrente del campo Questo in realtà è quanto avveniva fino ai kernel della serie 2.2, dalla serie 2.4 viene usato lo stesso fattore di moltiplicazione per qualunque tipo di -oggetto, utilizzando il valore dalla costante \const{IPCMNI} (definita in +oggetto, utilizzando il valore dalla costante \constd{IPCMNI} (definita in \file{include/linux/ipc.h}), che indica il limite massimo complessivo per il numero di tutti gli oggetti presenti nel \textit{SysV-IPC}, ed il cui default è 32768. Si evita così il riutilizzo degli stessi numeri, e si fa sì che @@ -1270,10 +1266,10 @@ validi. Se invece si vuole creare una nuova coda di messaggi \param{flag} non può essere nullo e deve essere fornito come maschera binaria, impostando il bit -corrispondente al valore \const{IPC\_CREAT}. In questo caso i nove bit meno +corrispondente al valore \constd{IPC\_CREAT}. In questo caso i nove bit meno significativi di \param{flag} saranno usati come permessi per il nuovo oggetto, secondo quanto illustrato in sez.~\ref{sec:ipc_sysv_access_control}. -Se si imposta anche il bit corrispondente a \const{IPC\_EXCL} la funzione avrà +Se si imposta anche il bit corrispondente a \constd{IPC\_EXCL} la funzione avrà successo solo se l'oggetto non esiste già, fallendo con un errore di \errcode{EEXIST} altrimenti. @@ -1295,11 +1291,11 @@ creazione di una nuova coda. & \textbf{Significato} \\ \hline \hline - \const{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di + \constd{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di messaggi.\\ - \const{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo + \constd{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo messaggio.\\ - \const{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di + \constd{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di una coda.\\ \hline \end{tabular} @@ -1311,37 +1307,42 @@ Le code di messaggi sono caratterizzate da tre limiti fondamentali, un tempo definiti staticamente e corrispondenti alle prime tre costanti riportate in tab.~\ref{tab:ipc_msg_limits}. Come accennato però con tutte le versioni più recenti del kernel con Linux è possibile modificare questi limiti attraverso -l'uso di \func{sysctl} o scrivendo nei file \sysctlrelfile{kernel}{msgmax}, -\sysctlrelfile{kernel}{msgmnb} e \sysctlrelfile{kernel}{msgmni} di +l'uso di \func{sysctl} o scrivendo nei file \sysctlrelfiled{kernel}{msgmax}, +\sysctlrelfiled{kernel}{msgmnb} e \sysctlrelfiled{kernel}{msgmni} di \file{/proc/sys/kernel/}. -Una coda di messaggi è costituita da una \itindex{linked~list} \textit{linked - list}.\footnote{una \itindex{linked~list} \textit{linked list} è una tipica - struttura di dati, organizzati in una lista in cui ciascun elemento contiene - un puntatore al successivo. In questo modo la struttura è veloce - nell'estrazione ed immissione dei dati dalle estremità dalla lista (basta - aggiungere un elemento in testa o in coda ed aggiornare un puntatore), e - relativamente veloce da attraversare in ordine sequenziale (seguendo i - puntatori), è invece relativamente lenta nell'accesso casuale e nella - ricerca.} I nuovi messaggi vengono inseriti in coda alla lista e vengono -letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si è riportato uno schema -semplificato con cui queste strutture vengono mantenute dal kernel. Lo schema -illustrato in realtà è una semplificazione di quello usato fino ai kernel -della serie 2.2. A partire della serie 2.4 la gestione delle code di messaggi -è effettuata in maniera diversa (e non esiste una struttura \struct{msqid\_ds} -nel kernel), ma abbiamo mantenuto lo schema precedente dato che illustra in -maniera più che adeguata i principi di funzionamento delle code di messaggi. +\itindbeg{linked~list} + +Una coda di messaggi è costituita da una \textit{linked list}.\footnote{una + \textit{linked list} è una tipica struttura di dati, organizzati in una + lista in cui ciascun elemento contiene un puntatore al successivo. In questo + modo la struttura è veloce nell'estrazione ed immissione dei dati dalle + estremità dalla lista (basta aggiungere un elemento in testa o in coda ed + aggiornare un puntatore), e relativamente veloce da attraversare in ordine + sequenziale (seguendo i puntatori), è invece relativamente lenta + nell'accesso casuale e nella ricerca.} I nuovi messaggi vengono inseriti in +coda alla lista e vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si +è riportato uno schema semplificato con cui queste strutture vengono mantenute +dal kernel. Lo schema illustrato in realtà è una semplificazione di quello +usato fino ai kernel della serie 2.2. A partire della serie 2.4 la gestione +delle code di messaggi è effettuata in maniera diversa (e non esiste una +struttura \kstruct{msqid\_ds} nel kernel), ma abbiamo mantenuto lo schema +precedente dato che illustra in maniera più che adeguata i principi di +funzionamento delle code di messaggi. + +\itindend{linked~list} \begin{figure}[!htb] \centering \includegraphics[width=13cm]{img/mqstruct} - \caption{Schema della struttura di una coda messaggi.} + \caption{Schema delle strutture di una coda di messaggi + (\kstructd{msqid\_ds} e \kstructd{msg}).} \label{fig:ipc_mq_schema} \end{figure} -A ciascuna coda è associata una struttura \struct{msqid\_ds} la cui +A ciascuna coda è associata una struttura \kstruct{msqid\_ds} la cui definizione è riportata in fig.~\ref{fig:ipc_msqid_ds} ed a cui si accede -includendo \headfile{sys/msg.h}; +includendo \headfiled{sys/msg.h}; % % INFO: sotto materiale obsoleto e non interessante % In questa struttura il @@ -1360,7 +1361,7 @@ come \ctyp{short}. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{.90\textwidth} + \begin{minipage}[c]{.91\textwidth} \includestruct{listati/msqid_ds.h} \end{minipage} \normalsize @@ -1395,7 +1396,7 @@ riguarda gli altri campi invece: % primo e ultimo messaggio sono inizializzati a \val{NULL} e % \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è % inizializzato a zero. Questi campi sono ad uso interno dell'implementazione -% e non devono essere utilizzati da programmi in user space). +% e non devono essere utilizzati da programmi in \textit{user space}). \end{itemize*} Una volta creata una coda di messaggi le operazioni di controllo vengono @@ -1433,17 +1434,17 @@ comportamento della funzione dipende dal valore dell'argomento \param{cmd}, che specifica il tipo di azione da eseguire. I valori possibili per \param{cmd} sono: \begin{basedescript}{\desclabelwidth{1.6cm}\desclabelstyle{\nextlinelabel}} -\item[\const{IPC\_STAT}] Legge le informazioni riguardo la coda nella +\item[\constd{IPC\_STAT}] Legge le informazioni riguardo la coda nella struttura \struct{msqid\_ds} indicata da \param{buf}. Occorre avere il permesso di lettura sulla coda. -\item[\const{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con +\item[\constd{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con effetto immediato. Tutti i processi che cercheranno di accedere alla coda riceveranno un errore di \errcode{EIDRM}, e tutti processi in attesa su funzioni di lettura o di scrittura sulla coda saranno svegliati ricevendo il medesimo errore. Questo comando può essere eseguito solo da un processo con \ids{UID} effettivo corrispondente al creatore o al proprietario della coda, o all'amministratore. -\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario +\item[\constd{IPC\_SET}] Permette di modificare i permessi ed il proprietario della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in essa contenuti (\var{msg\_qbytes}). I valori devono essere passati in una struttura \struct{msqid\_ds} puntata da \param{buf}. Per modificare i @@ -1451,14 +1452,14 @@ per \param{cmd} sono: occorre essere il proprietario o il creatore della coda, oppure l'amministratore e lo stesso vale per \var{msg\_qbytes}. Infine solo l'amministratore (più precisamente un processo con la capacità - \itindex{capability} \const{CAP\_IPC\_RESOURCE}) ha la facoltà di - incrementarne il valore a limiti superiori a \const{MSGMNB}. Se eseguita con - successo la funzione aggiorna anche il campo \var{msg\_ctime}. + \const{CAP\_IPC\_RESOURCE}) ha la facoltà di incrementarne il valore a + limiti superiori a \const{MSGMNB}. Se eseguita con successo la funzione + aggiorna anche il campo \var{msg\_ctime}. \end{basedescript} A questi tre valori, che sono quelli previsti dallo standard, su Linux se ne -affiancano altri tre (\const{IPC\_INFO}, \const{MSG\_STAT} e -\const{MSG\_INFO}) introdotti ad uso del programma \cmd{ipcs} per ottenere le +affiancano altri tre (\constd{IPC\_INFO}, \constd{MSG\_STAT} e +\constd{MSG\_INFO}) introdotti ad uso del programma \cmd{ipcs} per ottenere le informazioni generali relative alle risorse usate dalle code di messaggi. Questi potranno essere modificati o rimossi in favore dell'uso di \texttt{/proc}, per cui non devono essere usati e non li tratteremo. @@ -1531,24 +1532,24 @@ argomento è solo quella del messaggio, non quella di tutta la struttura, se cioè \var{message} è una propria struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se consideriamo il caso dell'esempio in fig.~\ref{fig:ipc_msbuf}, \param{msgsz} -dovrà essere pari a \const{LENGTH}). +dovrà essere pari a \var{LENGTH}). Per capire meglio il funzionamento della funzione riprendiamo in considerazione la struttura della coda illustrata in -fig.~\ref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio -sarà aggiunto in fondo alla lista inserendo una nuova struttura \struct{msg}, -il puntatore \var{msg\_last} di \struct{msqid\_ds} verrà aggiornato, come pure -il puntatore al messaggio successivo per quello che era il precedente ultimo -messaggio; il valore di \var{mtype} verrà mantenuto in \var{msg\_type} ed il -valore di \param{msgsz} in \var{msg\_ts}; il testo del messaggio sarà copiato -all'indirizzo specificato da \var{msg\_spot}. +fig.~\ref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo +messaggio sarà aggiunto in fondo alla lista inserendo una nuova struttura +\kstruct{msg}, il puntatore \var{msg\_last} di \kstruct{msqid\_ds} verrà +aggiornato, come pure il puntatore al messaggio successivo per quello che era +il precedente ultimo messaggio; il valore di \var{mtype} verrà mantenuto in +\var{msg\_type} ed il valore di \param{msgsz} in \var{msg\_ts}; il testo del +messaggio sarà copiato all'indirizzo specificato da \var{msg\_spot}. Il valore dell'argomento \param{flag} permette di specificare il comportamento della funzione. Di norma, quando si specifica un valore nullo, la funzione ritorna immediatamente a meno che si sia ecceduto il valore di \var{msg\_qbytes}, o il limite di sistema sul numero di messaggi, nel qual caso si blocca. Se si specifica per \param{flag} il valore -\const{IPC\_NOWAIT} la funzione opera in modalità non-bloccante, ed in questi +\constd{IPC\_NOWAIT} la funzione opera in modalità non-bloccante, ed in questi casi ritorna immediatamente con un errore di \errcode{EAGAIN}. Se non si specifica \const{IPC\_NOWAIT} la funzione resterà bloccata fintanto @@ -1600,11 +1601,11 @@ scrivendolo sulla struttura puntata da \param{msgp}, che dovrà avere un formato analogo a quello di fig.~\ref{fig:ipc_msbuf}. Una volta estratto, il messaggio sarà rimosso dalla coda. L'argomento \param{msgsz} indica la lunghezza massima del testo del messaggio (equivalente al valore del parametro -\const{LENGTH} nell'esempio di fig.~\ref{fig:ipc_msbuf}). +\var{LENGTH} nell'esempio di fig.~\ref{fig:ipc_msbuf}). Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a -\const{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene +\constd{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con un errore di \errcode{E2BIG}. @@ -1628,7 +1629,7 @@ coda, è quello meno recente); in particolare: Il valore di \param{msgflg} permette di controllare il comportamento della funzione, esso può essere nullo o una maschera binaria composta da uno o più valori. Oltre al precedente \const{MSG\_NOERROR}, sono possibili altri due -valori: \const{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo, +valori: \constd{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo, di leggere il primo messaggio nella coda con tipo diverso da \param{msgtyp}, e \const{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non ci sono messaggi sulla coda. @@ -1667,8 +1668,7 @@ possono essere utilizzate, e non si ha a disposizione niente di analogo alle funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di una di queste strutture alla volta; ad esempio non si può scrivere un server che aspetti un messaggio su più di una coda senza fare ricorso ad una tecnica -di \itindex{polling} \textit{polling} che esegua un ciclo di attesa su -ciascuna di esse. +di \textit{polling} che esegua un ciclo di attesa su ciascuna di esse. Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro server di \textit{fortunes} usando queste al posto delle \textit{fifo}. In @@ -1834,9 +1834,9 @@ lettura della risposta, quest'ultima resta nella coda (così come per le \textit{fifo} si aveva il problema delle \textit{fifo} che restavano nel filesystem). In questo caso però il problemi sono maggiori, sia perché è molto più facile esaurire la memoria dedicata ad una coda di messaggi che gli -\itindex{inode} \textit{inode} di un filesystem, sia perché, con il riutilizzo -dei \ids{PID} da parte dei processi, un client eseguito in un momento -successivo potrebbe ricevere un messaggio non indirizzato a lui. +\textit{inode} di un filesystem, sia perché, con il riutilizzo 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} @@ -1845,14 +1845,13 @@ successivo potrebbe ricevere un messaggio non indirizzato a lui. I semafori non sono propriamente meccanismi di intercomunicazione come \textit{pipe}, \textit{fifo} e code di messaggi, poiché non consentono di scambiare dati fra processi, ma servono piuttosto come meccanismi di -sincronizzazione o di protezione per le \index{sezione~critica} -\textsl{sezioni critiche} del codice (si ricordi quanto detto in -sez.~\ref{sec:proc_race_cond}). Un semaforo infatti non è altro che un -contatore mantenuto nel kernel che determina se consentire o meno la -prosecuzione dell'esecuzione di un programma. In questo modo si può -controllare l'accesso ad una risorsa condivisa da più processi, associandovi -un semaforo che assicuri che non possa essere usata da più di un processo alla -volta. +sincronizzazione o di protezione per le \textsl{sezioni critiche} del codice +(si ricordi quanto detto in sez.~\ref{sec:proc_race_cond}). Un semaforo +infatti non è altro che un contatore mantenuto nel kernel che determina se +consentire o meno la prosecuzione dell'esecuzione di un programma. In questo +modo si può controllare l'accesso ad una risorsa condivisa da più processi, +associandovi un semaforo che assicuri che non possa essere usata da più di un +processo alla volta. Il concetto di semaforo è uno dei concetti base nella programmazione ed è assolutamente generico, così come del tutto generali sono modalità con cui lo @@ -1945,7 +1944,7 @@ processo, e la gestione diventa più complicata. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{.80\textwidth} + \begin{minipage}[c]{.85\textwidth} \includestruct{listati/semid_ds.h} \end{minipage} \normalsize @@ -1975,7 +1974,7 @@ quanto riguarda gli altri campi invece: \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{.80\textwidth} + \begin{minipage}[c]{.85\textwidth} \includestruct{listati/sem.h} \end{minipage} \normalsize @@ -2020,17 +2019,17 @@ direttamente nel file \sysctlfile{kernel/sem}. \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{SEMMNI}& 128 & Numero massimo di insiemi di semafori.\\ - \const{SEMMSL}& 250 & Numero massimo di semafori per insieme.\\ - \const{SEMMNS}&\const{SEMMNI}*\const{SEMMSL}& Numero massimo di semafori - nel sistema.\\ - \const{SEMVMX}& 32767 & Massimo valore per un semaforo.\\ - \const{SEMOPM}& 32 & Massimo numero di operazioni per chiamata a - \func{semop}. \\ - \const{SEMMNU}&\const{SEMMNS}& Massimo numero di strutture di ripristino.\\ - \const{SEMUME}&\const{SEMOPM}& Massimo numero di voci di ripristino.\\ - \const{SEMAEM}&\const{SEMVMX}& Valore massimo per l'aggiustamento - all'uscita. \\ + \constd{SEMMNI}& 128 & Numero massimo di insiemi di semafori.\\ + \constd{SEMMSL}& 250 & Numero massimo di semafori per insieme.\\ + \constd{SEMMNS}&\const{SEMMNI}*\const{SEMMSL}& Numero massimo di semafori + nel sistema.\\ + \constd{SEMVMX}& 32767 & Massimo valore per un semaforo.\\ + \constd{SEMOPM}& 32 & Massimo numero di operazioni per chiamata a + \func{semop}. \\ + \constd{SEMMNU}&\const{SEMMNS}& Massimo numero di strutture di ripristino.\\ + \constd{SEMUME}&\const{SEMOPM}& Massimo numero di voci di ripristino.\\ + \constd{SEMAEM}&\const{SEMVMX}& Valore massimo per l'aggiustamento + all'uscita. \\ \hline \end{tabular} \caption{Valori delle costanti associate ai limiti degli insiemi di @@ -2083,7 +2082,7 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da \includestruct{listati/semun.h} \end{minipage} \normalsize - \caption{La definizione dei possibili valori di una \direct{union} + \caption{La definizione dei possibili valori di una \dirct{union} \structd{semun}, usata come quarto argomento della funzione \func{semctl}.} \label{fig:ipc_semun} @@ -2095,11 +2094,11 @@ unificare detto argomento esso deve essere passato come una unione \struct{semun}, la cui definizione, con i possibili valori che può assumere, è riportata in fig.~\ref{fig:ipc_semun}. -Nelle versioni più vecchie delle \acr{glibc} questa unione veniva definita in +Nelle versioni più vecchie della \acr{glibc} questa unione veniva definita in \file{sys/sem.h}, ma nelle versioni più recenti questo non avviene più in quanto lo standard POSIX.1-2001 richiede che sia sempre definita a cura del -chiamante. In questa seconda evenienza le \acr{glibc} definiscono però la -macro \macro{\_SEM\_SEMUN\_UNDEFINED} che può essere usata per controllare la +chiamante. In questa seconda evenienza la \acr{glibc} definisce però la +macro \macrod{\_SEM\_SEMUN\_UNDEFINED} che può essere usata per controllare la situazione. Come già accennato sia il comportamento della funzione che il numero di @@ -2126,40 +2125,40 @@ i seguenti: \var{sem\_ctime}. L'\ids{UID} effettivo del processo deve corrispondere o al creatore o al proprietario dell'insieme, o all'amministratore. L'argomento \param{semnum} viene ignorato. -\item[\const{GETALL}] Restituisce il valore corrente di ciascun semaforo +\item[\constd{GETALL}] Restituisce il valore corrente di ciascun semaforo dell'insieme (corrispondente al campo \var{semval} di \struct{sem}) nel vettore indicato da \param{arg.array}. Occorre avere il permesso di lettura. L'argomento \param{semnum} viene ignorato. -\item[\const{GETNCNT}] Restituisce come valore di ritorno della funzione il +\item[\constd{GETNCNT}] Restituisce come valore di ritorno della funzione il numero di processi in attesa che il semaforo \param{semnum} dell'insieme \param{semid} venga incrementato (corrispondente al campo \var{semncnt} di \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. -\item[\const{GETPID}] Restituisce come valore di ritorno della funzione il +\item[\constd{GETPID}] Restituisce come valore di ritorno della funzione il \ids{PID} dell'ultimo processo che ha compiuto una operazione sul semaforo \param{semnum} dell'insieme \param{semid} (corrispondente al campo \var{sempid} di \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. -\item[\const{GETVAL}] Restituisce come valore di ritorno della funzione il il +\item[\constd{GETVAL}] Restituisce come valore di ritorno della funzione il valore corrente del semaforo \param{semnum} dell'insieme \param{semid} (corrispondente al campo \var{semval} di \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. -\item[\const{GETZCNT}] Restituisce come valore di ritorno della funzione il +\item[\constd{GETZCNT}] Restituisce come valore di ritorno della funzione il numero di processi in attesa che il valore del semaforo \param{semnum} dell'insieme \param{semid} diventi nullo (corrispondente al campo \var{semncnt} di \struct{sem}). Va invocata con tre argomenti. Occorre avere il permesso di lettura. -\item[\const{SETALL}] Inizializza il valore di tutti i semafori dell'insieme, +\item[\constd{SETALL}] Inizializza il valore di tutti i semafori dell'insieme, aggiornando il campo \var{sem\_ctime} di \struct{semid\_ds}. I valori devono essere passati nel vettore indicato da \param{arg.array}. Si devono avere i privilegi di scrittura. L'argomento \param{semnum} viene ignorato. -\item[\const{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato +\item[\constd{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di \struct{semid\_ds}. Si devono avere i privilegi di scrittura. \end{basedescript} Come per \func{msgctl} esistono tre ulteriori valori, \const{IPC\_INFO}, -\const{SEM\_STAT} e \const{SEM\_INFO}, specifici di Linux e fuori da ogni +\constd{SEM\_STAT} e \constd{SEM\_INFO}, specifici di Linux e fuori da ogni standard, creati specificamente ad uso del comando \cmd{ipcs}. Dato che anche questi potranno essere modificati o rimossi, non devono essere utilizzati e pertanto non li tratteremo. @@ -2243,7 +2242,7 @@ vettore \param{sops}. Con lo standard POSIX.1-2001 è stata introdotta una variante di \func{semop} che consente di specificare anche un tempo massimo di attesa. La nuova -funzione di sistema, disponibile a partire dal kernel 2.4.22 e dalle +funzione di sistema, disponibile a partire dal kernel 2.4.22 e dalla \acr{glibc} 2.3.3, ed utilizzabile solo dopo aver definito la macro \macro{\_GNU\_SOURCE}, è \funcd{semtimedop}, ed il suo prototipo è: @@ -2304,7 +2303,7 @@ un valore nullo di \var{sem\_num}. Il campo \var{sem\_flg} è un flag, mantenuto come maschera binaria, per il quale possono essere impostati i due valori \const{IPC\_NOWAIT} e -\const{SEM\_UNDO}. Impostando \const{IPC\_NOWAIT} si fa si che in tutti quei +\constd{SEM\_UNDO}. Impostando \const{IPC\_NOWAIT} si fa sì che in tutti quei casi in cui l'esecuzione di una operazione richiederebbe di porre il processo vada nello stato di \textit{sleep}, invece di bloccarsi \func{semop} ritorni immediatamente (abortendo così le eventuali operazioni restanti) con un errore @@ -2408,25 +2407,26 @@ versioni delle librerie del C, come le \acr{libc5}). \begin{figure}[!htb] \centering \includegraphics[width=12cm]{img/semtruct} - \caption{Schema della struttura di un insieme di semafori.} + \caption{Schema delle varie strutture di un insieme di semafori + (\kstructd{semid\_ds}, \kstructd{sem}, \kstructd{sem\_queue} e + \kstructd{sem\_undo}).} \label{fig:ipc_sem_schema} \end{figure} Alla creazione di un nuovo insieme viene allocata una nuova strutture -\struct{semid\_ds} ed il relativo vettore di strutture \struct{sem}. Quando si -richiede una operazione viene anzitutto verificato che tutte le operazioni +\kstruct{semid\_ds} ed il relativo vettore di strutture \kstruct{sem}. Quando +si richiede una operazione viene anzitutto verificato che tutte le operazioni possono avere successo; se una di esse comporta il blocco del processo il kernel crea una struttura \kstruct{sem\_queue} che viene aggiunta in fondo alla coda di attesa associata a ciascun insieme di semafori, che viene referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last} di -\struct{semid\_ds}. Nella struttura viene memorizzato il riferimento alle +\kstruct{semid\_ds}. Nella struttura viene memorizzato il riferimento alle operazioni richieste (nel campo \var{sops}, che è un puntatore ad una struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper}) poi quest'ultimo viene messo stato di attesa e viene invocato lo -\itindex{scheduler} \textit{scheduler} per passare all'esecuzione di un altro -processo. +\textit{scheduler} per passare all'esecuzione di un altro processo. -Se invece tutte le operazioni possono avere successo queste vengono eseguite +Se invece tutte le operazioni possono avere successo vengono eseguite immediatamente, dopo di che il kernel esegue una scansione della coda di attesa (a partire da \var{sem\_pending}) per verificare se qualcuna delle operazioni sospese in precedenza può essere eseguita, nel qual caso la @@ -2540,7 +2540,7 @@ controllare il valore dei mutex prima di proseguire in una operazione di sblocco non servirebbe comunque, dato che l'operazione non sarebbe atomica. Vedremo in sez.~\ref{sec:ipc_lock_file} come sia possibile ottenere un'interfaccia analoga a quella appena illustrata, senza incorrere in questi -problemi, usando il \itindex{file~locking} \textit{file locking}. +problemi, usando il \textit{file locking}. \subsection{Memoria condivisa} @@ -2586,21 +2586,21 @@ l'argomento \param{flag}, specifici di \func{shmget}, attinenti alle modalità di gestione del segmento di memoria condivisa in relazione al sistema della memoria virtuale. -Il primo dei due flag è \const{SHM\_HUGETLB} che consente di richiedere la -creazione del segmento usando una \itindex{huge~page} \textit{huge page}, le -pagine di memoria di grandi dimensioni introdotte con il kernel 2.6 per -ottimizzare le prestazioni nei sistemi più recenti che hanno grandi quantità -di memoria. L'operazione è privilegiata e richiede che il processo abbia la -\itindex{capability} \textit{capability} \const{CAP\_IPC\_LOCK}. Questa -funzionalità è specifica di Linux e non è portabile. +Il primo dei due flag è \constd{SHM\_HUGETLB} che consente di richiedere la +creazione del segmento usando una \textit{huge page}, le pagine di memoria di +grandi dimensioni introdotte con il kernel 2.6 per ottimizzare le prestazioni +nei sistemi più recenti che hanno grandi quantità di memoria. L'operazione è +privilegiata e richiede che il processo abbia la \textit{capability} +\const{CAP\_IPC\_LOCK}. Questa funzionalità è specifica di Linux e non è +portabile. Il secondo flag aggiuntivo, introdotto a partire dal kernel 2.6.15, è -\const{SHM\_NORESERVE}, ed ha lo stesso scopo del flag \const{MAP\_NORESERVE} +\constd{SHM\_NORESERVE}, ed ha lo stesso scopo del flag \const{MAP\_NORESERVE} di \func{mmap} (vedi sez.~\ref{sec:file_memory_map}): non vengono riservate -delle pagine di swap ad uso del meccanismo del \textit{copy on write} -\itindex{copy~on~write} per mantenere le modifiche fatte sul segmento. Questo -significa che caso di scrittura sul segmento quando non c'è più memoria -disponibile, si avrà l'emissione di un \signal{SIGSEGV}. +delle pagine di swap ad uso del meccanismo del \textit{copy on write} per +mantenere le modifiche fatte sul segmento. Questo significa che caso di +scrittura sul segmento quando non c'è più memoria disponibile, si avrà +l'emissione di un \signal{SIGSEGV}. Infine l'argomento \param{size} specifica la dimensione del segmento di memoria condivisa; il valore deve essere specificato in byte, ma verrà @@ -2684,27 +2684,27 @@ che permettono di cambiarne il valore. & \textbf{Significato} \\ \hline \hline - \const{SHMALL}& 0x200000&\sysctlrelfile{kernel}{shmall} - & Numero massimo di pagine che - possono essere usate per i segmenti di - memoria condivisa.\\ - \const{SHMMAX}&0x2000000&\sysctlrelfile{kernel}{shmmax} - & Dimensione massima di un segmento di memoria - condivisa.\\ - \const{SHMMNI}& 4096&\sysctlrelfile{kernel}{msgmni} - & Numero massimo di segmenti di memoria condivisa + \constd{SHMALL}& 0x200000&\sysctlrelfiled{kernel}{shmall} + & Numero massimo di pagine che + possono essere usate per i segmenti di + memoria condivisa.\\ + \constd{SHMMAX}&0x2000000&\sysctlrelfiled{kernel}{shmmax} + & Dimensione massima di un segmento di memoria + condivisa.\\ + \constd{SHMMNI}& 4096&\sysctlrelfiled{kernel}{shmmni} + & Numero massimo di segmenti di memoria condivisa presenti nel kernel.\\ - \const{SHMMIN}& 1& --- & Dimensione minima di un segmento di - memoria condivisa.\\ - \const{SHMLBA}&\const{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni - minime di un segmento (deve essere - allineato alle dimensioni di una - pagina di memoria).\\ - \const{SHMSEG}& --- & --- & Numero massimo di segmenti di - memoria condivisa per ciascun - processo (l'implementazione non - prevede l'esistenza di questo - limite).\\ + \constd{SHMMIN}& 1& --- & Dimensione minima di un segmento di + memoria condivisa.\\ + \constd{SHMLBA}&\const{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni + minime di un segmento (deve essere + allineato alle dimensioni di una + pagina di memoria).\\ + \constd{SHMSEG}& --- & --- & Numero massimo di segmenti di + memoria condivisa per ciascun + processo (l'implementazione non + prevede l'esistenza di questo + limite).\\ \hline @@ -2774,24 +2774,21 @@ consentono di estendere le funzionalità, ovviamente non devono essere usati se si ha a cuore la portabilità. Questi comandi aggiuntivi sono: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} -\item[\const{SHM\_LOCK}] Abilita il \itindex{memory~locking} \textit{memory - locking} sul segmento di memoria condivisa, impedendo che la memoria usata - per il segmento venga salvata su disco dal meccanismo della - \index{memoria~virtuale} memoria virtuale. Come illustrato in +\item[\constd{SHM\_LOCK}] Abilita il \textit{memory locking} sul segmento di + memoria condivisa, impedendo che la memoria usata per il segmento venga + salvata su disco dal meccanismo della memoria virtuale. Come illustrato in 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 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} - \textit{memory locking} sul segmento di memoria condivisa. Fino al kernel - 2.6.9 solo l'amministratore poteva utilizzare questo comando in - corrispondenza di un segmento da lui bloccato. + \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal kernel 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[\constd{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento + di memoria condivisa. Fino al kernel 2.6.9 solo l'amministratore poteva + utilizzare questo comando in corrispondenza di un segmento da lui bloccato. \end{basedescript} A questi due, come per \func{msgctl} e \func{semctl}, si aggiungono tre -ulteriori valori, \const{IPC\_INFO}, \const{MSG\_STAT} e \const{MSG\_INFO}, +ulteriori valori, \const{IPC\_INFO}, \constd{SHM\_STAT} e \constd{SHM\_INFO}, introdotti ad uso del programma \cmd{ipcs} per ottenere le informazioni generali relative alle risorse usate dai segmenti di memoria condivisa. Dato che potranno essere modificati o rimossi in favore dell'uso di \texttt{/proc}, @@ -2818,7 +2815,7 @@ il suo prototipo è: } {La funzione ritorna l'indirizzo del segmento in caso di successo e $-1$ (in - un cast a \type{void *}) per un errore, nel qual caso \var{errno} assumerà + un cast a \ctyp{void *}) 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 al @@ -2850,8 +2847,8 @@ stato marcato per la cancellazione. L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{lo standard SVID prevede che l'argomento \param{shmaddr} sia di tipo \ctyp{char *}, così - come il valore di ritorno della funzione; in Linux è stato così con le - \acr{libc4} e le \acr{libc5}, con il passaggio alla \acr{glibc} il tipo di + come il valore di ritorno della funzione; in Linux è stato così con la + \acr{libc4} e la \acr{libc5}, con il passaggio alla \acr{glibc} il tipo di \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di ritorno un \ctyp{void *} seguendo POSIX.1-2001.} deve essere associato il segmento, se il valore specificato è \val{NULL} è il sistema a scegliere @@ -2870,33 +2867,33 @@ riferiti all'indirizzo di partenza del segmento). L'argomento \param{shmflg} permette di cambiare il comportamento della funzione; esso va specificato come maschera binaria, i bit utilizzati al -momento sono sono tre e sono identificati dalle costanti \const{SHM\_RND}, +momento sono tre e sono identificati dalle costanti \const{SHM\_RND}, \const{SHM\_RDONLY} e \const{SHM\_REMAP} che vanno combinate con un OR -aritmetico. +aritmetico. -Specificando \const{SHM\_RND} si evita che \func{shmat} ritorni un errore +Specificando \constd{SHM\_RND} si evita che \func{shmat} ritorni un errore quando \param{shmaddr} non è allineato ai confini di una pagina. Si può quindi usare un valore qualunque per \param{shmaddr}, e il segmento verrà comunque agganciato, ma al più vicino multiplo di \const{SHMLBA}; il nome della costante sta infatti per \textit{rounded}, e serve per specificare un indirizzo come arrotondamento. -L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola +L'uso di \constd{SHM\_RDONLY} permette di agganciare il segmento in sola lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal -caso un tentativo di scrivere sul segmento comporterà una -\itindex{segment~violation} violazione di accesso con l'emissione di un -segnale di \signal{SIGSEGV}. Il comportamento usuale di \func{shmat} è quello -di agganciare il segmento con l'accesso in lettura e scrittura (ed il processo -deve aver questi permessi in \var{shm\_perm}), non è prevista la possibilità -di agganciare un segmento in sola scrittura. - -Infine \const{SHM\_REMAP} è una estensione specifica di Linux (quindi non +caso un tentativo di scrivere sul segmento comporterà una violazione di +accesso con l'emissione di un segnale di \signal{SIGSEGV}. Il comportamento +usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in +lettura e scrittura (ed il processo deve aver questi permessi in +\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in +sola scrittura. + +Infine \constd{SHM\_REMAP} è una estensione specifica di Linux (quindi non portabile) che indica che la mappatura del segmento deve rimpiazzare ogni precedente mappatura esistente nell'intervallo iniziante all'indirizzo \param{shmaddr} e di dimensione pari alla lunghezza del segmento. In condizioni normali questo tipo di richiesta fallirebbe con un errore di \errval{EINVAL}. Ovviamente usando \const{SHM\_REMAP} -l'argomento \param{shmaddr} non può essere nullo. +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}: @@ -3037,10 +3034,10 @@ ricavare la parte di informazione che interessa. In fig.~\ref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del corpo del programma server, insieme alle definizioni delle altre funzioni -usate nel programma e delle \index{variabili!globali} variabili globali, -omettendo tutto quello che riguarda la gestione delle opzioni e la stampa -delle istruzioni di uso a video; al solito il codice completo si trova con i -sorgenti allegati nel file \file{DirMonitor.c}. +usate nel programma e delle variabili globali, omettendo tutto quello che +riguarda la gestione delle opzioni e la stampa delle istruzioni di uso a +video; al solito il codice completo si trova con i sorgenti allegati nel file +\file{DirMonitor.c}. \begin{figure}[!htbp] \footnotesize \centering @@ -3052,11 +3049,11 @@ sorgenti allegati nel file \file{DirMonitor.c}. \label{fig:ipc_dirmonitor_main} \end{figure} -Il programma usa delle \index{variabili!globali} variabili globali -(\texttt{\small 2-14}) per mantenere i valori relativi agli oggetti usati per -la comunicazione inter-processo; si è definita inoltre una apposita struttura -\struct{DirProp} che contiene i dati relativi alle proprietà che si vogliono -mantenere nella memoria condivisa, per l'accesso da parte dei client. +Il programma usa delle variabili globali (\texttt{\small 2-14}) per mantenere +i valori relativi agli oggetti usati per la comunicazione inter-processo; si è +definita inoltre una apposita struttura \struct{DirProp} che contiene i dati +relativi alle proprietà che si vogliono mantenere nella memoria condivisa, per +l'accesso da parte dei client. Il programma, dopo la sezione, omessa, relativa alla gestione delle opzioni da riga di comando (che si limitano alla eventuale stampa di un messaggio di @@ -3069,12 +3066,11 @@ con un messaggio di errore. Poi, per verificare che l'argomento specifichi effettivamente una directory, si esegue (\texttt{\small 24-26}) su di esso una \func{chdir}, uscendo immediatamente in caso di errore. Questa funzione serve anche per impostare -la \index{directory~di~lavoro} directory di lavoro del programma nella -directory da tenere sotto controllo, in vista del successivo uso della -funzione \func{daemon}. Si noti come si è potuta fare questa scelta, -nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il -particolare scopo del programma, che necessita comunque di restare all'interno -di una directory. +la directory di lavoro del programma nella directory da tenere sotto +controllo, in vista del successivo uso della funzione \func{daemon}. Si noti +come si è potuta fare questa scelta, nonostante le indicazioni illustrate in +sez.~\ref{sec:sess_daemon}, per il particolare scopo del programma, che +necessita comunque di restare all'interno di una directory. Infine (\texttt{\small 27-29}) si installano i gestori per i vari segnali di terminazione che, avendo a che fare con un programma che deve essere eseguito @@ -3103,9 +3099,9 @@ intercomunicazione il programma entra nel ciclo principale (\texttt{\small Il primo passo (\texttt{\small 41}) è eseguire \func{daemon} per proseguire con l'esecuzione in background come si conviene ad un programma demone; si noti che si è mantenuta, usando un valore non nullo del primo argomento, la -\index{directory~di~lavoro} directory di lavoro corrente. Una volta che il -programma è andato in background l'esecuzione prosegue all'interno di un ciclo -infinito (\texttt{\small 42-48}). +directory di lavoro corrente. Una volta che il programma è andato in +background l'esecuzione prosegue all'interno di un ciclo infinito +(\texttt{\small 42-48}). Si inizia (\texttt{\small 43}) bloccando il mutex con \func{MutexLock} per poter accedere alla memoria condivisa (la funzione si bloccherà @@ -3135,11 +3131,11 @@ esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari. Il codice di quest'ultima è riportato in fig.~\ref{fig:ipc_dirmonitor_sub}. -Come si vede la funzione (\texttt{\small 2-16}) è molto semplice e si limita -a chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da +Come si vede la funzione (\texttt{\small 2-16}) è molto semplice e si limita a +chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari -contatori nella memoria condivisa, cui accede grazie alla -\index{variabili!globali} variabile globale \var{shmptr}. +contatori nella memoria condivisa, cui accede grazie alla variabile globale +\var{shmptr}. Dato che la funzione è chiamata da \myfunc{dir\_scan}, si è all'interno del ciclo principale del programma, con un mutex acquisito, perciò non è @@ -3329,7 +3325,7 @@ relativamente poco diffuso. \subsection{I \textsl{file di lock}} \label{sec:ipc_file_lock} -\index{file!di lock|(} +\index{file!di~lock|(} Come illustrato in sez.~\ref{sec:ipc_sysv_sem} i semafori del \textit{SysV-IPC} presentano una interfaccia inutilmente complessa e con alcuni difetti @@ -3347,12 +3343,12 @@ directory, \file{/var/lock}, nella standardizzazione del \textit{Filesystem prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non toglie che in alcune implementazioni questa tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si è comunque soggetti alla - possibilità di una \itindex{race~condition} \textit{race condition}.} che -essa ritorni un errore quando usata con i flag di \const{O\_CREAT} e -\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può -essere eseguita atomicamente, il processo che crea il file con successo si può -considerare come titolare del lock (e della risorsa ad esso associata) mentre -il rilascio si può eseguire con una chiamata ad \func{unlink}. + possibilità di una \textit{race condition}.} che essa ritorni un errore +quando usata con i flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la +creazione di un \textsl{file di lock} può essere eseguita atomicamente, il +processo che crea il file con successo si può considerare come titolare del +lock (e della risorsa ad esso associata) mentre il rilascio si può eseguire +con una chiamata ad \func{unlink}. Un esempio dell'uso di questa funzione è mostrato dalle funzioni \func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock} @@ -3392,8 +3388,8 @@ problemi che non lo rendono una alternativa praticabile per la sincronizzazione: anzitutto in caso di terminazione imprevista del processo, si lascia allocata la risorsa (il \textsl{file di lock}) e questa deve essere sempre cancellata esplicitamente. Inoltre il controllo della disponibilità -può essere eseguito solo con una tecnica di \itindex{polling} -\textit{polling}, ed è quindi molto inefficiente. +può essere eseguito solo con una tecnica di \textit{polling}, ed è quindi +molto inefficiente. La tecnica dei file di lock ha comunque una sua utilità, e può essere usata con successo quando l'esigenza è solo quella di segnalare l'occupazione di una @@ -3402,22 +3398,21 @@ usa spesso per evitare interferenze sull'uso delle porte seriali da parte di più programmi: qualora si trovi un file di lock il programma che cerca di accedere alla seriale si limita a segnalare che la risorsa non è disponibile. -\index{file!di lock|)} +\index{file!di~lock|)} \subsection{La sincronizzazione con il \textit{file locking}} \label{sec:ipc_lock_file} -Dato che i \index{file!di lock} file di lock presentano gli inconvenienti -illustrati in precedenza, la tecnica alternativa di sincronizzazione più -comune è quella di fare ricorso al \itindex{file~locking} \textit{file - locking} (trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un -file creato per l'occasione per ottenere un write lock. In questo modo potremo -usare il lock come un \textit{mutex}: per bloccare la risorsa basterà -acquisire il lock, per sbloccarla basterà rilasciare il lock. Una richiesta -fatta con un write lock metterà automaticamente il processo in stato di -attesa, senza necessità di ricorrere al \itindex{polling} \textit{polling} per -determinare la disponibilità della risorsa, e al rilascio della stessa da +Dato che i file di lock presentano gli inconvenienti illustrati in precedenza, +la tecnica alternativa di sincronizzazione più comune è quella di fare ricorso +al \textit{file locking} (trattato in sez.~\ref{sec:file_locking}) usando +\func{fcntl} su un file creato per l'occasione per ottenere un write lock. In +questo modo potremo usare il lock come un \textit{mutex}: per bloccare la +risorsa basterà acquisire il lock, per sbloccarla basterà rilasciare il +lock. Una richiesta fatta con un write lock metterà automaticamente il +processo in stato di attesa, senza necessità di ricorrere al \textit{polling} +per determinare la disponibilità della risorsa, e al rilascio della stessa da parte del processo che la occupava si otterrà il nuovo lock atomicamente. Questo approccio presenta il notevole vantaggio che alla terminazione di un @@ -3433,17 +3428,16 @@ leggermente più lento. \includecodesample{listati/MutexLocking.c} \end{minipage} \normalsize - \caption{Il codice delle funzioni che permettono per la gestione dei - \textit{mutex} con il \itindex{file~locking} \textit{file locking}.} + \caption{Il codice delle funzioni che permettono per la gestione dei + \textit{mutex} con il \textit{file locking}.} \label{fig:ipc_flock_mutex} \end{figure} Il codice delle varie funzioni usate per implementare un mutex utilizzando il -\textit{file locking} \itindex{file~locking} è riportato in -fig.~\ref{fig:ipc_flock_mutex}; si è mantenuta volutamente una struttura -analoga alle precedenti funzioni che usano i semafori, anche se le due -interfacce non possono essere completamente equivalenti, specie per quanto -riguarda la rimozione del mutex. +\textit{file locking} è riportato in fig.~\ref{fig:ipc_flock_mutex}; si è +mantenuta volutamente una struttura analoga alle precedenti funzioni che usano +i semafori, anche se le due interfacce non possono essere completamente +equivalenti, specie per quanto riguarda la rimozione del mutex. La prima funzione (\texttt{\small 1-5}) è \func{CreateMutex}, e serve a creare il mutex; la funzione è estremamente semplice, e si limita @@ -3456,9 +3450,9 @@ mutex. La seconda funzione (\texttt{\small 6-10}) è \func{FindMutex}, che, come la precedente, è stata definita per mantenere una analogia con la corrispondente funzione basata sui semafori. Anch'essa si limita (\texttt{\small 9}) ad -aprire il file da usare per il \itindex{file~locking} \textit{file locking}, -solo che in questo caso le opzioni di \func{open} sono tali che il file in -questione deve esistere di già. +aprire il file da usare per il \textit{file locking}, solo che in questo caso +le opzioni di \func{open} sono tali che il file in questione deve esistere di +già. La terza funzione (\texttt{\small 11-22}) è \func{LockMutex} e serve per acquisire il mutex. La funzione definisce (\texttt{\small 14}) e inizializza @@ -3473,10 +3467,9 @@ La quarta funzione (\texttt{\small 24-34}) è \func{UnlockMutex} e serve a rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo caso si inizializza (\texttt{\small 28-31}) la struttura \var{lock} per il rilascio del lock, che viene effettuato (\texttt{\small 33}) con la opportuna -chiamata a \func{fcntl}. Avendo usato il \itindex{file~locking} \textit{file - locking} in semantica POSIX (si riveda quanto detto -sez.~\ref{sec:file_posix_lock}) solo il processo che ha precedentemente -eseguito il lock può sbloccare il mutex. +chiamata a \func{fcntl}. Avendo usato il \textit{file locking} in semantica +POSIX (si riveda quanto detto sez.~\ref{sec:file_posix_lock}) solo il processo +che ha precedentemente eseguito il lock può sbloccare il mutex. La quinta funzione (\texttt{\small 36-39}) è \func{RemoveMutex} e serve a cancellare il mutex. Anche questa funzione è stata definita per mantenere una @@ -3514,11 +3507,13 @@ nessun inconveniente. \subsection{Il \textit{memory mapping} anonimo} \label{sec:ipc_mmap_anonymous} -\itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono -\textsl{correlati}, se cioè hanno almeno un progenitore comune, l'uso delle -\textit{pipe} può costituire una valida alternativa alle code di messaggi; -nella stessa situazione si può evitare l'uso di una memoria condivisa facendo -ricorso al cosiddetto \textit{memory mapping} anonimo. +\itindbeg{memory~mapping} + +Abbiamo già visto che quando i processi sono \textsl{correlati}, se cioè hanno +almeno un progenitore comune, l'uso delle \textit{pipe} può costituire una +valida alternativa alle code di messaggi; nella stessa situazione si può +evitare l'uso di una memoria condivisa facendo ricorso al cosiddetto +\textit{memory mapping} anonimo. In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il contenuto di un file nella memoria di un processo, e che, quando viene usato @@ -3544,6 +3539,7 @@ il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica più avanti, quando realizzeremo una nuova versione del monitor visto in sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. + \itindend{memory~mapping} % TODO: fare esempio di mmap anonima @@ -3556,6 +3552,8 @@ sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. % TODO: con il kernel 3.17 è stata introdotta una fuunzionalità di % sigillatura dei file mappati in memoria e la system call memfd % (capire se va messo qui o altrove) vedi: http://lwn.net/Articles/593918/ +% col 5.1 aggiunta a memfd F_SEAL_FUTURE_WRITE, vedi +% https://git.kernel.org/linus/ab3948f58ff8 e https://lwn.net/Articles/782511/ \section{L'intercomunicazione fra processi di POSIX} @@ -3574,9 +3572,8 @@ una interfaccia completamente nuova, che tratteremo in questa sezione. Oggi Linux supporta tutti gli oggetti definito nello standard POSIX per l'IPC, ma a lungo non è stato così; la memoria condivisa è presente a partire dal kernel 2.4.x, i semafori sono forniti dalla \acr{glibc} nella sezione che -implementa i \itindex{thread} \textit{thread} POSIX di nuova generazione che -richiedono il kernel 2.6, le code di messaggi sono supportate a partire dal -kernel 2.6.6. +implementa i \textit{thread} POSIX di nuova generazione che richiedono il +kernel 2.6, le code di messaggi sono supportate a partire dal kernel 2.6.6. La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso degli identificatori e delle chiavi visti nel \textit{SysV-IPC}, per passare ai @@ -3706,7 +3703,7 @@ una coda di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è: 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}. Nel caso di Linux si tratta in effetti proprio di un normale +\typed{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 @@ -3781,34 +3778,33 @@ 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: +I suddetti limiti di sistema sono impostati attraverso una serie di file +presenti sotto \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 +\item[\sysctlfiled{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 *))}, + valore massimo è \constd{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. + precisamente con la \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 +\item[\sysctlfiled{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}). + processi con privilegi amministrativi (con la \textit{capability} + \const{CAP\_SYS\_RESOURCE}). -\item[\sysctlfile{fs/mqueue/queues\_max}] Indica il numero massimo di code di +\item[\sysctlfiled{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}). + \textit{capability} \const{CAP\_SYS\_RESOURCE}). \end{basedescript} @@ -3837,7 +3833,7 @@ descrittore con la funzione \funcd{mq\_close}, il cui prototipo è: 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 + viene rimappata su \func{close} dalla \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 @@ -3942,7 +3938,8 @@ I rispettivi prototipi sono: \fhead{time.h} \fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len, \\ -\phantom{int mq\_timedsend(}unsigned int msg\_prio, const struct timespec *abs\_timeout)} +\phantom{int mq\_timedsend(}unsigned int msg\_prio, const struct timespec +*abs\_timeout)} \fdesc{Esegue l'inserimento di un messaggio su una coda entro un tempo specificato} } @@ -3971,13 +3968,13 @@ 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, che, essendo -definito come \ctyp{unsigned int}, è sempre un intero positivo. I messaggi di +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 +priorità non può eccedere il limite di sistema \constd{MQ\_PRIO\_MAX}, che al momento è pari a 32768. Qualora la coda sia piena, entrambe le funzioni si bloccano, a meno che non @@ -4152,12 +4149,12 @@ 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 (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 -occorre per ripetere la richiesta di notifica basta avere cura di eseguire -questa operazione prima di estrarre i messaggi presenti dalla coda. +\ref{sec:sig_semantics}) questa caratteristica non configura una \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 occorre per ripetere la +richiesta di notifica basta avere cura di eseguire questa operazione prima di +estrarre i messaggi presenti dalla coda. L'invio del segnale di notifica avvalora alcuni campi di informazione restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in @@ -4198,7 +4195,7 @@ mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e \texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne la titolarità, e \texttt{nr\_blocks} che permette di specificarne la -dimensione in blocchi, cioè in multipli di \const{PAGECACHE\_SIZE} che in +dimensione in blocchi, cioè in multipli di \constd{PAGECACHE\_SIZE} che in questo caso è l'unità di allocazione elementare. La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed @@ -4267,9 +4264,9 @@ sez.~\ref{sec:file_open_close}. Inoltre sul file descriptor viene sempre impostato il flag \const{FD\_CLOEXEC}. Chiamate effettuate da diversi processi usando lo stesso nome restituiranno file descriptor associati allo stesso segmento, così come, nel caso di file ordinari, essi sono associati -allo stesso \itindex{inode} inode. In questo modo è possibile effettuare una -chiamata ad \func{mmap} sul file descriptor restituito da \func{shm\_open} ed -i processi vedranno lo stesso segmento di memoria condivisa. +allo stesso inode. In questo modo è possibile effettuare una chiamata ad +\func{mmap} sul file descriptor restituito da \func{shm\_open} ed i processi +vedranno lo stesso segmento di memoria condivisa. Quando il nome non esiste si può creare un nuovo segmento specificando \const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file) @@ -4386,15 +4383,15 @@ restituendo al chiamante il valore di ritorno. \label{sec:ipc_posix_sem} Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale -dei semafori POSIX che li realizzava solo a livello di \itindex{thread} -\textit{thread} e non di processi,\footnote{questo significava che i semafori - erano visibili solo all'interno dei \itindex{thread} \textit{thread} creati - da un singolo processo, e non potevano essere usati come meccanismo di - sincronizzazione fra processi diversi.} fornita attraverso la sezione delle -estensioni \textit{real-time} della \acr{glibc} (quelle che si accedono -collegandosi alla libreria \texttt{librt}). Esisteva inoltre una libreria che -realizzava (parzialmente) l'interfaccia POSIX usando le funzioni dei semafori -di \textit{SysV-IPC} (mantenendo così tutti i problemi sottolineati in +dei semafori POSIX che li realizzava solo a livello di \textit{thread} e non +di processi,\footnote{questo significava che i semafori erano visibili solo + all'interno dei \textit{thread} creati da un singolo processo, e non + potevano essere usati come meccanismo di sincronizzazione fra processi + diversi.} fornita attraverso la sezione delle estensioni \textit{real-time} +della \acr{glibc} (quelle che si accedono collegandosi alla libreria +\texttt{librt}). Esisteva inoltre una libreria che realizzava (parzialmente) +l'interfaccia POSIX usando le funzioni dei semafori di \textit{SysV-IPC} +(mantenendo così tutti i problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem}). A partire dal kernel 2.5.7 è stato introdotto un meccanismo di @@ -4402,9 +4399,9 @@ sincronizzazione completamente nuovo, basato sui cosiddetti \textit{futex} (la sigla sta per \textit{fast user mode mutex}) con il quale è stato possibile implementare una versione nativa dei semafori POSIX. Grazie a questo con i kernel della serie 2.6 e le nuove versioni della \acr{glibc} che usano questa -nuova infrastruttura per quella che viene che viene chiamata \textit{New Posix - Thread Library}, sono state implementate anche tutte le funzioni -dell'interfaccia dei semafori POSIX. +nuova infrastruttura per quella che viene chiamata \textit{New Posix Thread + Library}, sono state implementate anche tutte le funzioni dell'interfaccia +dei semafori POSIX. Anche in questo caso è necessario appoggiarsi alla libreria per le estensioni \textit{real-time} \texttt{librt}, questo significa che se si vuole utilizzare @@ -4428,7 +4425,7 @@ esistente o per crearne uno nuovi, i relativi prototipi sono: \fdesc{Crea un semaforo o ne apre uno esistente.} } {La funzione ritorna l'indirizzo del semaforo in caso di successo e - \const{SEM\_FAILED} per un errore, nel qual caso \var{errno} assumerà uno + \constd{SEM\_FAILED} per un errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EACCES}] il semaforo esiste ma non si hanno permessi @@ -4436,7 +4433,7 @@ esistente o per crearne uno nuovi, i relativi prototipi sono: \item[\errcode{EEXIST}] si sono specificati \const{O\_CREAT} e \const{O\_EXCL} ma il semaforo esiste. \item[\errcode{EINVAL}] il valore di \param{value} eccede - \const{SEM\_VALUE\_MAX} o il nome è solo ``\texttt{/}''. + \constd{SEM\_VALUE\_MAX} o il nome è solo ``\texttt{/}''. \item[\errcode{ENAMETOOLONG}] si è utilizzato un nome troppo lungo. \item[\errcode{ENOENT}] non si è usato \const{O\_CREAT} ed il nome specificato non esiste. @@ -4484,10 +4481,9 @@ Si tenga presente che, come accennato in sez.~\ref{sec:ipc_posix_generic}, i semafori usano la semantica standard dei file per quanto riguarda i controlli di accesso, questo significa che un nuovo semaforo viene sempre creato con l'\ids{UID} ed il \ids{GID} effettivo del processo chiamante, e che i permessi -indicati con \param{mode} vengono filtrati dal valore della \itindex{umask} -\textit{umask} del processo. Inoltre per poter aprire un semaforo è -necessario avere su di esso sia il permesso di lettura che quello di -scrittura. +indicati con \param{mode} vengono filtrati dal valore della \textit{umask} del +processo. Inoltre per poter aprire un semaforo è necessario avere su di esso +sia il permesso di lettura che quello di scrittura. La funzione restituisce in caso di successo un puntatore all'indirizzo del semaforo con un valore di tipo \ctyp{sem\_t *}, è questo valore che dovrà @@ -4532,7 +4528,7 @@ semaforo con una chiamata a \func{sem\_post}) così che poi essa possa decrementarlo con successo e proseguire. Si tenga presente che la funzione può sempre essere interrotta da un segnale, -nel qual caso si avrà un errore di \const{EINTR}; inoltre questo avverrà +nel qual caso si avrà un errore di \errval{EINTR}; inoltre questo avverrà comunque, anche qualora si fosse richiesta la gestione con la semantica BSD, installando il gestore del suddetto segnale con l'opzione \const{SA\_RESTART} (vedi sez.~\ref{sec:sig_sigaction}) per riavviare le \textit{system call} @@ -4571,7 +4567,7 @@ La seconda variante di \func{sem\_wait} è una estensione specifica che può essere utilizzata soltanto se viene definita la macro \macro{\_XOPEN\_SOURCE} ad un valore di almeno 600 o la macro \macro{\_POSIX\_C\_SOURCE} ad un valore uguale o maggiore di \texttt{200112L} prima di includere -\headfile{semaphore.h}, la funzione è \funcd{sem\_timedwait}, ed il suo +\headfiled{semaphore.h}, la funzione è \funcd{sem\_timedwait}, ed il suo prototipo è: \begin{funcproto}{ @@ -4628,11 +4624,11 @@ prototipo è: La funzione incrementa di uno il valore corrente del semaforo indicato dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà -sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread}) -eventualmente bloccato in una \func{sem\_wait} sul semaforo possa essere -svegliato e rimesso in esecuzione. Si tenga presente che la funzione è sicura -\index{funzioni!sicure} per l'uso all'interno di un gestore di segnali (si -ricordi quanto detto in sez.~\ref{sec:sig_signal_handler}). +sbloccata, cosicché un altro processo (o \textit{thread}) eventualmente +bloccato in una \func{sem\_wait} sul semaforo possa essere svegliato e rimesso +in esecuzione. Si tenga presente che la funzione è sicura per l'uso +all'interno di un gestore di segnali (si ricordi quanto detto in +sez.~\ref{sec:sig_signal_handler}). Se invece di operare su un semaforo se ne volesse semplicemente leggere il valore, si potrà usare la funzione \funcd{sem\_getvalue}, il cui prototipo è: @@ -4762,16 +4758,15 @@ prototipo è: La funzione inizializza un semaforo all'indirizzo puntato dall'argomento \param{sem}, e come per \func{sem\_open} consente di impostare un valore iniziale con \param{value}. L'argomento \param{pshared} serve ad indicare se -il semaforo deve essere utilizzato dai \itindex{thread} \textit{thread} di uno -stesso processo (con un valore nullo) o condiviso fra processi diversi (con un -valore non nullo). +il semaforo deve essere utilizzato dai \textit{thread} di uno stesso processo +(con un valore nullo) o condiviso fra processi diversi (con un valore non +nullo). -Qualora il semaforo debba essere condiviso dai \itindex{thread} -\textit{thread} di uno stesso processo (nel qual caso si parla di -\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 \index{variabili!globali} variabile globale o una -variabile allocata dinamicamente nello \itindex{heap} \textit{heap}. +Qualora il semaforo debba essere condiviso dai \textit{thread} di uno stesso +processo (nel qual caso si parla di \textit{thread-shared semaphore}), +occorrerà che \param{sem} sia l'indirizzo di una variabile visibile da tutti i +\textit{thread}, si dovrà usare cioè una variabile globale o una variabile +allocata dinamicamente nello \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 @@ -4811,9 +4806,8 @@ La funzione prende come unico argomento l'indirizzo di un semaforo che deve essere stato inizializzato con \func{sem\_init}; non deve quindi essere applicata a semafori creati con \func{sem\_open}. Inoltre si deve essere sicuri che il semaforo sia effettivamente inutilizzato, la distruzione di un -semaforo su cui sono presenti processi (o \itindex{thread} \textit{thread}) in -attesa (cioè bloccati in una \func{sem\_wait}) provoca un comportamento -indefinito. +semaforo su cui sono presenti processi (o \textit{thread}) in attesa (cioè +bloccati in una \func{sem\_wait}) provoca un comportamento indefinito. Si tenga presente infine che utilizzare un semaforo che è stato distrutto con \func{sem\_destroy} di nuovo può dare esito a comportamenti indefiniti. Nel @@ -4852,9 +4846,9 @@ dall'altro programma prima di averla finita di stampare. La parte iniziale del programma contiene le definizioni (\texttt{\small 1-8}) del gestore del segnale usato per liberare le risorse utilizzate, delle -\index{variabili!globali} variabili globali contenenti i nomi di default del -segmento di memoria condivisa e del semaforo (il default scelto è -\texttt{messages}), e delle altre variabili utilizzate dal programma. +variabili globali contenenti i nomi di default del segmento di memoria +condivisa e del semaforo (il default scelto è \texttt{messages}), e delle +altre variabili utilizzate dal programma. Come prima istruzione (\texttt{\small 10}) si è provveduto ad installare un gestore di segnale che consentirà di effettuare le operazioni di pulizia @@ -4883,12 +4877,12 @@ notazione ottale). Infine il semaforo verrà inizializzato ad un valore nullo A questo punto (\texttt{\small 22}) si potrà inizializzare il messaggio posto nel segmento di memoria condivisa usando la stringa passata come argomento al programma. Essendo il semaforo stato creato già bloccato non ci si dovrà -preoccupare di eventuali \itindex{race~condition} \textit{race condition} -qualora il programma di modifica del messaggio venisse lanciato proprio in -questo momento. Una volta inizializzato il messaggio occorrerà però -rilasciare il semaforo (\texttt{\small 24-27}) per consentirne l'uso; in -tutte queste operazioni si provvederà ad uscire dal programma con un opportuno -messaggio in caso di errore. +preoccupare di eventuali \textit{race condition} qualora il programma di +modifica del messaggio venisse lanciato proprio in questo momento. Una volta +inizializzato il messaggio occorrerà però rilasciare il semaforo +(\texttt{\small 24-27}) per consentirne l'uso; in tutte queste operazioni si +provvederà ad uscire dal programma con un opportuno messaggio in caso di +errore. Una volta completate le inizializzazioni il ciclo principale del programma (\texttt{\small 29-47}) viene ripetuto indefinitamente (\texttt{\small 29}) @@ -4959,8 +4953,8 @@ argomento. Una volta completate con successo le precedenti inizializzazioni, il passo seguente (\texttt{\small 21-24}) è quello di acquisire il semaforo, dopo di che sarà possibile eseguire la sostituzione del messaggio (\texttt{\small 25}) -senza incorrere in possibili \itindex{race~condition} \textit{race condition} -con la stampa dello stesso da parte di \file{message\_getter}. +senza incorrere in possibili \textit{race condition} con la stampa dello +stesso da parte di \file{message\_getter}. Una volta effettuata la modifica viene stampato (\texttt{\small 26}) il tempo di attesa impostato con l'opzione ``\texttt{-t}'' dopo di che (\texttt{\small @@ -4969,11 +4963,11 @@ quindi bloccato (causando a questo punto una interruzione delle stampe eseguite da \file{message\_getter}). Terminato il tempo di attesa si rilascerà (\texttt{\small 29-32}) il semaforo per poi uscire. -Per verificare il funzionamento dei programmi occorrerà lanciare per primo -\file{message\_getter}\footnote{lanciare per primo \file{message\_setter} darà - luogo ad un errore, non essendo stati creati il semaforo ed il segmento di - memoria condivisa.} che inizierà a stampare una volta al secondo il -contenuto del messaggio ed i suoi dati, con qualcosa del tipo: +Per verificare il funzionamento dei programmi occorrerà lanciare prima +\file{message\_getter} (lanciare per primo \file{message\_setter} darebbe +luogo ad un errore, non essendo stati creati il semaforo ed il segmento di +memoria condivisa) che inizierà a stampare una volta al secondo il contenuto +del messaggio ed i suoi dati, con qualcosa del tipo: \begin{Console} piccardi@hain:~/gapil/sources$ \textbf{./message_getter messaggio} sem=1, Fri Dec 31 14:12:41 2010 @@ -4996,10 +4990,8 @@ Sleeping for 3 seconds \end{Console} %$ dove il programma si fermerà per 3 secondi prima di rilasciare il semaforo e -terminare. - -L'effetto di questo programma si potrà però apprezzare meglio nell'uscita di -\file{message\_getter}, che verrà interrotta per questo stesso tempo, prima di +terminare. L'effetto di tutto ciò si potrà vedere nell'\textit{output} di +\file{message\_getter}, che verrà interrotto per questo stesso tempo, prima di ricominciare con il nuovo testo: \begin{Console} ... @@ -5017,10 +5009,10 @@ message: ciao \end{Console} %$ -E si noterà come nel momento in cui si è lanciato \file{message\_setter} le -stampe di \file{message\_getter} si bloccheranno, come corretto, dopo aver -registrato un valore nullo per il semaforo. Il programma infatti resterà -bloccato nella \func{sem\_wait} (quella di riga (\texttt{\small 37}) in +E si noterà come nel momento in cui si lancia \file{message\_setter} le stampe +di \file{message\_getter} si bloccheranno, come corretto, dopo aver registrato +un valore nullo per il semaforo. Il programma infatti resterà bloccato nella +\func{sem\_wait} (quella di riga (\texttt{\small 37}) in fig.~\ref{fig:ipc_posix_sem_shm_message_server}) fino alla scadenza dell'attesa di \file{message\_setter} (con l'esecuzione della \func{sem\_post} della riga (\texttt{\small 29}) di @@ -5087,10 +5079,10 @@ testo alla terminazione di quest'ultimo. % LocalWords: SysV capability short RESOURCE INFO UNDEFINED EFBIG semtimedop % LocalWords: scan HUGETLB huge page NORESERVE copy RLIMIT MEMLOCK REMAP UTC % LocalWords: readmon Hierarchy defaults queues MSGQUEUE effective fstat +% LocalWords: fchown fchmod Epoch January %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: -% LocalWords: fchown fchmod Epoch January