Avanti piano
[gapil.git] / prochand.tex
index 38a9b2f18799685c4e5c23a94ce5279a33f37521..582831aa8eb6dc908ab4b8a56c526fcbb37594aa 100644 (file)
@@ -103,15 +103,15 @@ init-+-keventd
 
 Dato che tutti i processi attivi nel sistema sono comunque generati da
 \cmd{init} o da uno dei suoi figli\footnote{in realtà questo non è del tutto
 
 Dato che tutti i processi attivi nel sistema sono comunque generati da
 \cmd{init} o da uno dei suoi figli\footnote{in realtà questo non è del tutto
-  vero, in Linux ci sono alcuni processi che pur comparendo come figli di
-  init, o con \acr{pid} successivi, sono in realtà generati direttamente dal
-  kernel, (come \cmd{keventd}, \cmd{kswapd}, etc.)} si possono classificare i
-processi con la relazione padre/figlio in un'organizzazione gerarchica ad
-albero, in maniera analoga a come i file sono organizzati in un albero di
-directory (si veda \secref{sec:file_organization}); in \curfig\ si è mostrato
-il risultato del comando \cmd{pstree} che permette di visualizzare questa
-struttura, alla cui base c'è \cmd{init} che è progenitore di tutti gli altri
-processi.
+  vero, in Linux ci sono alcuni processi speciali che pur comparendo come
+  figli di \cmd{init}, o con \acr{pid} successivi, sono in realtà generati
+  direttamente dal kernel, (come \cmd{keventd}, \cmd{kswapd}, etc.).} si
+possono classificare i processi con la relazione padre/figlio in
+un'organizzazione gerarchica ad albero, in maniera analoga a come i file sono
+organizzati in un albero di directory (si veda
+\secref{sec:file_organization}); in \curfig\ si è mostrato il risultato del
+comando \cmd{pstree} che permette di visualizzare questa struttura, alla cui
+base c'è \cmd{init} che è progenitore di tutti gli altri processi.
 
 
 Il kernel mantiene una tabella dei processi attivi, la cosiddetta
 
 
 Il kernel mantiene una tabella dei processi attivi, la cosiddetta
@@ -138,8 +138,9 @@ system call ed ad ogni interrupt, (ma pu
 esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato
 periodicamente, generando un interrupt periodico secondo la frequenza
 specificata dalla costante \macro{HZ}, definita in \file{asm/param.h} Il
 esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato
 periodicamente, generando un interrupt periodico secondo la frequenza
 specificata dalla costante \macro{HZ}, definita in \file{asm/param.h} Il
-valore usuale è 100 (è espresso in Hertz), si ha cioè un interrupt dal timer
-ogni centesimo di secondo.
+valore usuale è 100\footnote{è così per tutte le archietetture eccetto
+  l'alpha, per la quale è 1000} (è espresso in Hertz), si ha cioè un interrupt
+dal timer ogni centesimo di secondo.
 
 Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle
 priorità dei vari processi attivi (torneremo su questo in
 
 Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle
 priorità dei vari processi attivi (torneremo su questo in
@@ -213,11 +214,15 @@ intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato 
 \type{int}).
 
 Il \acr{pid} viene assegnato in forma progressiva ogni volta che un nuovo
 \type{int}).
 
 Il \acr{pid} viene assegnato in forma progressiva ogni volta che un nuovo
-processo viene creato, fino ad un limite massimo (in genere essendo detto
-numero memorizzato in un intero a 16 bit si arriva a 32767) oltre il quale si
-riparte dal numero più basso disponibile\footnote{FIXME: verificare, non sono
-  sicuro}.  Per questo motivo, come visto in \secref{sec:proc_hierarchy}, il
-processo di avvio (\cmd{init}) ha sempre il \acr{pid} uguale a uno.
+processo viene creato, fino ad un limite che, essendo il \acr{pid} un numero
+positivo memorizzato in un intero a 16 bit, arriva ad un massimo di 32767.
+Oltre questo valore l'assegnazione riparte dal numero più basso disponibile a
+partire da un minimo di 300,\footnote{questi valori sono definiti dalla macro
+  \macro{PID\_MAX} in \file{threads.h} e direttamente in \file{fork.c} nei
+  sorgenti del kernel.} che serve a riservare i \acr{pid} più bassi ai processi
+eseguiti dal direttamente dal kernel.  Per questo motivo, come visto in
+\secref{sec:proc_hierarchy}, il processo di avvio (\cmd{init}) ha sempre il
+\acr{pid} uguale a uno.
 
 Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui
 sono stati creati, questo viene chiamato in genere \acr{ppid} (da
 
 Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui
 sono stati creati, questo viene chiamato in genere \acr{ppid} (da
@@ -449,7 +454,7 @@ si pu
 primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
   scheduler di Ingo Molnar che esegue sempre per primo il figlio; per
   mantenere la portabilità è opportuno non fare comunque affidamento su questo
 primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
   scheduler di Ingo Molnar che esegue sempre per primo il figlio; per
   mantenere la portabilità è opportuno non fare comunque affidamento su questo
-  comportamento} dopo la chiamata a \func{fork}; dall'esempio si può notare
+  comportamento.} dopo la chiamata a \func{fork}; dall'esempio si può notare
 infatti come nei primi due cicli sia stato eseguito per primo il padre (con la
 stampa del \acr{pid} del nuovo processo) per poi passare all'esecuzione del
 figlio (completata con i due avvisi di esecuzione ed uscita), e tornare
 infatti come nei primi due cicli sia stato eseguito per primo il padre (con la
 stampa del \acr{pid} del nuovo processo) per poi passare all'esecuzione del
 figlio (completata con i due avvisi di esecuzione ed uscita), e tornare
@@ -678,7 +683,7 @@ eseguite alla chiusura di un processo 
 \item ad ogni processo figlio viene assegnato un nuovo padre (in genere
   \cmd{init}).
 \item viene inviato il segnale \macro{SIGCHLD} al processo padre (vedi
 \item ad ogni processo figlio viene assegnato un nuovo padre (in genere
   \cmd{init}).
 \item viene inviato il segnale \macro{SIGCHLD} al processo padre (vedi
-  \secref{sec:sig_xxx}).
+  \secref{sec:sig_sigchld}).
 \item se il processo è un leader di sessione viene mandato un segnale di
   \macro{SIGHUP} a tutti i processi in background e il terminale di
   controllo viene disconnesso (vedi \secref{sec:sess_xxx}).
 \item se il processo è un leader di sessione viene mandato un segnale di
   \macro{SIGHUP} a tutti i processi in background e il terminale di
   controllo viene disconnesso (vedi \secref{sec:sess_xxx}).
@@ -795,7 +800,7 @@ si scrive un programma che deve essere mantenuto in esecuzione a lungo e
 creare molti figli. In questo caso si deve sempre avere cura di far leggere
 l'eventuale stato di uscita di tutti i figli (in genere questo si fa
 attraverso un apposito \textit{signal handler}, che chiama la funzione
 creare molti figli. In questo caso si deve sempre avere cura di far leggere
 l'eventuale stato di uscita di tutti i figli (in genere questo si fa
 attraverso un apposito \textit{signal handler}, che chiama la funzione
-\func{wait}, vedi \secref{sec:sig_xxx} e \secref{sec:proc_wait}). Questa
+\func{wait}, vedi \secref{sec:sig_sigchld} e \secref{sec:proc_wait}). Questa
 operazione è necessaria perché anche se gli \textit{zombie} non consumano
 risorse di memoria o processore, occupano comunque una voce nella tabella dei
 processi, che a lungo andare potrebbe esaurirsi.
 operazione è necessaria perché anche se gli \textit{zombie} non consumano
 risorse di memoria o processore, occupano comunque una voce nella tabella dei
 processi, che a lungo andare potrebbe esaurirsi.
@@ -846,7 +851,7 @@ segnale termina il processo o chiama una funzione di gestione.
 processo figlio termina. Se un figlio è già terminato la funzione ritorna
 immediatamente.
 
 processo figlio termina. Se un figlio è già terminato la funzione ritorna
 immediatamente.
 
-Al ritorno lo stato di termininazione del processo viene salvato nella
+Al ritorno lo stato di terminazione del processo viene salvato nella
 variabile puntata da \var{status} e tutte le informazioni relative al
 processo (vedi \secref{sec:proc_termination}) vengono rilasciate.  Nel
 caso un processo abbia più figli il valore di ritorno permette di
 variabile puntata da \var{status} e tutte le informazioni relative al
 processo (vedi \secref{sec:proc_termination}) vengono rilasciate.  Nel
 caso un processo abbia più figli il valore di ritorno permette di
@@ -960,9 +965,9 @@ avremo la certezza che la chiamata a \func{wait} non si bloccher
     \macro{WIFSIGNALED} ha restituito un valore non nullo.\\
     \macro{WCOREDUMP(s)}   & Vera se il processo terminato ha generato un
     file si \textit{core dump}. Può essere valutata solo se
     \macro{WIFSIGNALED} ha restituito un valore non nullo.\\
     \macro{WCOREDUMP(s)}   & Vera se il processo terminato ha generato un
     file si \textit{core dump}. Può essere valutata solo se
-    \macro{WIFSIGNALED} ha restituito un valore non nullo\footnote{questa
+    \macro{WIFSIGNALED} ha restituito un valore non nullo.\footnote{questa
     macro non è definita dallo standard POSIX.1, ma è presente come estensione
     macro non è definita dallo standard POSIX.1, ma è presente come estensione
-    sia in Linux che in altri unix}.\\
+    sia in Linux che in altri Unix.}\\
     \macro{WIFSTOPPED(s)}  & Vera se il processo che ha causato il ritorno di
     \func{waitpid} è bloccato. L'uso è possibile solo avendo specificato
     l'opzione \macro{WUNTRACED}. \\
     \macro{WIFSTOPPED(s)}  & Vera se il processo che ha causato il ritorno di
     \func{waitpid} è bloccato. L'uso è possibile solo avendo specificato
     l'opzione \macro{WUNTRACED}. \\
@@ -1204,7 +1209,7 @@ la lista completa 
 \item il \textit{session id} ed il \textit{process group id} (vedi
   \secref{sec:sess_xxx}).
 \item il terminale di controllo (vedi \secref{sec:sess_xxx}).
 \item il \textit{session id} ed il \textit{process group id} (vedi
   \secref{sec:sess_xxx}).
 \item il terminale di controllo (vedi \secref{sec:sess_xxx}).
-\item il tempo restante ad un allarme (vedi \secref{sec:sig_xxx}).
+\item il tempo restante ad un allarme (vedi \secref{sec:sig_alarm_abort}).
 \item la directory radice e la directory di lavoro corrente (vedi
   \secref{sec:file_work_dir}).
 \item la maschera di creazione dei file (\var{umask}, vedi
 \item la directory radice e la directory di lavoro corrente (vedi
   \secref{sec:file_work_dir}).
 \item la maschera di creazione dei file (\var{umask}, vedi
@@ -1282,7 +1287,7 @@ problematiche connesse ad una gestione accorta dei privilegi.
 Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in
   realtà già esistono estensioni di questo modello base, che lo rendono più
   flessibile e controllabile, come le \textit{capabilities}, le ACL per i file
 Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in
   realtà già esistono estensioni di questo modello base, che lo rendono più
   flessibile e controllabile, come le \textit{capabilities}, le ACL per i file
-  o il \textit{Mandatory Access Control} di SELinux} di sicurezza di un
+  o il \textit{Mandatory Access Control} di SELinux.} di sicurezza di un
 sistema unix-like è fondato sui concetti di utente e gruppo, e sulla
 separazione fra l'amministratore (\textsl{root}, detto spesso anche
 \textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli
 sistema unix-like è fondato sui concetti di utente e gruppo, e sulla
 separazione fra l'amministratore (\textsl{root}, detto spesso anche
 \textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli
@@ -1818,7 +1823,7 @@ quando si definisce \macro{\_POSIX\_SOURCE} o si compila con il flag
 In questa sezione tratteremo più approfonditamente i meccanismi con il quale
 lo \textit{scheduler}\footnote{che è la parte del kernel che si occupa di
   stabilire quale processo dovrà essere posto in esecuzione.} assegna la CPU
 In questa sezione tratteremo più approfonditamente i meccanismi con il quale
 lo \textit{scheduler}\footnote{che è la parte del kernel che si occupa di
   stabilire quale processo dovrà essere posto in esecuzione.} assegna la CPU
-ai vari processi attivi. In particolare prendremo in esame i vari meccanismi
+ai vari processi attivi. In particolare prenderemo in esame i vari meccanismi
 con cui viene gestita l'assegnazione del tempo di CPU, ed illustreremo le
 varie funzioni di gestione.
 
 con cui viene gestita l'assegnazione del tempo di CPU, ed illustreremo le
 varie funzioni di gestione.
 
@@ -1836,15 +1841,14 @@ multi-processore si introduce anche la problematica dovuta alla scelta di
 quale sia la CPU più opportuna da utilizzare.\footnote{nei processori moderni
   la presenza di ampie cache può rendere poco efficiente trasferire
   l'esecuzione di un processo da una CPU ad un'altra, per cui occorrono
 quale sia la CPU più opportuna da utilizzare.\footnote{nei processori moderni
   la presenza di ampie cache può rendere poco efficiente trasferire
   l'esecuzione di un processo da una CPU ad un'altra, per cui occorrono
-  meccanismi per determininare quale è la migliore scelta fra le diverse CPU.}
+  meccanismi per determinare quale è la migliore scelta fra le diverse CPU.}
 Tutto questo comunque appartiene alle sottigliezze dell'implementazione del
 Tutto questo comunque appartiene alle sottigliezze dell'implementazione del
-kernel, e dal punto di vista dei programmi che girano in user space anche
-quando si hanno più processori, e quindi potenzialmente anche dei processi che
-sono eseguiti davvero in contemporanea, si può pensare alle politiche di
-scheduling come concernenti la risorsa \textsl{tempo di esecuzione}, la cui
-assegnazione sarà governata dagli stessi meccanismi di scelta di priorità,
-solo che nel caso di più processori sarà a disposizione di più di un processo
-alla volta.
+kernel, e dal punto di vista dei programmi che girano in user space, anche
+quando si hanno più processori (e dei processi che sono eseguiti davvero in
+contemporanea), si può pensare alle politiche di scheduling come concernenti
+la risorsa \textsl{tempo di esecuzione}, la cui assegnazione sarà governata
+dagli stessi meccanismi di scelta di priorità, solo che nel caso di più
+processori sarà a disposizione di più di un processo alla volta.
 
 Si tenga presente inoltre che l'utilizzo della CPU è soltanto una delle
 risorse (insieme alla memoria e all'accesso alle periferiche) che sono
 
 Si tenga presente inoltre che l'utilizzo della CPU è soltanto una delle
 risorse (insieme alla memoria e all'accesso alle periferiche) che sono
@@ -1853,48 +1857,66 @@ importante. Per questo non 
 priorità di esecuzione abbia risultati significativi in termini di
 prestazioni.
 
 priorità di esecuzione abbia risultati significativi in termini di
 prestazioni.
 
-La politica tradizionale di scheduling di Unix (che tratteremo in
-\secref{sec:proc_sched_stand}) è sempre stata basata su delle priorità
-dinamiche, che assicurassero che tutti i processi, anche i meno importanti,
-potessero ricevere un po' di tempo di CPU.
-
-Lo standard POSIX però per tenere conto dei sistemi real-time,\footnote{per
-  sistema real-time si intende un sistema in grado di eseguire operazioni in
-  tempo reale; in genere si tende a distinguere fra l'\textit{hard real-time}
-  in cui è necessario che i tempi di esecuzione di un programma siano
-  determinabili con certezza assoluta, come nel caso di meccanismi di
-  controllo di macchine, dove uno sforamento dei tempi avrebbe conseguenze
-  disastrose, e \textit{soft-real-time} in cui un occasionale sforamento è
-  ritenuto accettabile.} in cui è vitale che i processi che devono essere
-eseguiti in un determinato momento non debbano aspettare la conclusione di 
-altri processi che non hanno questa necessità, ha introdotto il concetto di
-\textsl{priorità assoluta}, chimata anche \textsl{priorità statica}, in
-contrapposizione con la normale priorità dinamica.
-
-Il concetto di prorità assoluta dice che quando due processi si contendono
-l'esecuzione, vince sempre quello con la priorità assoluta più alta, anche,
-grazie al \textit{prehemptive scheduling}, se l'altro è in esecuzione.
+Il meccanismo tradizionale di scheduling di Unix (che tratteremo in
+\secref{sec:proc_sched_stand}) è sempre stato basato su delle \textsl{priorità
+  dinamiche}, in modo da assicurare che tutti i processi, anche i meno
+importanti, possano ricevere un po' di tempo di CPU. In sostanza quando un
+processo ottiene la CPU la sua priorità viene diminuita. In questo modo alla
+fine, anche un processo con priorità iniziale molto bassa, finisce per avere
+una priorità sufficiente per essere eseguito.
+
+Lo standard POSIX.1b però ha introdotto il concetto di \textsl{priorità
+  assoluta}, (chiamata anche \textsl{priorità statica}, in contrapposizione
+alla normale priorità dinamica), per tenere conto dei sistemi
+real-time,\footnote{per sistema real-time si intende un sistema in grado di
+  eseguire operazioni in tempo reale; in genere si tende a distinguere fra
+  l'\textit{hard real-time} in cui è necessario che i tempi di esecuzione di
+  un programma siano determinabili con certezza assoluta, come nel caso di
+  meccanismi di controllo di macchine, dove uno sforamento dei tempi avrebbe
+  conseguenze disastrose, e \textit{soft-real-time} in cui un occasionale
+  sforamento è ritenuto accettabile.} in cui è vitale che i processi che
+devono essere eseguiti in un determinato momento non debbano aspettare la
+conclusione di altri che non hanno questa necessità.
+
+Il concetto di priorità assoluta dice che quando due processi si contendono
+l'esecuzione, vince sempre quello con la priorità assoluta più alta, anche
+quando l'altro è in esecuzione (grazie al \textit{prehemptive scheduling}).
 Ovviamente questo avviene solo per i processi che sono pronti per essere
 Ovviamente questo avviene solo per i processi che sono pronti per essere
-eseguiti (cioè nello stato \textit{runnable}\footnote{lo stato di un processo
+eseguiti (cioè nello stato \textit{runnable},\footnote{lo stato di un processo
   è riportato nel campo \texttt{STAT} dell'output del comando \cmd{ps},
   abbiamo già visto che lo stato di \textit{zombie} è indicato con \texttt{Z},
   gli stati \textit{runnable}, \textit{sleep} e di I/O (\textit{uninteruttible
   è riportato nel campo \texttt{STAT} dell'output del comando \cmd{ps},
   abbiamo già visto che lo stato di \textit{zombie} è indicato con \texttt{Z},
   gli stati \textit{runnable}, \textit{sleep} e di I/O (\textit{uninteruttible
-    sleep}) sono invece indicati con \texttt{R}, \texttt{S} e \texttt{D}.}),
+    sleep}) sono invece indicati con \texttt{R}, \texttt{S} e \texttt{D}.})
 la priorità assoluta viene invece ignorata per quelli che sono bloccati su una
 la priorità assoluta viene invece ignorata per quelli che sono bloccati su una
-richiesta di I/O o in stato di \textit{sleep}.
-
-Questa viene in genere indicata con un numero
-
+richiesta di I/O o in stato di \textit{sleep}.  La priorità assoluta viene in
+genere indicata con un numero intero, ed un valore più alto comporta una
+priorità maggiore, su questa politica di scheduling torneremo in
+\secref{sec:proc_real_time}.  
 
 
+In generale quello che succede in tutti gli Unix moderni è che ai processi
+normali viene sempre data una priorità assoluta pari a zero, e la decisione di
+assegnazione della CPU è fatta solo in base ad una priorità dinamica che è
+calcolata indipendentemente. È tuttavia possibile assegnare anche una priorità
+assoluta nel qual caso un processo avrà la precedenza su tutti gli altri di
+priorità inferiore che saranno eseguiti solo quando quest'ultimo non avrà
+bisogno della CPU.
 
 
 \subsection{Il meccanismo di \textit{scheduling} standard}
 \label{sec:proc_sched_stand}
 
 
 
 \subsection{Il meccanismo di \textit{scheduling} standard}
 \label{sec:proc_sched_stand}
 
-In Linux tutti i processi hanno sostanzialmente la stessa priorità; benché sia
-possibile specificare una priorità assoluta secondo lo standard POSIX
-(argomento che tratteremo più avanti) l'uso comune segue quello che è il
-meccanismo tradizionale con cui i sistemi
+A meno che non si abbiano specifiche esigenze, l'unico meccanismo di
+scheduling con il quale si avrà a che fare è quello tradizionale che prevede
+solo priorità dinamiche, ed è di questo che di norma ci si dovrà preoccupare
+nella programmazione.
+
+Come accennato in Linux tutti i processi ordinari hanno la stessa priorità
+assoluta. Quello che determina quale, fra tutti i processi in attesa di
+esecuzione, sarà eseguito per primo, è la priorità dinamica, che è chiamata
+così proprio perché viene varia nel corso dell'esecuzione di un processo.
+
+
+
 
 \subsection{Il meccanismo di \textit{scheduling real-time}}
 \label{sec:proc_real_time}
 
 \subsection{Il meccanismo di \textit{scheduling real-time}}
 \label{sec:proc_real_time}
@@ -1902,6 +1924,17 @@ meccanismo tradizionale con cui i sistemi
 Per settare le 
 
 
 Per settare le 
 
 
+\footnote{a meno che non si siano installate le patch di RTLinux o RTAI, con i
+  quali è possibile ottenere un sistema effettivamente hard real-time.}
+
+in realtà non si tratta di un vero hard real-time, in quanto
+  la presenza di eventuali interrupt o di page fault può sempre interrompere
+  l'esecuzione di un processo, a meno di non installare le estensioni di
+  RTLinux o RTAI, il normale kernel non è real-time.
+
+
+
+
 
 \section{Problematiche di programmazione multitasking}
 \label{sec:proc_multi_prog}
 
 \section{Problematiche di programmazione multitasking}
 \label{sec:proc_multi_prog}