Aggiuno un altro esempio
[gapil.git] / prochand.tex
index 9d07969bf4a0e95896fb46566f84e5dd35f8c636..73f2e7fb7e154388c55ce952497a41d5ab27e972 100644 (file)
@@ -113,7 +113,6 @@ organizzati in un albero di directory (si veda
 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
 \textit{process table}; per ciascun processo viene mantenuta una voce nella
 tabella dei processi costituita da una struttura \type{task\_struct}, che
@@ -134,7 +133,8 @@ riprese), 
 
 Come accennato in \secref{sec:intro_unix_struct} è lo \textit{scheduler} che
 decide quale processo mettere in esecuzione; esso viene eseguito ad ogni
-system call ed ad ogni interrupt, (ma può essere anche attivato
+system call ed ad ogni interrupt,\footnote{più in una serie di altre
+  occasioni. NDT completare questa parte.} (ma può essere anche attivato
 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
@@ -895,18 +895,18 @@ specchietto riportato in \ntab:
 \begin{table}[!htb]
   \centering
   \footnotesize
-  \begin{tabular}[c]{|c|p{10cm}|}
+  \begin{tabular}[c]{|c|c|p{8cm}|}
     \hline
-    \textbf{Valore} & \textbf{Significato}\\
+    \textbf{Valore} & \textbf{Macro} &\textbf{Significato}\\
     \hline
     \hline
-    $<-1$& attende per un figlio il cui \textit{process group} è uguale al
+    $<-1$& -- & attende per un figlio il cui \textit{process group} è uguale al
     valore assoluto di \var{pid}. \\
-    $-1$ & attende per un figlio qualsiasi, usata in questa maniera è
-    equivalente a \func{wait}.\\ 
-    $0$  & attende per un figlio il cui \textit{process group} è uguale a
-    quello del processo chiamante. \\
-    $>0$ & attende per un figlio il cui \acr{pid} è uguale al
+    $-1$ & \macro{WAIT\_ANY} & attende per un figlio qualsiasi, usata in
+    questa maniera è equivalente a \func{wait}.\\ 
+    $0$  & \macro{WAIT\_MYPGRP} & attende per un figlio il cui \textit{process
+    group} è uguale a quello del processo chiamante. \\
+    $>0$ & -- &attende per un figlio il cui \acr{pid} è uguale al
     valore di \var{pid}.\\
     \hline
   \end{tabular}
@@ -1348,7 +1348,7 @@ rispettivamente \textit{real} ed \textit{effective}.
     \hline
   \end{tabular}
   \caption{Identificatori di utente e gruppo associati a ciascun processo con
-    indicazione dei suffissi usate dalle varie funzioni di manipolazione.}
+    indicazione dei suffissi usati dalle varie funzioni di manipolazione.}
   \label{tab:proc_uid_gid}
 \end{table}
 
@@ -1424,11 +1424,11 @@ processo, come copie dell'\textit{effective user id} e dell'\textit{effective
 fossero utente e gruppo effettivi all'inizio dell'esecuzione di un nuovo
 programma.
 
-Il \textit{filesystem user id} e il \textit{filesystem group id} sono una
-estensione introdotta in Linux per rendere più sicuro l'uso di NFS (torneremo
-sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una replica dei
-corrispondenti \textit{effective id}, ai quali si sostituiscono per tutte le
-operazioni di verifica dei permessi relativi ai file (trattate in
+Il \textit{filesystem user id} e il \textit{filesystem group id} sono
+un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS
+(torneremo sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una
+replica dei corrispondenti \textit{effective id}, ai quali si sostituiscono
+per tutte le operazioni di verifica dei permessi relativi ai file (trattate in
 \secref{sec:file_perm_overview}).  Ogni cambiamento effettuato sugli
 \textit{effective id} viene automaticamente riportato su di essi, per cui in
 condizioni normali se ne può tranquillamente ignorare l'esistenza, in quanto
@@ -1588,9 +1588,10 @@ Lo stesso problema di propagazione dei privilegi ad eventuali processi figli
 si porrebbe per i \textit{saved id}: queste funzioni derivano da
 un'implementazione che non ne prevede la presenza, e quindi non è possibile
 usarle per correggere la situazione come nel caso precedente. Per questo
-motivo in Linux tutte le volte che vengono usate per modificare uno degli
-identificatori ad un valore diverso dal \textit{real id} precedente, il
-\textit{saved id} viene sempre settato al valore dell'\textit{effective id}.
+motivo in Linux tutte le volte che tali funzioni vengono usate per modificare
+uno degli identificatori ad un valore diverso dal \textit{real id} precedente,
+il \textit{saved id} viene sempre settato al valore dell'\textit{effective
+  id}.
 
 
 
@@ -1821,11 +1822,9 @@ quando si definisce \macro{\_POSIX\_SOURCE} o si compila con il flag
 \label{sec:proc_priority}
 
 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 prenderemo in esame i vari meccanismi
-con cui viene gestita l'assegnazione del tempo di CPU, ed illustreremo le
-varie funzioni di gestione.
+lo \textit{scheduler} assegna la CPU 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.
 
 
 \subsection{I meccanismi di \textit{scheduling}}
@@ -1836,6 +1835,16 @@ il tempo di CPU per l'esecuzione dei processi 
 ed oggetto di numerose ricerche; in ogni caso essa dipende in maniera
 essenziale anche dal tipo di utilizzo che deve essere fatto del sistema.
 
+
+La caratteristica specifica di un sistema multitasking come Linux è quella del
+cosiddetto \textit{prehemptive multitasking}: questo significa che al
+contrario di altri sistemi (che usano invece il cosiddetto \textit{cooperative
+  multitasking}) non sono i singoli processi, ma il kernel stesso a decidere
+quando la CPU deve essere passata ad un altro processo. Come accennato in
+\secref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione
+apposita del kernel, lo \textit{scheduler}, il cui scopo è quello di
+distribuire al meglio il tempo di CPU fra i vari processi.
+
 La cosa è resa ancora più complicata dal fatto che con le architetture
 multi-processore si introduce anche la problematica dovuta alla scelta di
 quale sia la CPU più opportuna da utilizzare.\footnote{nei processori moderni
@@ -1850,12 +1859,63 @@ la risorsa \textsl{tempo di esecuzione}, la cui assegnazione sar
 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
-necessarie per l'esecuzione di un programma, e spesso non è neanche la più
-importante. Per questo non è affatto detto che dare ad un programma la massima
-priorità di esecuzione abbia risultati significativi in termini di
-prestazioni.
+I processi non devono solo eseguire del codice, ad esempio molto spesso
+saranno impegnati in operazioni di I/O, possono venire bloccati da un
+comando dal terminale, sospesi per un certo periodo di tempo. In tutti questi
+casi la CPU diventa disponibile ed è compito dello kernel provvedere a mettere
+in esecuzione un altro processo.
+
+Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del
+processo ,
+
+In Linux un processo può trovarsi in uno degli stati riportati in
+\tabref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato
+\textit{runnable} concorrono per l'esecuzione. Questo vuol di
+
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|p{3cm}|c|p{8cm}|}
+    \hline
+    \textbf{Stato} & \texttt{STAT} & \textbf{Descrizione} \\
+    \hline
+    \hline
+    \textbf{Runnable} & \texttt{R} & Il processo è in esecuzione o è pronto ad
+    essere eseguito (cioè è in attesa che gli venga assegnata la CPU).   \\
+    \textbf{Sleep} & \texttt{S} & Il processo processo è in attesa di un
+    risposta dal sistema, ma può essere interrotto da un segnale. \\
+    \textbf{Uninterrutible Sleep} & \texttt{D} & Il  processo è in
+    attesa di un risposta dal sistema (in genere per I/O), e non può essere
+    interrotto in nessuna circostanza. \\
+    \textbf{Stopped} & \texttt{T} & Il processo è stato fermato con un
+    \macro{SIGSTOP}, o è tracciato.\\
+    \textbf{Zombie} & \texttt{Z} & Il processo è terminato ma il suo stato di
+    terminazione non è ancora stato letto dal padre. \\
+    \hline
+  \end{tabular}
+  \caption{Elenco dei possibili stati di un processo in Linux, nella colonna
+    \texttt{STAT} si è riportata la corripondente lettera usata dal comando 
+    \cmd{ps} nell'omonimo campo.}
+  \label{tab:proc_proc_states}
+\end{table}
+
+
+
+Si deve quindi tenere presente che l'utilizzo della CPU è soltanto una delle
+risorse che sono necessarie per l'esecuzione di un programma, e spesso non è
+neanche la più importante. Per questo motivo non è affatto detto che dare ad
+un programma la massima priorità di esecuzione abbia risultati significativi
+in termini di prestazioni.
+
+
+
+
+Una delle caratteristiche c
+
+la priorità assoluta viene invece ignorata per quelli che sono bloccati su una
+richiesta di I/O o in stato di \textit{sleep}
+
+
 
 Il meccanismo tradizionale di scheduling di Unix (che tratteremo in
 \secref{sec:proc_sched_stand}) è sempre stato basato su delle \textsl{priorità
@@ -1882,13 +1942,7 @@ Il concetto di priorit
 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
-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
-    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
-richiesta di I/O o in stato di \textit{sleep}.  La priorità assoluta viene in
+eseguiti (cioè nello stato \textit{runnable}).  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}.
@@ -1901,6 +1955,7 @@ assoluta nel qual caso un processo avr
 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}
 
@@ -1985,7 +2040,7 @@ qualunque momento, e le operazioni di un eventuale \textit{signal handler}
 sono compiute nello stesso spazio di indirizzi del processo. Per questo, anche
 il solo accesso o l'assegnazione di una variabile possono non essere più
 operazioni atomiche (torneremo su questi aspetti in
-\secref{sec:sign_control}).
+\secref{sec:sig_control}).
 
 In questo caso il sistema provvede un tipo di dato, il \type{sig\_atomic\_t},
 il cui accesso è assicurato essere atomico.  In pratica comunque si può
@@ -1998,6 +2053,7 @@ le strutture. In tutti questi casi 
 condiviso, onde evitare problemi con le ottimizzazioni del codice.
 
 
+
 \subsection{Le \textit{race condition} e i \textit{deadlock}}
 \label{sec:proc_race_cond}
 
@@ -2019,7 +2075,7 @@ funzioner
 
 Per questo occorre essere ben consapevoli di queste problematiche, e del fatto
 che l'unico modo per evitarle è quello di riconoscerle come tali e prendere
-gli adeguati provvedimenti per far si che non si verifichino. Casi tipici di
+gli adeguati provvedimenti per far sì che non si verifichino. Casi tipici di
 \textit{race condition} si hanno quando diversi processi accedono allo stesso
 file, o nell'accesso a meccanismi di intercomunicazione come la memoria
 condivisa. In questi casi, se non si dispone della possibilità di eseguire
@@ -2065,12 +2121,12 @@ mai rientrante se usa una variabile globale o statica.
 Nel caso invece la funzione operi su un oggetto allocato dinamicamente, la
 cosa viene a dipendere da come avvengono le operazioni: se l'oggetto è creato
 ogni volta e ritornato indietro la funzione può essere rientrante, se invece
-esso viene individuato dalla funzione stessa, due chiamate alla stessa
-funzione potranno interferire quando entrambe faranno riferimento allo stesso
-oggetto.  Allo stesso modo una funzione può non essere rientrante se usa e
-modifica un oggetto che le viene fornito dal chiamante: due chiamate possono
-interferire se viene passato lo stesso oggetto; in tutti questi casi occorre
-molta cura da parte del programmatore.
+esso viene individuato dalla funzione stessa due chiamate alla stessa funzione
+potranno interferire quando entrambe faranno riferimento allo stesso oggetto.
+Allo stesso modo una funzione può non essere rientrante se usa e modifica un
+oggetto che le viene fornito dal chiamante: due chiamate possono interferire
+se viene passato lo stesso oggetto; in tutti questi casi occorre molta cura da
+parte del programmatore.
 
 In genere le funzioni di libreria non sono rientranti, molte di esse ad
 esempio utilizzano variabili statiche, le \acr{glibc} però mettono a