%% 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
\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
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
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.