Sistemati gli indici.
authorSimone Piccardi <piccardi@gnulinux.it>
Tue, 9 Jul 2002 17:29:24 +0000 (17:29 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Tue, 9 Jul 2002 17:29:24 +0000 (17:29 +0000)
fileadv.tex
filedir.tex
fileunix.tex
intro.tex
process.tex
prochand.tex
signal.tex
system.tex

index 067e1ff04970e5009e230935f97f2a1f5a527a7f..744237990b07fc99dc9948e48d0e189b80d4f2bb 100644 (file)
@@ -84,11 +84,56 @@ Attende che un certo insieme di file descriptor cambi stato.
 \end{prototype}
 
 La funzione mette il processo in stato di \textit{sleep} (vedi
-\ref{tab:proc_proc_states})
+\tabref{tab:proc_proc_states}) fintanto che non viene rilevate dell'attività
+sull'insieme dei file descriptor specificati (\param{readfds},
+\param{writefds} e \param{exceptfds}), per un tempo massimo specificato da
+\param{timeout}. 
+
+Per specificare quali file descriptor si intende selezionare, la funzione usa
+un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo
+\type{fd\_set}, che serve ad identificare un insieme di file descriptor, in
+maniera analoga a come un \textit{signal set} (vedi \secref{sec:sig_sigset})
+identifica un insieme di segnali. Per la manipolazione di questi \textit{file
+  descriptor set} si possono usare delle opportune macro di preprocessore:
+\begin{functions}
+  \headdecl{sys/select.h}
+  \funcdecl{FD\_ZERO(fd\_set *set)}
+  Inizializza l'insieme (vuoto).
+
+  \funcdecl{FD\_SET(int fd, fd\_set *set)}
+  Inserisce il file descriptor \param{fd} nell'insieme.
+
+  \funcdecl{FD\_CLR(int fd, fd\_set *set)}
+  Rimuove il file descriptor \param{fd} nell'insieme.
+  
+  \funcdecl{FD\_ISSET(int fd, fd\_set *set)}
+  Controlla se il file descriptor \param{fd} è nell'insieme.
+\end{functions}
 
+In genere un \textit{file descriptor set} può contenere fino ad un massimo di
+\macro{FD\_SETSIZE} file descriptor.  Questo a seconda del sistema può essere
+il limite del numero massimo di file aperti\footnote{ad esempio in Linux, fino
+  alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma quando,
+come nelle versioni più recenti del kernel, questo limite non c'è un massimo,
+esso indica le dimensioni in munero di bit utilizzabili per l'insieme.
 
 
-il cui prototipo è:
+La funzione richiede di specificare tre insiemi distinti di file descriptor;
+il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
+input in lettura, il secondo, \param{writefds} per verificare la possibilità
+di scrivere ed il terzo, \param{exceptfds}, per verificare l'esistenza di
+eccezioni. I corrispondenti valori dei \textit{file descriptor set} saranno
+modificati di conseguenza per mostrare quale dei file descriptor ha cambiato
+stato.
+
+
+
+
+
+Come accennato l'interfaccia di \func{select} è una estensione aggiunta BSD, e
+poi entrata a far parte di POSIX; allo stesso tempo System V aveva introdotto
+una interfaccia alternativa, basata sulla funzione \func{poll}, il cui
+prototipo è:
 \begin{prototype}{sys/poll.h}
   {int poll(struct pollfd *ufds, unsigned int nfds, int timeout)}
 
@@ -97,7 +142,9 @@ specificati da \param{ufds}.
   
 \bodydesc{La funzione restituisce il numero di file descriptor con attività in
   caso di successo, o 0 se c'è stato un timeout; in caso di errore viene
-  restituito  -1 ed \var{errno} viene .}
+  restituito  -1 ed \var{errno} viene settata ai valori:
+
+.}
 \end{prototype}
 
 
@@ -145,11 +192,12 @@ diversi. In quell'occasione si 
 in \textit{append mode}, quando più processi scrivono contemporaneamente sullo
 stesso file non è possibile determinare la sequenza in cui essi opereranno.
 
-Questo causa la possibilità di race condition; in generale le situazioni più
-comuni sono due: l'interazione fra un processo che scrive e altri che leggono,
-in cui questi ultimi possono leggere informazioni scritte solo in maniera
-parziale o incompleta; o quella in cui diversi processi scrivono, mescolando
-in maniera imprevedebile il loro output sul file.
+Questo causa la possibilità di race condition\index{race condition}; in
+generale le situazioni più comuni sono due: l'interazione fra un processo che
+scrive e altri che leggono, in cui questi ultimi possono leggere informazioni
+scritte solo in maniera parziale o incompleta; o quella in cui diversi
+processi scrivono, mescolando in maniera imprevedebile il loro output sul
+file.
 
 In tutti questi casi il \textit{file locking} è la tecnica che permette di
 evitare le race condition, attraverso una serie di funzioni che permettono di
index 66b1f99ca40ccf2688b6763c1dbf59ff0e16af10..c389a7de87d5ac351a71c5d31fb5cb79e8b9c501 100644 (file)
@@ -793,7 +793,8 @@ POSIX definisce la funzione \func{tempfile}, il cui prototipo 
 automaticamente cancellato alla sua chiusura o all'uscita dal programma. Lo
 standard non specifica in quale directory verrà aperto il file, ma le
 \acr{glibc} prima tentano con \macro{P\_tmpdir} e poi con \file{/tmp}. Questa
-funzione è rientrante e non soffre di problemi di \textit{race condition}.
+funzione è rientrante e non soffre di problemi di \textit{race
+  condition}\index{race condition}.
 
 Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo
 caso si possono usare le vecchie funzioni \func{mktemp} e \func{mkstemp} che
@@ -814,12 +815,13 @@ il suo prototipo 
 \end{prototype}
 \noindent dato che \param{template} deve poter essere modificata dalla
 funzione non si può usare una stringa costante.  Tutte le avvertenze riguardo
-alle possibili \textit{race condition} date per \func{tmpnam} continuano a
-valere; inoltre in alcune vecchie implementazioni il valore di usato per
-sostituire le \code{XXXXXX} viene formato con il \acr{pid} del processo più
-una lettera, il che mette a disposizione solo 26 possibilità diverse per il
-nome del file, e rende il nome temporaneo facile da indovinare. Per tutti
-questi motivi la funzione è deprecata e non dovrebbe mai essere usata.
+alle possibili \textit{race condition}\index{race condition} date per
+\func{tmpnam} continuano a valere; inoltre in alcune vecchie implementazioni
+il valore di usato per sostituire le \code{XXXXXX} viene formato con il
+\acr{pid} del processo più una lettera, il che mette a disposizione solo 26
+possibilità diverse per il nome del file, e rende il nome temporaneo facile da
+indovinare. Per tutti questi motivi la funzione è deprecata e non dovrebbe mai
+essere usata.
 
 
 
@@ -865,8 +867,8 @@ In OpenBSD 
 \end{prototype}
 \noindent la directory è creata con permessi \code{0700} (al solito si veda
 \capref{cha:file_unix_interface} per i dettagli); dato che la creazione della
-directory è sempre esclusiva i precedenti problemi di \textit{race condition}
-non si pongono.
+directory è sempre esclusiva i precedenti problemi di \textit{race
+  condition}\index{race condition} non si pongono.
 
 
 \section{La manipolazione delle caratteristiche dei files}
index 56e70435f4d2934b1e1abdeffe54b4ce5e82e703..37b090626418cd83b16726298ba994c89f3418b4 100644 (file)
@@ -3,11 +3,12 @@
 
 
 Esamineremo in questo capitolo la prima delle due interfacce di programmazione
-per i file, quella dei \textit{file descriptor}, nativa di Unix. Questa è
-l'interfaccia di basso livello provvista direttamente dalle system call, che
-non prevede funzionalità evolute come la bufferizzazione o funzioni di lettura
-o scrittura formattata, e sulla quale è costruita anche l'interfaccia definita
-dallo standard ANSI C che affronteremo al \capref{cha:files_std_interface}.
+per i file, quella dei \textit{file descriptor}\index{file descriptor},
+nativa di Unix. Questa è l'interfaccia di basso livello provvista direttamente
+dalle system call, che non prevede funzionalità evolute come la
+bufferizzazione o funzioni di lettura o scrittura formattata, e sulla quale è
+costruita anche l'interfaccia definita dallo standard ANSI C che affronteremo
+al \capref{cha:files_std_interface}.
 
 
 
@@ -33,10 +34,10 @@ terminate le operazioni, il file dovr
 canale di comunicazione impedendo ogni ulteriore operazione.
 
 All'interno di ogni processo i file aperti sono identificati da un intero non
-negativo, chiamato appunto \textit{file descriptor}. Quando un file viene
-aperto la funzione \func{open} restituisce questo numero, tutte le ulteriori
-operazioni saranno compiute specificando questo stesso valore come argomento
-alle varie funzioni dell'interfaccia.
+negativo, chiamato appunto \textit{file descriptor}\index{file descriptor}.
+Quando un file viene aperto la funzione \func{open} restituisce questo numero,
+tutte le ulteriori operazioni saranno compiute specificando questo stesso
+valore come argomento alle varie funzioni dell'interfaccia.
 
 Per capire come funziona il meccanismo occorre spiegare a grandi linee come è
 che il kernel gestisce l'interazione fra processi e file.  Il kernel mantiene
@@ -56,8 +57,8 @@ particolare:
 \item una tabella che contiene un puntatore alla relativa voce nella
   \textit{file table} per ogni file aperto.
 \end{itemize*}
-il \textit{file descriptor} in sostanza è l'intero positivo che indicizza
-quest'ultima tabella.
+il \textit{file descriptor}\index{file descriptor} in sostanza è l'intero
+positivo che indicizza quest'ultima tabella.
 
 La \textit{file table} è una tabella che contiene una voce per ciascun file
 che è stato aperto nel sistema. In Linux è costituita da strutture di tipo
@@ -87,23 +88,23 @@ varie strutture di dati sulla quale essa 
 \end{figure}
 Ritorneremo su questo schema più volte, dato che esso è fondamentale per
 capire i dettagli del funzionamento dell'interfaccia dei \textit{file
-  descriptor}.
+  descriptor}\index{file descriptor}.
 
 
 \subsection{I file standard}
 \label{sec:file_std_descr}
 
-Come accennato i \textit{file descriptor} non sono altro che un indice nella
-tabella dei file aperti di ciascun processo; per questo motivo essi vengono
-assegnati in successione tutte le volte che si apre un nuovo file (se non ne è
-stato chiuso nessuno in precedenza).
+Come accennato i \textit{file descriptor}\index{file descriptor} non sono
+altro che un indice nella tabella dei file aperti di ciascun processo; per
+questo motivo essi vengono assegnati in successione tutte le volte che si apre
+un nuovo file (se non ne è stato chiuso nessuno in precedenza).
 
 In tutti i sistemi unix-like esiste una convenzione generale per cui ogni
 processo viene lanciato con almeno tre file aperti. Questi, per quanto appena
-detto, avranno come \textit{file descriptor} i valori 0, 1 e 2.  Benché questa
-sia soltanto una convenzione, essa è seguita dalla gran parte delle
-applicazioni, e non aderirvi potrebbe portare a gravi problemi di
-interoperabilità.
+detto, avranno come \textit{file descriptor}\index{file descriptor} i valori
+0, 1 e 2.  Benché questa sia soltanto una convenzione, essa è seguita dalla
+gran parte delle applicazioni, e non aderirvi potrebbe portare a gravi
+problemi di interoperabilità.
 
 Il primo file è sempre associato a quello che viene chiamato \textit{standard
   input}. È cioè il file da cui il processo si aspetta di ricevere i dati in
@@ -292,9 +293,9 @@ sempre il file descriptor con il valore pi
 
 \footnotetext[2]{la man page di \func{open} segnala che questa opzione è
   difettosa su NFS, e che i programmi che la usano per stabilire un file di
-  lock possono incorrere in una race condition.  Si consiglia come alternativa
-  di usare un file con un nome univoco e la funzione \func{link} per
-  verificarne l'esistenza.}  
+  lock possono incorrere in una race condition\index{race condition}.  Si
+  consiglia come alternativa di usare un file con un nome univoco e la
+  funzione \func{link} per verificarne l'esistenza.}
 
 \footnotetext[3]{\textit{Denial of Service}, si chiamano così attacchi miranti
   ad impedire un servizio causando una qualche forma di carico eccessivo per
@@ -477,8 +478,8 @@ Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che
 successiva scrittura avvenga alla fine del file, infatti se questo è stato
 aperto anche da un altro processo che vi ha scritto, la fine del file può
 essersi spostata, ma noi scriveremo alla posizione settata in precedenza.
-(questa è una potenziale sorgente di \textit{race condition}, vedi
-\secref{sec:file_atomic}).
+(questa è una potenziale sorgente di 
+\textit{race condition}\index{race condition}, vedi \secref{sec:file_atomic}).
 
 Non tutti i file supportano la capacità di eseguire una \func{lseek}, in
 questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per
@@ -764,12 +765,14 @@ utilizzare meccanismi di sincronizzazione pi
 Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui
 vari processi devono scrivere alla fine di un file (ad esempio un file di
 log). Come accennato in \secref{sec:file_lseek} settare la posizione alla fine
-del file e poi scrivere può condurre ad una \textit{race condition}: infatti
-può succedere che un secondo processo scriva alla fine del file fra la
-\func{lseek} e la \func{write}; in questo caso, come abbiamo appena visto, il
-file sarà esteso, ma il nostro primo processo avrà ancora la posizione
-corrente settata con la \func{lseek} che non corrisponde più alla fine del
-file, e la successiva \func{write} sovrascriverà i dati del secondo processo.
+del file e poi scrivere può condurre ad una 
+\textit{race condition}\index{race condition}: 
+infatti può succedere che un secondo processo scriva alla fine
+del file fra la \func{lseek} e la \func{write}; in questo caso, come abbiamo
+appena visto, il file sarà esteso, ma il nostro primo processo avrà ancora la
+posizione corrente settata con la \func{lseek} che non corrisponde più alla
+fine del file, e la successiva \func{write} sovrascriverà i dati del secondo
+processo.
 
 Il problema è che usare due system call in successione non è un'operazione
 atomica; il problema è stato risolto introducendo la modalità
@@ -783,8 +786,8 @@ Un altro caso tipico in cui 
 creare un file di lock, bloccandosi se il file esiste. In questo caso la
 sequenza logica porterebbe a verificare prima l'esistenza del file con una
 \func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la
-possibilità di una race condition da parte di un altro processo che crea lo
-stesso file fra il controllo e la creazione. 
+possibilità di una race condition\index{race condition} da parte di un altro
+processo che crea lo stesso file fra il controllo e la creazione.
 
 Per questo motivo sono stati introdotti pe \func{open} i due flag
 \macro{O\_CREAT} e \macro{O\_EXCL}. In questo modo l'operazione di controllo
index 6b7be35e4d4bcff7a39e750c2e29460aa771096c..73f676134373a863bd0f15792e9a5c372173ccbf 100644 (file)
--- a/intro.tex
+++ b/intro.tex
@@ -61,12 +61,12 @@ soltanto attraverso delle opportune chiamate al sistema che restituiranno il
 controllo al kernel.
 
 La memoria viene sempre gestita dal kernel attraverso il meccanismo della
-\textsl{memoria virtuale}, che consente di assegnare a ciascun processo uno
-spazio di indirizzi ``virtuale'' (vedi \secref{sec:proc_memory}) che il kernel
-stesso, con l'ausilio della unità di gestione della memoria, si incaricherà di
-rimappare automaticamente sulla memoria disponibile, salvando su disco quando
-necessario (nella cosiddetta area di \textit{swap}) le pagine di memoria in
-eccedenza.
+\textsl{memoria virtuale}\index{memoria virtuale}, che consente di assegnare a
+ciascun processo uno spazio di indirizzi ``virtuale'' (vedi
+\secref{sec:proc_memory}) che il kernel stesso, con l'ausilio della unità di
+gestione della memoria, si incaricherà di rimappare automaticamente sulla
+memoria disponibile, salvando su disco quando necessario (nella cosiddetta
+area di \textit{swap}) le pagine di memoria in eccedenza.
 
 Le periferiche infine vengono viste in genere attraverso un'interfaccia
 astratta che permette di trattarle come fossero file, secondo il concetto per
index e3a4774786115eb7561fadeb0e0d914856dc4385..b6afd42cc09f5300e25ce23a689a1d3da1eee227 100644 (file)
@@ -291,8 +291,9 @@ servono. Questo meccanismo 
 \textit{paging}), ed è uno dei compiti principali del kernel.
 
 Quando un processo cerca di accedere ad una pagina che non è nella memoria
-reale, avviene quello che viene chiamato un \textit{page fault}\index{page
-  fault}; l'hardware di gestione della memoria genera un'interruzione e passa
+reale, avviene quello che viene chiamato un 
+\textit{page fault}\index{page fault}; 
+l'hardware di gestione della memoria genera un'interruzione e passa
 il controllo al kernel il quale sospende il processo e si incarica di mettere
 in RAM la pagina richiesta (effettuando tutte le operazioni necessarie per
 reperire lo spazio necessario), per poi restituire il controllo al processo.
@@ -319,14 +320,15 @@ tentativo di accedere ad un indirizzo non allocato 
 commette quando si è manipolato male un puntatore e genera quello che viene
 chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o
 scrivere da un indirizzo per il quale non esiste un'associazione della pagina
-virtuale, il kernel risponde al relativo \textit{page fault}
+virtuale, il kernel risponde al relativo \textit{page fault}\index{page fault}
 mandando un segnale \macro{SIGSEGV} al processo, che normalmente ne causa la
 terminazione immediata.
 
-È pertanto importante capire come viene strutturata la memoria virtuale di un
-processo. Essa viene divisa in \textsl{segmenti}, cioè un insieme contiguo di
-indirizzi virtuali ai quali il processo può accedere. Solitamente un
-programma C viene suddiviso nei seguenti segmenti:
+È pertanto importante capire come viene strutturata \textsl{la memoria
+  virtuale}\index{page fault} di un processo. Essa viene divisa in
+\textsl{segmenti}, cioè un insieme contiguo di indirizzi virtuali ai quali il
+processo può accedere.  Solitamente un programma C viene suddiviso nei
+seguenti segmenti:
 
 \begin{enumerate}
 \item Il segmento di testo o \textit{text segment}. Contiene il codice del
@@ -654,13 +656,13 @@ implementare una sua versione delle routine di allocazione.
 % \label{sec:proc_mem_malloc_custom}
 
 
-\subsection{Il controllo della memoria virtuale}  
+\subsection{Il controllo della memoria virtuale\index{memoria virtuale}}  
 \label{sec:proc_mem_lock}
 
-Come spiegato in \secref{sec:proc_mem_gen} il kernel gestisce la memoria in
-maniera trasparente ai processi, decidendo quando rimuovere pagine dalla
-memoria per metterle nello swap, sulla base dell'utilizzo corrente da parte
-dei vari processi.
+Come spiegato in \secref{sec:proc_mem_gen} il kernel gestisce la memoria
+virtuale in maniera trasparente ai processi, decidendo quando rimuovere pagine
+dalla memoria per metterle nello swap, sulla base dell'utilizzo corrente da
+parte dei vari processi.
 
 Nell'uso comune un processo non deve preoccuparsi di tutto ciò, in quanto il
 meccanismo della paginazione\index{paginazione} riporta in RAM, ed in maniera
@@ -708,14 +710,14 @@ comporta anche la fine dell'uso della sua memoria virtuale, e quindi anche di
 tutti i suoi \textit{memory lock}.
 
 I \textit{memory lock} non sono ereditati dai processi figli.\footnote{ma
-  siccome Linux usa il \textit{copy on write} (vedi \secref{sec:proc_fork})
-  gli indirizzi virtuali del figlio sono mantenuti sullo stesso segmento di
-  RAM del padre, quindi fintanto che un figlio non scrive su un segmento, può
-  usufruire del memory lock del padre.}  Siccome la presenza di un
-\textit{memory lock} riduce la memoria disponibile al sistema, con un impatto
-su tutti gli altri processi, solo l'amministratore ha la capacità di bloccare
-una pagina. Ogni processo può però sbloccare le pagine relative alla propria
-memoria.
+  siccome Linux usa il \textit{copy on write}\index{copy on write} (vedi
+  \secref{sec:proc_fork}) gli indirizzi virtuali del figlio sono mantenuti
+  sullo stesso segmento di RAM del padre, quindi fintanto che un figlio non
+  scrive su un segmento, può usufruire del memory lock del padre.}  Siccome la
+presenza di un \textit{memory lock} riduce la memoria disponibile al sistema,
+con un impatto su tutti gli altri processi, solo l'amministratore ha la
+capacità di bloccare una pagina. Ogni processo può però sbloccare le pagine
+relative alla propria memoria.
 
 Il sistema pone dei limiti all'ammontare di memoria di un processo che può
 essere bloccata e al totale di memoria fisica che può dedicare a questo, lo
@@ -787,11 +789,12 @@ esempio limitandosi a tutte le pagine allocate a partire da un certo momento.
 
 In ogni caso un processo real-time che deve entrare in una sezione critica
 deve provvedere a riservare memoria sufficiente prima dell'ingresso, per
-scongiurare in partenza un eventuale page fault causato dal meccanismo di
-\textit{copy on write}.  Infatti se nella sezione critica si va ad utilizzare
-memoria che non è ancora stata riportata in RAM si potrebbe avere un page
-fault durante l'esecuzione della stessa, con conseguente rallentamento
-(probabilmente inaccettabile) dei tempi di esecuzione.
+scongiurare in partenza un eventuale page fault\index{page fault} causato dal
+meccanismo di \textit{copy on write}\index{copy on write}.  Infatti se nella
+sezione critica si va ad utilizzare memoria che non è ancora stata riportata
+in RAM si potrebbe avere un page fault durante l'esecuzione della stessa, con
+conseguente rallentamento (probabilmente inaccettabile) dei tempi di
+esecuzione.
 
 In genere si ovvia a questa problematica chiamando una funzione che ha
 allocato una quantità sufficientemente ampia di variabili automatiche, in modo
index 1d805c02fedc0e55c0b4fe1d48c4d60d0e4e2b5e..e57e8ca84558fd05cf2e11e27dab49b7a9eaad6b 100644 (file)
@@ -416,8 +416,8 @@ degli eventuali tempi di attesa in secondi (eseguiti tramite la funzione
 descrizione delle opzioni); il codice completo, compresa la parte che gestisce
 le opzioni a riga di comando, è disponibile nel file \file{ForkTest.c},
 distribuito insieme agli altri sorgenti degli esempi su
-\href{http://firenze.linux.it/~piccardi/gapil_source.tgz}
-{\texttt{http://firenze.linux.it/\~~\hspace{-2.0mm}piccardi/gapil\_source.tgz}}.
+\href{http://gapil.firenze.linux.it/gapil_source.tgz}
+{\texttt{http://gapil.firenze.linux.it/gapil\_source.tgz}}.
 
 Decifrato il numero di figli da creare, il ciclo principale del programma
 (\texttt{\small 24--40}) esegue in successione la creazione dei processi figli
@@ -478,8 +478,9 @@ Pertanto non si pu
 istruzioni del codice fra padre e figli, né sull'ordine in cui questi potranno
 essere messi in esecuzione. Se è necessaria una qualche forma di precedenza
 occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il
-rischio di incorrere nelle cosiddette \textit{race condition} \index{race
-  condition} (vedi \secref{sec:proc_race_cond}.
+rischio di incorrere nelle cosiddette 
+\textit{race condition}\index{race condition} 
+(vedi \secref{sec:proc_race_cond}).
 
 Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
 processi completamente separati, le modifiche delle variabili nei processi
@@ -649,10 +650,10 @@ padre, che costituiva un inutile appesantimento in tutti quei casi in cui la
 \func{fork} veniva fatta solo per poi eseguire una \func{exec}. La funzione
 venne introdotta in BSD per migliorare le prestazioni.
 
-Dato che Linux supporta il \textit{copy on write} la perdita di prestazioni è
-assolutamente trascurabile, e l'uso di questa funzione (che resta un caso
-speciale della funzione \func{clone}), è deprecato; per questo eviteremo di
-trattarla ulteriormente.
+Dato che Linux supporta il \textit{copy on write}\index{copy on write} la
+perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
+funzione (che resta un caso speciale della funzione \func{clone}), è
+deprecato; per questo eviteremo di trattarla ulteriormente.
 
 
 \subsection{La conclusione di un processo.}
@@ -2103,11 +2104,11 @@ processo qualsiasi sia la sua priorit
   interrupt vengono intercettati dall'interfaccia real-time, e gestiti
   direttamente qualora ci sia la necessità di avere un processo con priorità
   più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un
-page fault si possono avere ritardi non previsti. Se l'ultimo problema può
-essere aggirato attraverso l'uso delle funzioni di controllo della memoria
-virtuale (vedi \secref{sec:proc_mem_lock}), il primo non è superabile e può
-comportare ritardi non prevedibili riguardo ai tempi di esecuzione di
-qualunque processo.
+page fault\index{page fault} si possono avere ritardi non previsti. Se
+l'ultimo problema può essere aggirato attraverso l'uso delle funzioni di
+controllo della memoria virtuale (vedi \secref{sec:proc_mem_lock}), il primo
+non è superabile e può comportare ritardi non prevedibili riguardo ai tempi di
+esecuzione di qualunque processo.
 
 In ogni caso occorre usare le priorità assolute con molta attenzione: se si dà
 ad un processo una priorità assoluta e questo finisce in un loop infinito,
@@ -2355,7 +2356,8 @@ di interruzione in una fase intermedia.
 In un ambiente multitasking il concetto è essenziale, dato che un processo può
 essere interrotto in qualunque momento dal kernel che mette in esecuzione un
 altro processo o dalla ricezione di un segnale; occorre pertanto essere
-accorti nei confronti delle possibili \textit{race condition} (vedi
+accorti nei confronti delle possibili 
+\textit{race condition}\index{race condition} (vedi
 \secref{sec:proc_race_cond}) derivanti da operazioni interrotte in una fase in
 cui non erano ancora state completate.
 
@@ -2389,7 +2391,8 @@ condiviso, onde evitare problemi con le ottimizzazioni del codice.
 
 
 
-\subsection{Le \textit{race condition} e i \textit{deadlock}}
+\subsection{Le \textit{race condition}\index{race condition} e i 
+  \textit{deadlock}}
 \label{sec:proc_race_cond}
 
 Si definiscono \textit{race condition} tutte quelle situazioni in cui processi
index 246c308c1f36bb0ab62cfe6ca999cdd6fdd5ed10..1ab3bd6aa8b1d9d510f83eecbc1fd3c7430cf7b2 100644 (file)
@@ -120,8 +120,8 @@ int sig_handler()
 Questa è la ragione per cui l'implementazione dei segnali secondo questa
 semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del
 segnale e la reinstallazione del suo manipolatore non sono operazioni
-atomiche, e sono sempre possibili delle race condition (sull'argomento vedi
-quanto detto in \secref{sec:proc_multi_prog}).
+atomiche, e sono sempre possibili delle race condition\index{race condition}
+(sull'argomento vedi quanto detto in \secref{sec:proc_multi_prog}).
 
 Un'altro problema è che in questa semantica non esiste un modo per bloccare i
 segnali quando non si vuole che arrivino; i processi possono ignorare il
@@ -242,7 +242,8 @@ Un programma pu
 \secref{sec:sig_sigaction}). Se si è installato un manipolatore sarà
 quest'ultimo ad essere eseguito alla notifica del segnale.  Inoltre il sistema
 farà si che mentre viene eseguito il manipolatore di un segnale, quest'ultimo
-venga automaticamente bloccato (così si possono evitare race condition).
+venga automaticamente bloccato (così si possono evitare race
+condition\index{race condition}).
 
 Nel caso non sia stata specificata un'azione, viene utilizzata l'azione
 standard che (come vedremo in \secref{sec:sig_standard}) è propria di ciascun
@@ -411,9 +412,9 @@ tipologia, verr
 \label{sec:sig_prog_error}
 
 Questi segnali sono generati quando il sistema, o in certi casi direttamente
-l'hardware (come per i page fault non validi) rileva un qualche errore
-insanabile nel programma in esecuzione. In generale la generazione di questi
-segnali significa che il programma ha dei gravi problemi (ad esempio ha
+l'hardware (come per i \textit{page fault} non validi) rileva un qualche
+errore insanabile nel programma in esecuzione. In generale la generazione di
+questi segnali significa che il programma ha dei gravi problemi (ad esempio ha
 dereferenziato un puntatore non valido o ha eseguito una operazione aritmetica
 proibita) e l'esecuzione non può essere proseguita.
 
@@ -1472,8 +1473,9 @@ tutti gli stati di terminazione sono stati ricevuti.
 
 Le funzioni esaminate finora fanno riferimento ad alle modalità più elementari
 della gestione dei segnali; non si sono pertanto ancora prese in
-considerazione le tematiche più complesse, collegate alle varie race condition
-che i segnali possono generare e alla natura asincrona degli stessi.
+considerazione le tematiche più complesse, collegate alle varie race
+condition\index{race condition} che i segnali possono generare e alla natura
+asincrona degli stessi.
 
 Affronteremo queste problematiche in questa sezione, partendo da un esempio
 che le evidenzi, per poi prendere in esame le varie funzioni che permettono di
@@ -1540,13 +1542,13 @@ unsigned int sleep(unsigned int seconds)
 
 Questo codice però, a parte il non gestire il caso in cui si è avuta una
 precedente chiamata a \func{alarm} (che si è tralasciato per brevità),
-presenta una pericolosa race condition.  Infatti se il processo viene
-interrotto fra la chiamata di \func{alarm} e \func{pause} può capitare (ad
-esempio se il sistema è molto carico) che il tempo di attesa scada prima
-dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo l'arrivo di
-\macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un deadlock, in
-quanto \func{pause} non verrebbe mai più interrotta (se non in caso di un
-altro segnale).
+presenta una pericolosa race condition\index{race condition}.  Infatti se il
+processo viene interrotto fra la chiamata di \func{alarm} e \func{pause} può
+capitare (ad esempio se il sistema è molto carico) che il tempo di attesa
+scada prima dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo
+l'arrivo di \macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un
+deadlock, in quanto \func{pause} non verrebbe mai più interrotta (se non in
+caso di un altro segnale).
 
 Questo problema può essere risolto (ed è la modalità con cui veniva fatto in
 SVr2) usando la funzione \func{longjmp} (vedi \secref{sec:proc_longjmp}) per
@@ -1650,10 +1652,10 @@ quale potr
 segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}).
 
 Questo è il tipico esempio di caso, già citato in \secref{sec:proc_race_cond},
-in cui si genera una race condition; se infatti il segnale arriva
-immediatamente dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima
-della cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà
-perduta.
+in cui si genera una race condition\index{race condition}; se infatti il
+segnale arriva immediatamente dopo l'esecuzione del controllo (\texttt{\small
+  6}) ma prima della cancellazione del flag (\texttt{\small 7}), la sua
+occorrenza sarà perduta.
 
 Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono
 funzioni più sofisticate di quelle illustrate finora, che hanno origine dalla
@@ -2048,15 +2050,15 @@ occorre ricordare che qualunque modifica alla maschera dei segnali viene
 perduta alla conclusione del terminatore. 
 
 Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte
-dei casi di race condition restano aperte alcune possibilità legate all'uso di
-\func{pause}; il caso è simile a quello del problema illustrato nell'esempio
-di \secref{fig:sig_sleep_incomplete}, e cioè la possibilità che il processo
-riceva il segnale che si intende usare per uscire dallo stato di attesa
-invocato con \func{pause} immediatamente prima dell'esecuzione di
-quest'ultima. Per poter effettuare atomicamente la modifica della maschera dei
-segnali (di solito attivandone uno specifico) insieme alla sospensione del
-processo lo standard POSIX ha previsto la funzione \func{sigsuspend}, il cui
-prototipo è:
+dei casi di race condition\index{race condition} restano aperte alcune
+possibilità legate all'uso di \func{pause}; il caso è simile a quello del
+problema illustrato nell'esempio di \secref{fig:sig_sleep_incomplete}, e cioè
+la possibilità che il processo riceva il segnale che si intende usare per
+uscire dallo stato di attesa invocato con \func{pause} immediatamente prima
+dell'esecuzione di quest'ultima. Per poter effettuare atomicamente la modifica
+della maschera dei segnali (di solito attivandone uno specifico) insieme alla
+sospensione del processo lo standard POSIX ha previsto la funzione
+\func{sigsuspend}, il cui prototipo è:
 \begin{prototype}{signal.h}
 {int sigsuspend(const sigset\_t *mask)} 
   
@@ -2146,10 +2148,10 @@ fine (\texttt{\small 27}), e al contempo si prepara la maschera dei segnali
 \var{sleep\_mask} per riattivare \macro{SIGALRM} all'esecuzione di
 \func{sigsuspend}.  
 
-In questo modo non sono più possibili race condition dato che \macro{SIGALRM}
-viene disabilitato con \func{sigprocmask} fino alla chiamata di
-\func{sigsuspend}. Questo metodo è assolutamente generale e può essere
-applicato a qualunque altra situazione in cui si deve attendere per un
+In questo modo non sono più possibili race condition\index{race conditionx}
+dato che \macro{SIGALRM} viene disabilitato con \func{sigprocmask} fino alla
+chiamata di \func{sigsuspend}. Questo metodo è assolutamente generale e può
+essere applicato a qualunque altra situazione in cui si deve attendere per un
 segnale, i passi sono sempre i seguenti:
 \begin{enumerate}
 \item Leggere la maschera dei segnali corrente e bloccare il segnale voluto
index ced0465ec599e1b6ef9f623e0efad98413b554ce..04d92db60aecd39c7851efcc225352d34551bede 100644 (file)
@@ -1395,12 +1395,13 @@ rispettivamente il tempo impiegato dal processo nell'eseguire le istruzioni in
 user space, e quello impiegato dal kernel nelle system call eseguite per conto
 del processo.
 
-Gli altri tre campi servono a quantificare l'uso della memoria virtuale e
-corrispondono rispettivamente al numero di \textit{page fault}\index{page
-  fault} (vedi \secref{sec:proc_mem_gen}) avvenuti senza richiedere I/O (i
-cosiddetti \textit{minor page fault}), a quelli che invece han richiesto I/O
-(detti invece \textit{major page fault}) ed al numero di volte che il processo
-è stato completamente tolto dalla memoria per essere inserito nello swap.
+Gli altri tre campi servono a quantificare l'uso della memoria
+virtuale\index{memoria virtuale} e corrispondono rispettivamente al numero di
+\textit{page fault}\index{page fault} (vedi \secref{sec:proc_mem_gen})
+avvenuti senza richiedere I/O (i cosiddetti \textit{minor page fault}), a
+quelli che invece han richiesto I/O (detti invece \textit{major page fault})
+ed al numero di volte che il processo è stato completamente tolto dalla
+memoria per essere inserito nello swap.
 
 In genere includere esplicitamente \file{<sys/time.h>} non è più necessario,
 ma aumenta la portabilità, e serve comunque quando, come nella maggior parte
@@ -1568,12 +1569,12 @@ mantenuti attraverso una \func{exec} (vedi \secref{sec:proc_exec}).
 
 La gestione della memoria è già stata affrontata in dettaglio in
 \secref{sec:proc_memory}; abbiamo visto allora che il kernel provvede il
-meccanismo della memoria virtuale attraverso la divisione della memoria fisica
-in pagine.
+meccanismo della memoria virtuale\index{memoria virtuale} attraverso la
+divisione della memoria fisica in pagine.
 
 In genere questo è del tutto trasparente al singolo processo, ma in certi
-casi, come per l'I/O mappato in memoria (vedi \ref{sec:file_memory_map}) che
-usa lo stesso meccanismo per accedere ai file, è necessario conoscere le
+casi, come per l'I/O mappato in memoria (vedi \secref{sec:file_memory_map})
+che usa lo stesso meccanismo per accedere ai file, è necessario conoscere le
 dimensioni delle pagine usate dal kernel. Lo stesso vale quando si vuole
 gestire in maniera ottimale l'interazione della memoria allocata con il
 meccanismo della paginazione.
@@ -1586,7 +1587,7 @@ dover fornire binari diversi per ogni possibile modello, 
 utilizzare una funzione. 
 
 In genere questa dimensione può essere ottenuta attraverso una chiamata a
-\func{sysconf} come \func{sysconf(\_SC\_PAGESIZE)}, ma in BSD 4.2 è stata
+\func{sysconf} come \code{sysconf(\_SC\_PAGESIZE)}, ma in BSD 4.2 è stata
 introdotta una apposita funzione, \func{getpagesize}, che restituisce la
 dimensione delle pagine di memoria; il suo prototipo è:
 \begin{prototype}{unistd.h}{int getpagesize(void)}