%% Copyright (C) 2000-2004 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 "Prefazione",
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
%% license is included in the section entitled "GNU Free Documentation
%% License".
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} deve poter gestire più richieste in concorrenza, e si avrebbe una
-evidente race condition\index{race condition} in caso di accesso simultaneo a
-detto file.\footnote{il problema potrebbe essere superato determinando in
- anticipo un nome appropriato per il file temporaneo, che verrebbe utilizzato
- dai vari sotto-processi, e cancellato alla fine della loro esecuzione; ma a
- questo le cose non sarebbero più tanto semplici.} L'uso di una 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}\index{\textit{race~condition}} in caso di
+accesso simultaneo a detto file.\footnote{il problema potrebbe essere superato
+ determinando in anticipo un nome appropriato per il file temporaneo, che
+ verrebbe utilizzato dai vari sotto-processi, e cancellato alla fine della
+ loro esecuzione; ma a questo le cose non sarebbero più tanto semplici.}
+L'uso di una 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
lettura; è possibile anche usare la fifo all'interno di un solo processo, nel
qual caso però occorre stare molto attenti alla possibili situazioni di
stallo.\footnote{se si cerca di leggere da una fifo che non contiene dati si
- avrà un deadlock\index{deadlock} immediato, dato che il processo si blocca e
- non potrà quindi mai eseguire le funzioni di scrittura.}
+ avrà un deadlock\index{\textit{deadlock}} immediato, dato che il processo si
+ blocca e non potrà quindi mai eseguire le funzioni di scrittura.}
Per la loro caratteristica di essere accessibili attraverso il filesystem, è
piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle
occorrerà definire la speciale variabile di ambiente \code{LD\_LIBRARY\_PATH}
in modo che il linker dinamico possa accedervi.
-In generale questa variabile indica il pathname della directory contenente la
+In generale questa variabile indica il
+\index{\textit{pathname}}\textit{pathname} della directory contenente la
libreria. Nell'ipotesi (che daremo sempre per verificata) che si facciano le
prove direttamente nella directory dei sorgenti (dove di norma vengono creati
sia i programmi che la libreria), il comando da dare sarà \code{export
(torneremo su questa funzionalità in sez.~\ref{sec:xxx_fd_passing}).
-\section{La comunicazione fra processi di System V}
+\section{Il sistema di comunicazione fra processi di System V}
\label{sec:ipc_sysv}
Benché le pipe e le fifo siano ancora ampiamente usate, esse scontano il
oggetti per la comunicazione fra processi ed una nuova interfaccia di
programmazione, che fossero in grado di garantire una maggiore flessibilità.
In questa sezione esamineremo come Linux supporta quello che viene chiamato il
-\textsl{Sistema di comunicazione inter-processo} di System V, cui da qui in
+\textsl{Sistema di comunicazione fra processi} di System V, cui da qui in
avanti faremo riferimento come \textit{SysV IPC} (dove IPC è la sigla di
\textit{Inter-Process Comunication}).
\end{functions}
La funzione determina un valore della chiave sulla base di \param{pathname},
-che deve specificare il pathname di un file effettivamente esistente e di un
-numero di progetto \param{proj\_id)}, che di norma viene specificato come
-carattere, dato che ne vengono utilizzati solo gli 8 bit meno
-significativi.\footnote{nelle libc4 e libc5, come avviene in SunOS,
- l'argomento \param{proj\_id} è dichiarato tipo \ctyp{char}, le \acr{glibc}
- usano il prototipo specificato da XPG4, ma vengono lo stesso utilizzati gli
- 8 bit meno significativi.}
+che deve specificare il \index{\textit{pathname}}\textit{pathname} di un file
+effettivamente esistente e di un numero di progetto \param{proj\_id)}, che di
+norma viene specificato come carattere, dato che ne vengono utilizzati solo
+gli 8 bit meno significativi.\footnote{nelle libc4 e libc5, come avviene in
+ SunOS, l'argomento \param{proj\_id} è dichiarato tipo \ctyp{char}, le
+ \acr{glibc} usano il prototipo specificato da XPG4, ma vengono lo stesso
+ utilizzati gli 8 bit 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)}
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 \textit{polling}\index{polling} che esegua un ciclo di attesa su ciascuna
-di esse.
+di \textit{polling}\index{\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 fifo. In questo caso
I semafori non sono meccanismi di intercomunicazione diretta come quelli
(pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare
dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o
-di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del
+di protezione per le \textsl{sezioni critiche}\index{sezioni~critiche} del
codice (si ricordi quanto detto in sez.~\ref{sec:proc_race_cond}).
Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a
referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last}
di \struct{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
-scheduler\index{scheduler} per passare all'esecuzione di un altro processo.
+struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper})
+poi quest'ultimo viene messo stato di attesa e viene invocato lo
+scheduler\index{\textit{scheduler}} per passare all'esecuzione di un altro
+processo.
Se invece tutte le operazioni possono avere successo queste vengono eseguite
immediatamente, dopo di che il kernel esegue una scansione della coda di
\var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
il creatore del segmento, oppure l'amministratore. Compiuta l'operazione
aggiorna anche il valore del campo \var{shm\_ctime}.
-\item[\const{SHM\_LOCK}] Abilita il
- \textit{memory locking}\index{memory locking}\footnote{impedisce cioè che la
+\item[\const{SHM\_LOCK}] Abilita il \textit{memory
+ locking}\index{\textit{memory~locking}}\footnote{impedisce cioè che la
memoria usata per il segmento venga salvata su disco dal meccanismo della
- memoria virtuale\index{memoria virtuale}; si ricordi quanto trattato in
+ memoria virtuale\index{memoria~virtuale}; si ricordi quanto trattato in
sez.~\ref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo
l'amministratore può utilizzare questo comando.
-\item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento
- di memoria condivisa. Solo l'amministratore può utilizzare questo comando.
+\item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory
+ locking}\index{\textit{memory~locking}} sul segmento di memoria condivisa.
+ Solo l'amministratore può utilizzare questo comando.
\end{basedescript}
i primi tre comandi sono gli stessi già visti anche per le code di messaggi e
gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche
previste da Linux, che permettono di abilitare e disabilitare il meccanismo
-della memoria virtuale\index{memoria virtuale} per il segmento.
+della memoria virtuale\index{memoria~virtuale} per il segmento.
L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT}
e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura
sez.~\ref{sec:file_open}) che 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 race
- condition\index{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}.
+ è comunque soggetti alla possibilità di una race
+ condition\index{\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}
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 \textit{polling}\index{polling},
-ed è quindi molto inefficiente.
+può essere eseguito solo con una tecnica di
+\textit{polling}\index{\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
Dato che i file di lock\index{file!di lock} presentano gli inconvenienti
illustrati in precedenza, la tecnica alternativa di sincronizzazione più
comune è quella di fare ricorso al \textit{file locking}\index{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}\index{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.
+(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}\index{\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
processo tutti i lock acquisiti vengono rilasciati automaticamente (alla
-\section{La comunicazione fra processi di POSIX}
+\section{Il sistema di comunicazione fra processi di POSIX}
\label{sec:ipc_posix}
Per superare i numerosi problemi del \textit{SysV IPC}, evidenziati per i suoi
La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
degli identificatori e delle chiavi visti nel SysV IPC, per passare ai
-\textit{Posix IPC names}\index{Posix IPC names}, che sono sostanzialmente
-equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC
-Posix prendono come primo argomento una stringa che indica uno di questi nomi;
-lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
-possono avere o meno una corrispondenza sul filesystem; tutto quello che è
-richiesto è che:
+\textit{Posix IPC names}\index{\textit{Posix~IPC~names}}, che sono
+sostanzialmente equivalenti ai nomi dei file. Tutte le funzioni che creano un
+oggetto di IPC Posix prendono come primo argomento una stringa che indica uno
+di questi nomi; lo standard è molto generico riguardo l'implementazione, ed i
+nomi stessi possono avere o meno una corrispondenza sul filesystem; tutto
+quello che è richiesto è che:
\begin{itemize}
\item i nomi devono essere conformi alle regole che caratterizzano i
- \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX}
- byte e terminati da un carattere nullo.
+ \index{\textit{pathname}}\textit{pathname}, in particolare non essere più
+ lunghi di \const{PATH\_MAX} byte e terminati da un carattere nullo.
\item se il nome inizia per una \texttt{/} chiamate differenti allo stesso
nome fanno riferimento allo stesso oggetto, altrimenti l'interpretazione del
nome dipende dall'implementazione.
(rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si
faccia riferimento a sez.~\ref{sec:ipc_posix_shm} e
sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni
-sono considerati come un pathname assoluto (comprendente eventuali
-sottodirectory) rispetto a queste radici.
+sono considerati come un \index{\textit{pathname}!assoluto}\textit{pathname}
+assoluto (comprendente eventuali sottodirectory) rispetto a queste radici.
Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti
nell'albero dei file, e possono essere maneggiati con le usuali funzioni e
In realtà a partire dal kernel 2.5.7 è stato introdotto un meccanismo di
sincronizzazione completamente nuovo, basato sui cosiddetti
-\textit{futex}\footnote{la sigla sta per \textit{faxt user mode mutex}.}, con
+\textit{futex}\footnote{la sigla sta per \textit{fast user mode mutex}.}, con
il quale dovrebbe essere possibile implementare una versione nativa dei
semafori; esso è già stato usato con successo per reimplementare in maniera
più efficiente tutte le direttive di sincronizzazione previste per i thread
utilizzabile anche per la memoria condivisa; esso infatti non ha dimensione
fissa, ed usa direttamente la cache interna del kernel (che viene usata
anche per la shared memory in stile SysV). In più i suoi contenuti, essendo
- trattati direttamente dalla memoria virtuale\index{memoria virtuale} possono
+ trattati 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.