Aggiornamenti vari, in particolare sui segnali ed i timer.
[gapil.git] / prochand.tex
index da1d5020ba81e2a5101fa70697eca06797bb5a5f..f3329a855b5c0c9ccbbaee18210dc83584b5a6c1 100644 (file)
@@ -146,20 +146,21 @@ fig.~\ref{fig:proc_task_struct}.
 
 % TODO la task_struct è cambiata per qualche dettaglio vedi anche
 % http://www.ibm.com/developerworks/linux/library/l-linux-process-management/
+% TODO completare la parte su quando viene chiamato lo scheduler.
 
 Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \itindex{scheduler}
 \textit{scheduler} che decide quale processo mettere in esecuzione; esso viene
 eseguito ad ogni system call ed ad ogni interrupt,\footnote{più in una serie
-  di altre occasioni.}
-% TODO completare questa parte su quando viene chiamato lo scheduler.
-(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
-\const{HZ},\footnote{fino al kernel 2.4 il valore usuale di questa costante
-  era 100, per tutte le architetture eccetto l'alpha, per la quale era 1000,
-  nel 2.6 è stato portato a 1000 su tutte le architetture; occorre fare
-  attenzione a non confondere questo valore con quello dei
-  \itindex{clock~tick} \textit{clock tick} (vedi
+  di altre occasioni.} 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
+\const{HZ},\footnote{fino al kernel 2.4 il valore di \const{HZ} era 100 su
+  tutte le architetture tranne l'alpha, per cui era 1000, nel 2.6 è stato
+  portato a 1000 su tutte; dal 2.6.13 lo si può impostare in fase di
+  compilazione del kernel, con un default di 250 e valori possibili di 100,
+  250, 1000 e dal 2.6.20 anche 300 (che è divisibile per le frequenze di
+  refresh della televisione); occorre fare attenzione a non confondere questo
+  valore con quello dei \itindex{clock~tick} \textit{clock tick} (vedi
   sez.~\ref{sec:sys_unix_time}).} definita in \file{asm/param.h}, ed il cui
 valore è espresso in Hertz.\footnote{a partire dal kernel 2.6.21 è stato
   introdotto (a cura di Ingo Molnar) un meccanismo completamente diverso,
@@ -171,7 +172,6 @@ valore 
   da parte del processore che può essere messo in stato di sospensione anche
   per lunghi periodi di tempo.}
 
-
 Ogni volta che viene eseguito, lo \itindex{scheduler} \textit{scheduler}
 effettua il calcolo delle priorità dei vari processi attivi (torneremo su
 questo in sez.~\ref{sec:proc_priority}) e stabilisce quale di essi debba
@@ -2146,21 +2146,21 @@ fintanto che esso si trova in uno qualunque degli altri stati.
 \begin{table}[htb]
   \footnotesize
   \centering
-  \begin{tabular}[c]{|p{2.8cm}|c|p{10cm}|}
+  \begin{tabular}[c]{|p{2.4cm}|c|p{9cm}|}
     \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). \\
+                                    venga assegnata la CPU).\\
     \textbf{Sleep}   & \texttt{S} & Il processo  è in attesa di un
                                     risposta dal sistema, ma può essere 
-                                    interrotto da un segnale. \\
+                                    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. \\
+                                    interrotto in nessuna circostanza.\\
     \textbf{Stopped} & \texttt{T} & Il processo è stato fermato con un
                                     \const{SIGSTOP}, o è tracciato.\\
     \textbf{Zombie}\index{zombie} & \texttt{Z} & Il processo è terminato ma il
@@ -2982,12 +2982,196 @@ risorsa che i processi devono contendersi, un'altra, altrettanto importante
 per le prestazioni, è quella dell'accesso a disco. Per questo motivo sono
 stati introdotti diversi \textit{I/O scheduler} in grado di distribuire in
 maniera opportuna questa risorsa ai vari processi. Fino al kernel 2.6.17 era
-possibile soltanto decidere le politiche di gestione scegliendo un diverso
-\textit{I/O scheduler}  
+possibile soltanto differenziare le politiche generali di gestione, scegliendo
+di usare un diverso \textit{I/O scheduler}; a partire da questa versione, con
+l'introduzione dello scheduler CFQ (\textit{Completely Fair Queuing}) è
+divenuto possibile, qualora si usi questo scheduler, impostare anche delle
+diverse priorità di accesso per i singoli processi.\footnote{al momento
+  (kernel 2.6.31), le priorità di I/O sono disponibili soltanto per questo
+  scheduler.}
+
+La scelta dello scheduler di I/O si può fare in maniera generica a livello di
+avvio del kernel assegnando il nome dello stesso al parametro
+\texttt{elevator}, mentre se ne può indicare uno per l'accesso al singolo
+disco scrivendo nel file \texttt{/sys/block/\textit{dev}/queue/scheduler}
+(dove \texttt{\textit{dev}} è il nome del dispositivo associato al disco); gli
+scheduler disponibili sono mostrati dal contenuto dello stesso file che
+riporta fra parentesi quadre quello attivo, il default in tutti i kernel
+recenti è proprio il \texttt{cfq},\footnote{nome con cui si indica appunto lo
+  scheduler \textit{Completely Fair Queuing}.} che supporta le priorità. Per i
+dettagli sulle caratteristiche specifiche degli altri scheduler, la cui
+discussione attiene a problematiche di ambito sistemistico, si consulti la
+documentazione nella directory \texttt{Documentation/block/} dei sorgenti del
+kernel.
+
+Una volta che si sia impostato lo scheduler CFQ ci sono due specifiche system
+call, specifiche di Linux, che consentono di leggere ed impostare le priorità
+di I/O.\footnote{se usate in corrispondenza ad uno scheduler diverso il loro
+  utilizzo non avrà alcun effetto.} Dato che non esiste una interfaccia
+diretta nelle \acr{glibc} per queste due funzioni occorrerà invocarle tramite
+la funzione \func{syscall} (come illustrato in
+sez.~\ref{sec:intro_syscall}). Le due funzioni sono \funcd{ioprio\_get} ed
+\funcd{ioprio\_set}; i rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{linux/ioprio.h}
+  \funcdecl{int ioprio\_get(int which, int who)} 
+  \funcdecl{int ioprio\_set(int which, int who, int ioprio)} 
+
+  Rileva o imposta la priorità di I/O di un processo.
+  
+  \bodydesc{Le funzioni ritornano rispettivamente un intero positivo
+    (indicante la priorità) o 0 in caso di successo e $-1$ in caso di errore,
+    nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] non esiste il processo indicato.
+    \item[\errcode{EINVAL}] i valori di \param{which} e \param{who} non sono
+      validi. 
+    \item[\errcode{EPERM}] non si hanno i privilegi per eseguire
+      l'impostazione (solo per \func{ioprio\_set}). 
+  \end{errlist} }
+\end{functions}
+
+Le funzioni leggono o impostano la priorità di I/O sulla base dell'indicazione
+dei due argomenti \param{which} e \param{who} che hanno lo stesso significato
+già visto per gli omonimi argomenti di \func{getpriority} e
+\func{setpriority}. Anche in questo caso si deve specificare il valore
+di \param{which} tramite le opportune costanti riportate in
+tab.~\ref{tab:ioprio_args} che consentono di indicare un singolo processo, i
+processi di un \textit{process group} (tratteremo questo argomento in
+sez.~\ref{sec:sess_proc_group}) o tutti o processi di un utente.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|c|c|l|}
+    \hline
+    \param{which} & \param{who} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IPRIO\_WHO\_PROCESS} & \type{pid\_t} & processo\\
+    \const{IPRIO\_WHO\_PRGR}    & \type{pid\_t} & \itindex{process~group}
+                                                  \textit{process group}\\ 
+    \const{IPRIO\_WHO\_USER}    & \type{uid\_t} & utente\\
+    \hline
+  \end{tabular}
+  \caption{Legenda del valore dell'argomento \param{which} e del tipo
+    dell'argomento \param{who} delle funzioni \func{ioprio\_get} e
+    \func{ioprio\_set} per le tre possibili scelte.}
+  \label{tab:ioprio_args}
+\end{table}
+
+In caso di successo \func{ioprio\_get} restituisce un intero positivo che
+esprime il valore della priorità di I/O, questo valore è una maschera binaria
+composta da due parti, una che esprime la \textsl{classe} di scheduling di I/O
+del processo, l'altra che esprime, quando la classe di scheduling lo prevede,
+la priorità del processo all'interno della classe stessa. Questo stesso
+formato viene utilizzato per indicare il valore della priorità da impostare
+con l'argomento \param{ioprio} di \func{ioprio\_set}.
+
+Per la gestione dei valori che esprimono le priorità di I/O sono state
+definite delle opportune macro di preprocessore, riportate in
+tab.~\ref{tab:IOsched_class_macro}. I valori delle priorità si ottengono o si
+impostano usando queste macro.  Le prime due si usano con il valore restituito
+da \func{ioprio\_get} e per ottenere rispettivamente la classe di
+scheduling\footnote{restituita dalla macro con i valori di
+  tab.~\ref{tab:IOsched_class}.} e l'eventuale valore della priorità. La terza
+macro viene invece usata per creare un valore di priorità da usare come
+argomento di \func{ioprio\_set} per eseguire una impostazione.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Macro} & \textbf{Significato}\\
+    \hline
+    \hline
+    \macro{IOPRIO\_PRIO\_CLASS}\texttt{(\textit{value})}
+                                & dato il valore di una priorità come
+                                  restituito da \func{ioprio\_get} estrae il
+                                  valore della classe.\\
+    \macro{IOPRIO\_PRIO\_DATA}\texttt{(\textit{value})}
+                                & dato il valore di una priorità come
+                                  restituito da \func{ioprio\_get} estrae il
+                                  valore della priorità.\\
+    \macro{IOPRIO\_PRIO\_VALUE}\texttt{(\textit{class},\textit{prio})}
+                                & dato un valore di priorità ed una classe
+                                  ottiene il valore numerico da passare a
+                                  \func{ioprio\_set}.\\
+    \hline
+  \end{tabular}
+  \caption{Le macro per la gestione dei valori numerici .}
+  \label{tab:IOsched_class_macro}
+\end{table}
+
+Le classi di scheduling previste dallo scheduler CFQ sono tre, e ricalcano tre
+diverse modalità di distribuzione delle risorse analoghe a quelle già adottate
+anche nel funzionamento dello scheduler del processore. Ciascuna di esse è
+identificata tramite una opportuna costante, secondo quanto riportato in
+tab.~\ref{tab:IOsched_class}.
+
+La classe di priorità più bassa è \const{IOPRIO\_CLASS\_IDLE}; i processi in
+questa classe riescono ad accedere a disco soltanto quando nessun altro
+processo richiede l'accesso. Occorre pertanto usarla con molta attenzione,
+perché un processo in questa classe può venire completamente bloccato quando
+ci sono altri processi in una qualunque delle altre due classi che stanno
+accedendo al disco. Quando si usa questa classe non ha senso indicare un
+valore di priorità, dato che in questo caso non esiste nessuna gerarchia e la
+priorità è identica, la minima possibile, per tutti i processi.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Classe}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IOPRIO\_CLASS\_RT}  & Scheduling di I/O \textit{real time}.\\
+    \const{IOPRIO\_CLASS\_BE}  & Scheduling di I/O ordinario.\\ 
+    \const{IOPRIO\_CLASS\_IDLE}& Scheduling di I/O di priorità minima.\\
+    \hline
+  \end{tabular}
+  \caption{Costanti che identificano le classi di scheduling di I/O.}
+  \label{tab:IOsched_class}
+\end{table}
 
+La seconda classe di priorità di I/O è \const{IOPRIO\_CLASS\_BE} (il nome sta
+per \textit{best-effort}) che è quella usata ordinariamente da tutti
+processi. In questo caso esistono priorità diverse che consentono di
+assegnazione di una maggiore banda passante nell'accesso a disco ad un
+processo rispetto agli altri, con meccanismo simile a quello dei valori di
+\textit{nice} in cui si evita che un processo a priorità più alta possa
+bloccare indefinitamente quelli a priorità più bassa. In questo caso però le
+diverse priorità sono soltanto otto, indicate da un valore numerico fra 0 e 7
+e come per \textit{nice} anche in questo caso un valore più basso indica una
+priorità maggiore. 
+
+
+Infine la classe di priorità di I/O \textit{real-time}
+\const{IOPRIO\_CLASS\_RT} ricalca le omonime priorità di processore: un
+processo in questa classe ha sempre la precedenza nell'accesso a disco
+rispetto a tutti i processi delle altre classi e di un processo nella stessa
+classe ma con priorità inferiore, ed è pertanto in grado di bloccare
+completamente tutti gli altri. Anche in questo caso ci sono 8 priorità diverse
+con un valore numerico fra 0 e 7, con una priorità più elevata per valori più
+bassi.
+
+In generale nel funzionamento ordinario la priorità di I/O di un processo
+viene impostata in maniera automatica nella classe \const{IOPRIO\_CLASS\_BE}
+con un valore ottenuto a partire dal corrispondente valore di \textit{nice}
+tramite la formula: $\mathtt{\mathit{prio}}=(\mathtt{\mathit{nice}}+20)/5$. Un
+utente ordinario può modificare con \func{ioprio\_set} soltanto le priorità
+dei processi che gli appartengono,\footnote{per la modifica delle priorità di
+  altri processi occorrono privilegi amministrativi, ed in particolare la
+  capacità \const{CAP\_SYS\_NICE} (vedi sez.~\ref{sec:proc_capabilities}).}
+cioè quelli il cui user-ID reale corrisponde all'user-ID reale o effettivo del
+chiamante. Data la possibilità di ottenere un blocco totale dello stesso, solo
+l'amministratore\footnote{o un processo con la capacità
+  \const{CAP\_SYS\_ADMIN} (vedi sez.~\ref{sec:proc_capabilities}).} può
+impostare un processo ad una priorità di I/O nella classe
+\const{IOPRIO\_CLASS\_RT} o \const{IOPRIO\_CLASS\_IDLE}.
 
-%TODO trattare le priorità di I/O
-% vedi man ioprio_set e Documentation/block/ioprio.txt
 
 %TODO trattare le funzionalità per il NUMA
 % vedi man numa e le pagine di manuale relative
@@ -3202,7 +3386,8 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso
 % LocalWords:  CONTINUED sources forking Spawned successfully executing exiting
 % LocalWords:  next cat for COMMAND pts bash defunct TRAPPED DUMPED Killable PR
 % LocalWords:  SIGKILL static RLIMIT preemption PREEMPT VOLUNTARY IDLE RTPRIO
-% LocalWords:  Completely Fair compat Uniform
+% LocalWords:  Completely Fair compat Uniform CFQ Queuing elevator dev cfq RT
+% LocalWords:  Documentation block syscall ioprio IPRIO CLASS class best effort
 
 %%% Local Variables: 
 %%% mode: latex