X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=d8ffa5f83268604dfaa2149b95c72f096f44a664;hp=b0eb27ee76a651086eae29ee98b0fc9cc9efe8dc;hb=fe017ba5da165123761dbb85036ad3ed8bbd7ad2;hpb=7b52687f914b7a496df8fe2e7ac834b5cad2e59e diff --git a/ipc.tex b/ipc.tex index b0eb27e..d8ffa5f 100644 --- a/ipc.tex +++ b/ipc.tex @@ -2524,12 +2524,6 @@ invece: 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 @@ -2613,12 +2607,12 @@ attraverso l'argomento \param{cmd}, i valori possibili sono i seguenti: 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. +gli ultimi due sono delle estensioni previste da 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 è: +Per utilizzare i segmenti di memoria condivisa l'interfaccia prevede due +funzioni, la prima è \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} @@ -2635,8 +2629,6 @@ il suo prototipo \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} @@ -2645,8 +2637,9 @@ 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}). - +ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). Si +tenga presente che la funzione ha successo anche se il segmento è stato +marcato per la cancellazione. \begin{figure}[htb] \centering @@ -2656,7 +2649,6 @@ ricordi al proposito quanto illustrato in \secref{sec:proc_mem_layout}). \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 @@ -2665,23 +2657,54 @@ L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{Lo standard 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 +Altrimenti il kernel aggancia 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 è: +solo due e sono identificati dalle costanti \macro{SHM\_RND} e +\macro{SHM\_RDONLY}, che vanno combinate con un OR aritmetico. Specificando +\macro{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 \macro{SHMLBA} (il nome della +costante sta infatti per \textit{rounded}, e serve per specificare un +indirizzo come arrotondamento). + +Il secondo bit 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 violazione di accesso con l'emissione +di un segnale di \macro{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. + +In caso di successo la funzione aggiorna anche i seguenti campi di +\var{shmid\_ds}: +\begin{itemize*} +\item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene + impostato al tempo corrente. +\item il \acr{pid} \var{shm\_lpid} dell'ultimo processo che ha operato sul + segmento viene impostato a quello del processo corrente. +\item il numero \var{shm\_nattch} di processi agganciati al segmento viene + aumentato di uno. +\end{itemize*} + +Come accennato in \secref{sec:proc_fork} un segmento di memoria condivisa +agganciato ad un precesso viene ereditato da un figlio attraverso una +\func{fork}, dato che quest'ultimo riceve una copia dello spazio degli +indirizzi del padre. Invece, dato che attraverso una \func{exec} viene +eseguito un diverso programma con uno spazio di indirizzi completamente +diverso, tutti i segmenti agganciati al processo originario vengono +automaticamente sganciati. Lo stesso avviene all'uscita del processo +attraverso una \func{exit}. + + +Una volta che un segmento di memoria condivisa non serve più si può sganciarlo +esplicitamente dal processo usando la seconda funzione dell'interfaccia, +\func{shmdt}, il cui il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/shm.h} @@ -2689,27 +2712,69 @@ il suo prototipo \funcdecl{int shmdt(const void *shmaddr)} Sgancia dal processo un segmento di memoria condivisa. - \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di succes so, 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} +La funzione sgancia dallo spazio degli indirizzi del processo un segmento di +memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr} +restituito dalla precedente chiamata a \func{shmat} con il quale era stato +agganciato al processo. + + +Per capire meglio il funzionamento delle funzioni facciamo ancora una volta +riferimento alle strutture con cui il kernel implementa i segmenti di memoria +condivisa; uno schema semplificato della struttura è illustrato in +\figref{fig:ipc_shm_struct}. + +\begin{figure}[htb] + \centering + \includegraphics[width=10cm]{img/shmstruct} + \caption{Schema dell'implementazione dei segmenti di memoria condivisa in + Linux.} + \label{fig:ipc_shm_struct} +\end{figure} + + + \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. +System V presenta numerosi problemi; in \cite{APUE}\footnote{in particolare + nel capitolo 14.} Stevens effettua una accurata analisi (alcuni dei +concetti sono già stati accennati in precedenza) ed elenca alcune possibili +alternative, che vogliamo riprendere in questa sezione. + + +\subsection{Alternative alle code di messaggi} +\label{sec:ipc_mq_alternative} + +Le code di messaggi sono probabilmente il meno usato degli oggetti di IPC di +System V; esse infatti nacquero principalmente come meccanismo di +comunicazione bidirezionale quando ancora le pipe erano ancora unidirezionali; +abbiamo visto però in \secref{sec:ipc_socketpair} che la funzione +\func{socketpair} permette di fare la stessa cosa senza incorrere nelle +complicazioni introdotte dal sistema di IPC di System V. + +In realtà, grazie alla presenza del campo \var{mtype}, le code di messaggi +hanno delle caratteristiche ulteriori, consentendo una classificazione dei +messaggi ed un accesso non rigidamente sequenziale, due cose che sono +impossibili da ottenere con le pipe e i socket di \func{socketpair}. + +È però possibile implementare un meccanismo analogo attraverso l'uso di +memoria condivisa e di meccanismi di sincronizzazione, (un esempio di +reimplementazione di code di messaggi usando il \textit{memory mapping} e i +semafori si trova in \cite{UNP2}). pertanto non è \subsection{La sincronizzazione con il \textit{file locking}} \label{sec:ipc_file_lock} -Abbiamo esaminato il \textit{file locking} in \secref{sec:file_locking}, +Abbiamo esaminato il \textit{file locking} in \secref{sec:file_locking},