\label{sec:ipc_sysv_shm}
Il terzo oggetto introdotto dal \textit{System V IPC} è quello dei segmenti di
-memoria condivisa. La funzione che permette di ottenerne uno è \func{shmget}
+memoria condivisa. La funzione che permette di ottenerne uno è \func{shmget},
ed il suo prototipo è:
\begin{functions}
\headdecl{sys/types.h}
\param{size} specifica invece la dimensione, in byte, del segmento, che viene
comunque arrotondata al multiplo superiore di \macro{PAGE\_SIZE}.
+La memoria condivisa è la forma più veloce di comunicazione fra due processi,
+in quanto permette agli stessi di vedere nel loro spazio di indirizzi una
+stessa sezione di memoria. Pertanto non è necessaria nessuna operazione di
+copia per trasmettere i dati da un processo all'altro, in quanto ciascuno può
+accedervi direttamente con le normali operazioni di lettura e scrittura dei
+dati in memoria.
+
+Ovviamente tutto questo ha un prezzo, ed il problema fondamentale della
+memoria condivisa è la sincronizzazione degli accessi. È evidente infatti che
+se un processo deve scambiare dei dati con un altro, si deve essere sicuri che
+quest'ultimo non acceda al segmento di memoria condivisa prima che il primo
+non abbia completato le operazioni di scrittura, inoltre nel corso di una
+lettura si deve essere sicuri che i dati restano coerenti e non vengono
+sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
+altro processo; per questo in genere la memoria condivisa viene sempre
+utilizzata in abbinamento ad un meccanismo di sincronizzazione, il che, di
+norma, significa insime a dei semafori.
+
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
al segmento viene inizializzato a zero.
\end{itemize*}
+La struttura di come vengono gestiti i segmenti di memoria condivisa nel
+kernel è illustrata in .
+
+
+
+
Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
di memoria condivisa esistono una serie di limiti, i cui valori, riportati in
\tabref{tab:ipc_shm_limits} sono associati ad altrettante costanti. Alcuni di
\begin{errlist}
\item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma i permessi non
consentono l'accesso in lettura al segmento.
- \item[\macro{EINVAL}] .
- \item[\macro{ENOMEM}] .
- \end{errlist}.}
+ \item[\macro{EINVAL}] O \param{shmid} o \param{cmd} hanno valori non
+ validi.
+ \item[\macro{EIDRM}] L'argomento \param{shmid} fa riferimento ad un
+ segmento che è stato cancellato.
+ \item[\macro{EPERM}] Si è specificato un comando con \macro{IPC\_SET} o
+ \macro{IPC\_RMID} senza i permessi necessari.
+ \item[\macro{EOVERFLOW}] L'argomento \param{shmid} fa riferimento ad un
+ segmento che è stato cancellato.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}.}
\end{functions}
-Per utilizzare i segmenti di memoria condivisa si usano due funzioni,
-\func{shmat} e \func{shmdt}, che consentono di agganciarli e sganciarli da un
-processo, così che questo possa vederli nel suo spazio di indirizzi; i loro
-prototipi sono:
+Il comportamento della funzione dipende dal valore del comando passato
+attraverso l'argomento \param{cmd}, i valori possibili sono i seguenti:
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge le informazioni riguardo il segmento di memoria
+ condivisa nella struttura \var{shmid\_ds} puntata da \param{buf}. Occorre
+ avere il permesso di lettura sulla coda.
+\item[\macro{IPC\_RMID}] Marca il segmento di memoria condivisa per la
+ rimozione, questo verrà cancellato effettivamente solo quando l'ultimo
+ processo ad esso agganciato si sarà staccato. Questo comando può essere
+ eseguito solo da un processo con userid effettivo, corrispondente al
+ creatore o al proprietario della coda, o all'amministratore.
+\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+ del segmento. Per modificare i valori di \var{shm\_perm.mode},
+ \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
+ il creatore della coda, oppure l'amministratore. Compiuta l'operazione
+ aggiorna anche il valore del campo \var{shm\_ctime}.
+\item[\macro{SHM\_LOCK}] Abilita il \textit{memory locking}\index{memory
+ locking} (vedi \secref{sec:proc_mem_lock}) sul segmento di memoria
+ condivisa. Solo l'amministratore può utilizzare questo comando.
+\item[\macro{SHM\_UNLOCK}] Disabilita il \textit{memory locking}. Solo
+ l'amministratore può utilizzare questo comando.
+\end{basedescript}
+i primi tre comandi sono gli stessi già visti anche per le code ed i semafori,
+gli ultimi due sono delle estensioni previste solo in Linux.
+
+Per utilizzare i segmenti di memoria condivisa si usano due funzioni, la prima
+di queste è \func{shmat}, che serve ad agganciare un segmento al processo
+chiamante, in modo che quest'ultimo possa vederlo nel suo spazio di indirizzi;
+il suo prototipo è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/shm.h}
\funcdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)}
Aggancia al processo un segmento di memoria condivisa.
+
+ \bodydesc{La funzione restituisce l'indirizzo del segmento in caso di
+ successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà i
+ valori:
+ \begin{errlist}
+ \item[\macro{EACCES}] Il processo non ha i privilegi per accedere al
+ segmento nella modalità richiesta.
+ \item[\macro{EINVAL}] Si è specificato un identificatore invalido per
+ \param{shmid}, o un indirizzo non allineato sul confine di una pagina
+ per \param{shmaddr}.
+ \item[\macro{EIDRM}] Si è richiesto un segmento marcato per la
+ cancellazione.
+ \end{errlist}
+ ed inoltre \macro{ENOMEM}.}
+\end{functions}
+
+La funzione inserisce un segmento di memoria condivisa all'interno dello
+spazio di indirizzi del processo, in modo che questo possa accedervi
+direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
+\figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
+ricordi al proposito quanto illustrato in \secref{sec:proc_mem_layout}).
+
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[height=10cm]{img/sh_memory_layout}
+ \caption{Disposizione dei segmenti di memoria di un processo quando si è
+ agganciato un segmento di memoria condivisa.}
+ \label{fig:ipc_shmem_layout}
+\end{figure}
+
+
+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 alle \acr{glibc} il tipo di
+ \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di
+ ritorno un \ctyp{void *}.} deve essere associato il segmento, se il valore
+specificato è \macro{NULL} è il sistema a scegliere opportunamente un'area di
+memoria libera (questo è il modo più portabile e sicuro di usare la funzione).
+Altrimenti il kernel aggangia il segmento all'indirizzo specificato da
+\param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il
+limite di una pagina, cioè se è un multiplo esatto del parametro di sistema
+\macro{SHMLBA}, che in Linux è sempre uguale \macro{PAGE\_SIZE}.
+
+
+
+
+L'argomento \param{shmflg} permette di cambiare il comportamento della
+funzione; esso va specificato come maschera binaria, i bit utilizzati sono
+
+
+
+
+La seconda funzione è \func{shmdt}, che consente di sganciare un segmento di
+memoria condivisa dal processo chiamante quando questo non è più necessario,
+il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/shm.h}
\funcdecl{int shmdt(const void *shmaddr)}
Sgancia dal processo un segmento di memoria condivisa.
- \bodydesc{Le funzioni restituiscono rispettivamente l'indirizzo del segmento
- e 0 in caso di successo, mentre entrambe restituiscono -1 in caso di
- errore, nel qual caso \var{errno} assumerà i valori:
- \begin{errlist}
- \item[\macro{EACCES}] Il processo non ha i provilegi di accesso.
- \item[\macro{EINVAL}] .
- \item[\macro{EPERM}] Si è è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID}
- senza avere i permessi del creatore o del proprietario del segmento (o
- quelli dell'amministratore).
- \item[\macro{EOVERFLOW}] Si è richiesto \macro{IPC\_STAT} ma alcuni valori
- sono troppo grandi per essere memorizzati nella struttura puntata da
- \param{buf}.
- \end{errlist}
- ed inoltre \macro{EFAULT} e \macro{EIDRM}.}
+ \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+ errore, la funzione fallisce solo quando non c'è un segmento agganciato
+ all'indirizzo \func{shmaddr}, con \var{errno} che assume il valore
+ \macro{EINVAL}.}
\end{functions}
+\section{Tecniche alternative}
+\label{sec:ipc_alternatives}
+
+Come abbiamo visto in \secref{sec:ipc_sysv_generic} il sistema di IPC di
+System V presenta numerosi problemi; in \cite{APUE}\footnote{nel capitolo 14.}
+Stevens effettua una accurata analisi (i cui concetti sono già stati accennati
+in precedenza) ed elenca alcune possibili alternative, che vogliamo riprendere
+in questa sezione.
+
+
+\subsection{La sincronizzazione con il \textit{file locking}}
+\label{sec:ipc_file_lock}
+
+Abbiamo esaminato il \textit{file locking} in \secref{sec:file_locking},
+
+
+
+\subsection{Il \textit{memory mapping} anonimo}
+\label{sec:ipc_mmap_anonymous}
+Abbiamo visto in \secref{sec:file_memory_map} come sia possibile
\section{La comunicazione fra processi di POSIX}