X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=e17fe6decb0dac0bffd05c22f8e2effcbb1dbda4;hp=12cd3c0e07d99308eec8612c0d2e00f02892f045;hb=47a00595786c34a03266f19dd5163a45da63e29f;hpb=419951b29856965957fe4cacfb61de49e140bb9b diff --git a/ipc.tex b/ipc.tex index 12cd3c0..e17fe6d 100644 --- a/ipc.tex +++ b/ipc.tex @@ -66,8 +66,9 @@ La funzione restituisce la coppia di file descriptor nel vettore accennato concetto di funzionamento di una pipe è semplice: quello che si scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale nel file descriptor aperto in lettura. I file descriptor infatti non sono -connessi a nessun file reale, ma ad un buffer nel kernel, la cui dimensione è -specificata dal parametro di sistema \const{PIPE\_BUF}, (vedi +connessi a nessun file reale, ma, come accennato in +sez.~\ref{sec:file_sendfile_splice}, ad un buffer nel kernel, la cui +dimensione è specificata dal parametro di sistema \const{PIPE\_BUF}, (vedi sez.~\ref{sec:sys_file_limits}). Lo schema di funzionamento di una pipe è illustrato in fig.~\ref{fig:ipc_pipe_singular}, in cui sono illustrati i due capi della pipe, associati a ciascun file descriptor, con le frecce che @@ -133,7 +134,7 @@ Per capire meglio il funzionamento delle pipe faremo un esempio di quello che è il loro uso più comune, analogo a quello effettuato della shell, e che consiste nell'inviare l'output di un processo (lo standard output) sull'input di un altro. Realizzeremo il programma di esempio nella forma di un -\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un +\textit{CGI}\footnote{un CGI (\textit{Common Gateway Interface}) è un programma che permette la creazione dinamica di un oggetto da inserire all'interno di una pagina HTML.} per Apache, che genera una immagine JPEG di un codice a barre, specificato come argomento in ingresso. @@ -568,7 +569,7 @@ ricevuta la risposta, uscir A questo punto il server resta (se non ci sono altri client che stanno effettuando richieste) con la fifo chiusa sul lato in lettura, ed in questo stato la funzione \func{read} non si bloccherà in attesa di input, ma -ritornerà in continuazione, restituendo un end-of-file.\footnote{Si è usata +ritornerà in continuazione, restituendo un end-of-file.\footnote{si è usata questa tecnica per compatibilità, Linux infatti supporta l'apertura delle fifo in lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura con \const{O\_RDWR}, la doppia apertura comunque ha il vantaggio @@ -1017,8 +1018,9 @@ Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino altri limiti relativi al \textit{SysV IPC}) solo con una ricompilazione del kernel, andando a modificarne la definizione nei relativi header file. A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo - scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di - \file{/proc/sys/kernel} o con l'uso di \func{sysctl}.} e per ciascuno di + scrivendo sui file \procrelfile{/proc/sys/kernel}{shmmni}, + \procrelfile{/proc/sys/kernel}{msgmni} e \procrelfile{/proc/sys/kernel}{sem} + di \file{/proc/sys/kernel} o con l'uso di \func{sysctl}.} e per ciascuno di essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene incrementato di uno ogni volta che l'oggetto viene cancellato. Quando l'oggetto viene creato usando uno spazio che era già stato utilizzato in @@ -1160,7 +1162,7 @@ coda. \hline \hline \const{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di - messaggi. \\ + messaggi.\\ \const{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo messaggio.\\ \const{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di @@ -1175,7 +1177,9 @@ Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti negli header e corrispondenti alle prime tre costanti riportate in tab.~\ref{tab:ipc_msg_limits}, come accennato però in Linux è possibile modificare questi limiti attraverso l'uso di \func{sysctl} o scrivendo nei -file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}. +file \procrelfile{/proc/sys/kernel}{msgmax}, +\procrelfile{/proc/sys/kernel}{msgmnb} e +\procrelfile{/proc/sys/kernel}{msgmni} di \file{/proc/sys/kernel/}. \begin{figure}[htb] @@ -1860,16 +1864,16 @@ indicano rispettivamente: \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{SEMMNI}& 128 & Numero massimo di insiemi di semafori. \\ + \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 .\\ + 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 + \const{SEMAEM}&\const{SEMVMX}& Valore massimo per l'aggiustamento all'uscita. \\ \hline \end{tabular} @@ -1882,7 +1886,7 @@ Come per le code di messaggi anche per gli insiemi di semafori esistono una serie di limiti, i cui valori sono associati ad altrettante costanti, che si sono riportate in tab.~\ref{tab:ipc_sem_limits}. Alcuni di questi limiti sono al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo -direttamente nel file \file{/proc/sys/kernel/sem}. +direttamente nel file \procfile{/proc/sys/kernel/sem}. La funzione che permette di effettuare le varie operazioni di controllo sui semafori (fra le quali, come accennato, è impropriamente compresa anche la @@ -2008,10 +2012,10 @@ tutti i semafori il cui valore viene modificato. \textbf{Operazione} & \textbf{Valore restituito} \\ \hline \hline - \const{GETNCNT}& valore di \var{semncnt}.\\ - \const{GETPID} & valore di \var{sempid}.\\ - \const{GETVAL} & valore di \var{semval}.\\ - \const{GETZCNT}& valore di \var{semzcnt}.\\ + \const{GETNCNT}& Valore di \var{semncnt}.\\ + \const{GETPID} & Valore di \var{sempid}.\\ + \const{GETVAL} & Valore di \var{semval}.\\ + \const{GETZCNT}& Valore di \var{semzcnt}.\\ \hline \end{tabular} \caption{Valori di ritorno della funzione \func{semctl}.} @@ -2428,23 +2432,25 @@ che permettono di cambiarne il valore. & \textbf{Significato} \\ \hline \hline - \const{SHMALL}& 0x200000&\file{shmall}& Numero massimo di pagine che - possono essere usate per i segmenti di - memoria condivisa. \\ - \const{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento - di memoria condivisa.\\ - \const{SHMMNI}& 4096&\file{msgmni}& Numero massimo di segmenti di - memoria condivisa presenti nel - kernel.\\ + \const{SHMALL}& 0x200000&\procrelfile{/proc/sys/kernel}{shmall} + & Numero massimo di pagine che + possono essere usate per i segmenti di + memoria condivisa.\\ + \const{SHMMAX}&0x2000000&\procrelfile{/proc/sys/kernel}{shmmax} + & Dimensione massima di un segmento di memoria + condivisa.\\ + \const{SHMMNI}& 4096&\procrelfile{/proc/sys/kernel}{msgmni} + & Numero massimo di segmenti di memoria condivisa + presenti nel kernel.\\ \const{SHMMIN}& 1& --- & Dimensione minima di un segmento di - memoria condivisa. \\ + 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). \\ + pagina di memoria).\\ \const{SHMSEG}& --- & --- & Numero massimo di segmenti di - memoria condivisa - per ciascun processo.\\ + memoria condivisa per ciascun + processo.\\ \hline @@ -2470,7 +2476,7 @@ un segmento di memoria condivisa \begin{errlist} \item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma i permessi non consentono l'accesso in lettura al segmento. - \item[\errcode{EINVAL}] O \param{shmid} non è un identificatore valido o + \item[\errcode{EINVAL}] o \param{shmid} non è un identificatore valido o \param{cmd} non è un comando valido. \item[\errcode{EIDRM}] l'argomento \param{shmid} fa riferimento ad un segmento che è stato cancellato. @@ -2567,9 +2573,9 @@ stato marcato per la cancellazione. \label{fig:ipc_shmem_layout} \end{figure} -L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{Lo standard +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 + 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 @@ -3234,6 +3240,7 @@ pi sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. \itindend{memory~mapping} +% TODO fare esempio di mmap anonima \section{Il sistema di comunicazione fra processi di POSIX} \label{sec:ipc_posix} @@ -3315,7 +3322,7 @@ Le code di messaggi POSIX sono supportate da Linux a partire dalla versione 2.6.6-rc1 del kernel,\footnote{l'implementazione è dovuta a Michal Wronski e Krzysztof Benedyczak, e le relative informazioni si possono trovare su \href{http://www.geocities.com/wronski12/posix_ipc/index.html} - {\texttt{http://www.geocities.com/wronski12/posix\_ipc/index.html}}.} In + {\textsf{http://www.geocities.com/wronski12/posix\_ipc/index.html}}.} In generale, come le corrispettive del SysV IPC, le code di messaggi sono poco usate, dato che i socket, nei casi in cui sono sufficienti, sono più comodi, e che in casi più complessi la comunicazione può essere gestita direttamente con @@ -3335,7 +3342,7 @@ POSIX.\footnote{in realt La libreria inoltre richiede la presenza dell'apposito filesystem di tipo \texttt{mqueue} montato su \file{/dev/mqueue}; questo può essere fatto -aggiungendo ad \file{/etc/fstab} una riga come: +aggiungendo ad \conffile{/etc/fstab} una riga come: \begin{verbatim} mqueue /dev/mqueue mqueue defaults 0 0 \end{verbatim} @@ -3768,20 +3775,20 @@ suoi contenuti in memoria,\footnote{il filesystem \texttt{tmpfs} per la memoria condivisa; esso infatti non ha dimensione fissa, ed usa direttamente la cache interna del kernel (che viene usata anche per la shared memory in stile SysV). In più i suoi contenuti, essendo trattati - direttamente dalla memoria virtuale\index{memoria~virtuale} possono essere + direttamente dalla memoria virtuale \index{memoria~virtuale} possono essere salvati sullo swap automaticamente.} che viene attivato abilitando l'opzione \texttt{CONFIG\_TMPFS} in fase di compilazione del kernel. -Per potere utilizzare l'interfaccia POSIX per le code di messaggi le +Per potere utilizzare l'interfaccia POSIX per la memoria condivisa le \acr{glibc}\footnote{le funzioni sono state introdotte con le glibc-2.2.} richiedono di compilare i programmi con l'opzione \code{-lrt}; inoltre è necessario che in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs}; -questo di norma viene eseguita aggiungendo una riga tipo: +questo di norma viene fatto aggiungendo una riga del tipo di: \begin{verbatim} tmpfs /dev/shm tmpfs defaults 0 0 \end{verbatim} -ad \file{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs} +ad \conffile{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs} dove si vuole, per usarlo come RAM disk, con un comando del tipo: \begin{verbatim} mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs @@ -3845,7 +3852,7 @@ segmento di memoria condiviso con le stesse modalit 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 di dati, essi sono associati allo stesso -\index{inode}inode). In questo modo è possibile effettuare una chiamata ad +\index{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. @@ -3963,8 +3970,6 @@ Anche in questo caso questa interfaccia, oltre ad utilizzare gli opportuni file di definizione, occorrerà compilare i programmi con l'opzione \texttt{-lrt}. -% TODO trattare l'argomento a partire da man sem_overview. - La funzione che permette di creare un nuovo semaforo POSIX, creando il relativo file, o di accedere ad uno esistente, è \funcd{sem\_open}, questa prevede due forme diverse a seconda che sia utilizzata per aprire un semaforo @@ -4297,14 +4302,14 @@ variabile allocata dinamicamente nello \itindex{heap} 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 -renderlo visibile a tutti è di porlo in un tratto di memoria condivisa. In -tal caso occorrerà che tutti i processi abbiano un genitore comune che ha -allocato, con uno dei metodi possibili visti con \func{shm\_open} -(sez.~\ref{sec:ipc_posix_shm}), \func{mmap} (sez.~\ref{sec:file_memory_map}) o -\func{shmget} (sez.~\ref{sec:ipc_sysv_shm}) la memoria condivisa su cui si va -a creare il semaforo,\footnote{si ricordi che i tratti di memoria condivisa - vengono mantenuti nei processi figli attraverso la funzione \func{fork}.} a -cui essi poi potranno accedere. +renderlo visibile a tutti è di porlo in un tratto di memoria condivisa. Questo +potrà essere ottenuto direttamente sia con \func{shmget} (vedi +sez.~\ref{sec:ipc_sysv_shm}) che con \func{shm\_open} (vedi +sez.~\ref{sec:ipc_posix_shm}), oppure, nel caso che tutti i processi in gioco +abbiano un genitore comune, con una mappatura anonima con \func{mmap} (vedi +sez.~\ref{sec:file_memory_map}),\footnote{si ricordi che i tratti di memoria + condivisa vengono mantenuti nei processi figli attraverso la funzione + \func{fork}.} a cui essi poi potranno accedere. Una volta inizializzato il semaforo anonimo con \func{sem\_init} lo si potrà utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e @@ -4312,6 +4317,36 @@ utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e semaforo può dar luogo ad un comportamento indefinito. +Una volta che non si indenda più utilizzare un semaforo anonimo questo può +essere eliminato da sistema; per far questo di deve utilizzare una apposita +funzione, \funcd{sem\_destroy}, il cui prototipo è: +\begin{functions} + \headdecl{semaphore.h} + + \funcdecl{int sem\_destroy(sem\_t *sem)} + + Elimina il semaforo anonimo \param{sem}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore; nel quel caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EINVAL}] il valore di \param{value} eccede + \const{SEM\_VALUE\_MAX}. + \end{errlist} +} +\end{functions} + +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 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 +caso ci si trovi in una tale evenienza occorre reinizializzare il semaforo una +seconda volta con \func{sem\_init}. % LocalWords: like fifo System POSIX RPC Calls Common Object Request Brocker