Priorita' di I/O, ancora materiale.
[gapil.git] / prochand.tex
index 510e69ac8f11c3262149395d7b955f753e1c93cc..d649018d0e2001b50b652529ae2ad6ff23c5b1d6 100644 (file)
@@ -631,7 +631,7 @@ comune dopo l'esecuzione di una \func{fork} 
 \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
 \item il valori di \textit{nice}, le priorità real-time e le affinità di
   processore (vedi sez.~\ref{sec:proc_sched_stand},
 \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
 \item il valori di \textit{nice}, le priorità real-time e le affinità di
   processore (vedi sez.~\ref{sec:proc_sched_stand},
-  sez.~\ref{sec:proc_real_time} e sez.\ref{sec:proc_sched_multiprocess});
+  sez.~\ref{sec:proc_real_time} e sez.~\ref{sec:proc_sched_multiprocess});
 \item le variabili di ambiente (vedi sez.~\ref{sec:proc_environ}).
 \end{itemize*}
 Le differenze fra padre e figlio dopo la \func{fork} invece sono:
 \item le variabili di ambiente (vedi sez.~\ref{sec:proc_environ}).
 \end{itemize*}
 Le differenze fra padre e figlio dopo la \func{fork} invece sono:
@@ -648,7 +648,6 @@ Le differenze fra padre e figlio dopo la \func{fork} invece sono:
   per il figlio vengono cancellati.
 \end{itemize*}
 
   per il figlio vengono cancellati.
 \end{itemize*}
 
-
 Una seconda funzione storica usata per la creazione di un nuovo processo è
 \func{vfork}, che è esattamente identica a \func{fork} ed ha la stessa
 semantica e gli stessi errori; la sola differenza è che non viene creata la
 Una seconda funzione storica usata per la creazione di un nuovo processo è
 \func{vfork}, che è esattamente identica a \func{fork} ed ha la stessa
 semantica e gli stessi errori; la sola differenza è che non viene creata la
@@ -666,8 +665,9 @@ venne introdotta in BSD per migliorare le prestazioni.
 
 Dato che Linux supporta il \itindex{copy~on~write} \textit{copy on write} la
 perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
 
 Dato che Linux supporta il \itindex{copy~on~write} \textit{copy on write} la
 perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
-funzione (che resta un caso speciale della system call \func{\_\_clone}) è
-deprecato; per questo eviteremo di trattarla ulteriormente.
+funzione, che resta un caso speciale della system call \func{clone} (che
+tratteremo in dettaglio in sez.~\ref{sec:process_clone}) è deprecato; per
+questo eviteremo di trattarla ulteriormente.
 
 
 \subsection{La conclusione di un processo}
 
 
 \subsection{La conclusione di un processo}
@@ -742,8 +742,6 @@ che sia cos
 terminato; si potrebbe avere cioè quello che si chiama un processo
 \textsl{orfano}. 
 
 terminato; si potrebbe avere cioè quello che si chiama un processo
 \textsl{orfano}. 
 
-% TODO verificare il reparenting
-
 Questa complicazione viene superata facendo in modo che il processo orfano
 venga \textsl{adottato} da \cmd{init}. Come già accennato quando un processo
 termina, il kernel controlla se è il padre di altri processi in esecuzione: in
 Questa complicazione viene superata facendo in modo che il processo orfano
 venga \textsl{adottato} da \cmd{init}. Come già accennato quando un processo
 termina, il kernel controlla se è il padre di altri processi in esecuzione: in
@@ -2087,16 +2085,16 @@ compila con il flag \cmd{-ansi}, 
 scrivere codice portabile.
 
  
 scrivere codice portabile.
 
  
-\section{La gestione della priorità di esecuzione}
+\section{La gestione della priorità dei processi}
 \label{sec:proc_priority}
 
 In questa sezione tratteremo più approfonditamente i meccanismi con il quale
 lo \itindex{scheduler} \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
 \label{sec:proc_priority}
 
 In questa sezione tratteremo più approfonditamente i meccanismi con il quale
 lo \itindex{scheduler} \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.
+gestione. Tratteremo infine anche le altre priorità dei processi (come quelle
+per l'accesso a disco) divenute disponibili con i kernel più recenti.
 
 
-% TODO: rivedere alla luce degli aggiornamenti del 2.6 (man sched_setscheduler)
 
 \subsection{I meccanismi di \textit{scheduling}}
 \label{sec:proc_sched}
 
 \subsection{I meccanismi di \textit{scheduling}}
 \label{sec:proc_sched}
@@ -2148,21 +2146,21 @@ fintanto che esso si trova in uno qualunque degli altri stati.
 \begin{table}[htb]
   \footnotesize
   \centering
 \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
     \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 
     \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
     \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
     \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
@@ -2172,7 +2170,8 @@ fintanto che esso si trova in uno qualunque degli altri stati.
                                     2.6.25, sostanzialmente identico
                                     all'\textbf{Uninterrutible Sleep} con la
                                     sola differenza che il processo può
                                     2.6.25, sostanzialmente identico
                                     all'\textbf{Uninterrutible Sleep} con la
                                     sola differenza che il processo può
-                                    terminato (con \const{SIGKILL}).\\ 
+                                    terminato con \const{SIGKILL} (usato per
+                                    lo più per NFS).\\ 
     \hline
   \end{tabular}
   \caption{Elenco dei possibili stati di un processo in Linux, nella colonna
     \hline
   \end{tabular}
   \caption{Elenco dei possibili stati di un processo in Linux, nella colonna
@@ -2181,8 +2180,6 @@ fintanto che esso si trova in uno qualunque degli altri stati.
   \label{tab:proc_proc_states}
 \end{table}
 
   \label{tab:proc_proc_states}
 \end{table}
 
-% TODO nel 2.6.25 è stato aggiunto TASK_KILLABLE, da capire dova va messo.
-
 Si deve quindi tenere presente che l'utilizzo della CPU è soltanto una delle
 risorse che sono necessarie per l'esecuzione di un programma, e a seconda
 dello scopo del programma non è detto neanche che sia la più importante (molti
 Si deve quindi tenere presente che l'utilizzo della CPU è soltanto una delle
 risorse che sono necessarie per l'esecuzione di un programma, e a seconda
 dello scopo del programma non è detto neanche che sia la più importante (molti
@@ -2768,13 +2765,22 @@ real-time, e serve a far s
 da essere rimesso in coda alla lista dei processi con la stessa priorità per
 permettere ad un altro di essere eseguito; se però il processo è l'unico ad
 essere presente sulla coda l'esecuzione non sarà interrotta. In genere usano
 da essere rimesso in coda alla lista dei processi con la stessa priorità per
 permettere ad un altro di essere eseguito; se però il processo è l'unico ad
 essere presente sulla coda l'esecuzione non sarà interrotta. In genere usano
-questa funzione i processi in modalità \textit{fifo}, per permettere
+questa funzione i processi con politica \const{SCHED\_FIFO}, per permettere
 l'esecuzione degli altri processi con pari priorità quando la sezione più
 urgente è finita.
 
 l'esecuzione degli altri processi con pari priorità quando la sezione più
 urgente è finita.
 
-% TODO: con il 2.6.23 il comportamento è stato leggermente modificato ed è
-% stato introdotto /proc/sys/kernel/sched_compat_yield da mettere a 1 per aver
-% la compatibilità con il precedente.
+La funzione può essere utilizzata anche con processi che usano lo scheduling
+ordinario, ma in questo caso il comportamento non è ben definito, e dipende
+dall'implementazione. Fino al kernel 2.6.23 questo comportava che i processi
+venissero messi in fondo alla coda di quelli attivi, con la possibilità di
+essere rimessi in esecuzione entro breve tempo, con l'introduzione del
+\textit{Completely Fair Scheduler} questo comportamento è cambiato ed un
+processo che chiama la funzione viene inserito nella lista dei processi
+inattivo, con un tempo molto maggiore.\footnote{è comunque possibile
+  ripristinare un comportamento analogo al precedente scrivendo il valore 1
+  nel file \texttt{/proc/sys/kernel/sched\_compat\_yield}.}
+
+
 
 \subsection{Il controllo dello \textit{scheduler} per i sistemi
   multiprocessore}
 
 \subsection{Il controllo dello \textit{scheduler} per i sistemi
   multiprocessore}
@@ -2884,8 +2890,8 @@ utilizzato per un compito importante (ad esempio per applicazioni real-time o
 la cui risposta è critica) e si vuole la massima velocità, con questa
 interfaccia diventa possibile selezionare gruppi di processori utilizzabili in
 maniera esclusiva.  Lo stesso dicasi quando l'accesso a certe risorse (memoria
 la cui risposta è critica) e si vuole la massima velocità, con questa
 interfaccia diventa possibile selezionare gruppi di processori utilizzabili in
 maniera esclusiva.  Lo stesso dicasi quando l'accesso a certe risorse (memoria
-o periferiche) può avere un costo diverso a seconda del processore (come
-avviene nelle architetture NUMA).
+o periferiche) può avere un costo diverso a seconda del processorecome
+avviene nelle architetture NUMA (\textit{Non-Uniform Memory Access}).
 
 Infine se un gruppo di processi accede alle stesse risorse condivise (ad
 esempio una applicazione con più \itindex{thread} \textit{thread}) può avere
 
 Infine se un gruppo di processi accede alle stesse risorse condivise (ad
 esempio una applicazione con più \itindex{thread} \textit{thread}) può avere
@@ -2967,6 +2973,200 @@ non avranno alcun risultato effettivo.
 \itindend{CPU~affinity}
 
 
 \itindend{CPU~affinity}
 
 
+\subsection{Le priorità per le operazioni di I/O}
+\label{sec:io_priority}
+
+A lungo l'unica priorità usata per i processi è stata quella relativa
+all'assegnazione dell'uso del processore. Ma il processore non è l'unica
+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 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 librerie del C per queste due funzioni occorrerà invocarle
+tramite la funzione \func{syscall} (come illustrato in
+sez.~\ref{sec:intro_syscall}). La prima delle due è \funcd{ioprio\_get}, che
+consente di leggere la priorità; il suo prototipo è:
+\begin{prototype}{linux/ioprio.h}
+  {int ioprio\_get(int which, int who)} 
+  Legge la priorità di I/O.
+  
+  \bodydesc{La funzione ritorna un valore positivo 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. 
+  \end{errlist} }
+\end{prototype}
+
+La funzione legge 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 analoghi argomenti di \func{getpriority} e \func{setpriority};
+in questo caso vengono però per \param{which} sono state definite delle
+costanti apposite, illustrate in tab.~\ref{tab:ioprio_args}. A seconda dei
+valori è così possibile leggere delle priorità per il singolo processo, per i
+processi di un \textit{process group} (tratteremo questo argomento in
+sez.~\ref{sec:sess_proc_group}) o per 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}
+
+Gli stessi valori possono essere utilizzati anche quando si vuole eseguire
+l'impostazione di una priorità di I/O; in tal caso si deve usare la funzione
+\funcd{ioprio\_set}, il cui prototipo è:
+\begin{prototype}{linux/ioprio.h}
+  {int ioprio\_set(int which, int who, int ioprio)} 
+
+  Imposta la priorità di I/O.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di
+    errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{EPERM}] non si hanno i privilegi per eseguire
+      l'impostazione. 
+  \end{errlist}
+  oltre a \errcode{EINVAL} e \errcode{ESRCH} con lo stesso significato di
+  \func{ioprio\_get}.  }
+\end{prototype}
+
+
+La funzione in caso di successo restituisce un intero positivo che esprime il
+valore della priorità di I/O, questo è composto di due parti, una che esprime
+la cosiddetta \textsl{classe} di scheduling, l'altro che esprime la priorità
+all'interno della classe stessa. Le classi previste dallo scheduler CFQ sono
+tre, identificate da altrettanti costanti, riportate in
+tab.~\ref{tab:IOsched_class}.
+
+\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 tre classi ricalcano i concetti presenti anche nello scheduler della CPU;
+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 di priorità più alta che stanno accedendo al
+disco; in questa classe non esistono valori di priorità, tutti i processi
+hanno la stessa priorità, che è la minima possibile. 
+
+La classe per le priorità ordinarie è \const{IOPRIO\_CLASS\_BE} (il nome sta
+per \textit{best-effort}) che è quella usata di default per tutti processi; in
+questo caso esistono delle priorità all'interno della classe che corrispondono
+all'assegnazione ad un processo di una maggiore banda passante nell'accesso a
+disco rispetto agli altri senza però che questo possa bloccare indefinitamente
+l'accesso agli altri; con un concetto simile a quello dei valori di
+\textit{nice} per le priorità di processore. In questo caso esistono però
+soltanto otto diverse priorità, indicate da un valore numerico fra 0 e
+7,\footnote{come per \textit{nice} anche in questo caso un valore più basso
+  indica una priorità maggiore.} che sono assegnate ai singoli processi in
+maniera automatica a partire dal loro valore di \textit{nice}.\footnote{come
+  riportato nella documentazione il valore della priorità viene calcolato con
+  la formula: $\mathtt{prio}=(\mathtt{nice}+20)/5$.}
+
+Infine la classe di priorità \textit{real-time} \const{IOPRIO\_CLASS\_RT}
+ricalca le analoghe priorità di processore: un processo in questa classe ha
+sempre la precedenza nell'accesso a disco rispetto a tutti i processi di
+priorità inferiore, e pertanto è in grado di bloccare completamente 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 inferiori.
+
+Per manipolare il valori delle priorità di I/O sono state approntate delle
+opportune macro, in grado di estrarre i valori di priorità e la classe dai
+valori restituiti da \func{ioprio\_get} e di creare da questi un opportuno
+valore da passare a \func{ioprio\_set}, che si sono riportate in
+tab.~\ref{tab:IOsched_class_macro}. 
+
+\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 un priorità come
+                                  restituito da \func{ioprio\_get} ottiene il
+                                  valore della classe.\\
+    \macro{IOPRIO\_PRIO\_DATA}\texttt{(\textit{value})}
+                                & dato il valore di un priorità come
+                                  restituito da \func{ioprio\_get} ottiene 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}
+
+
+
+%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
+% vedere anche dove metterle...
 
 \section{Problematiche di programmazione multitasking}
 \label{sec:proc_multi_prog}
 
 \section{Problematiche di programmazione multitasking}
 \label{sec:proc_multi_prog}
@@ -3176,9 +3376,11 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso
 % LocalWords:  infop ALL WEXITED WSTOPPED WNOWAIT signo CLD EXITED KILLED page
 % LocalWords:  CONTINUED sources forking Spawned successfully executing exiting
 % LocalWords:  next cat for COMMAND pts bash defunct TRAPPED DUMPED Killable PR
 % LocalWords:  infop ALL WEXITED WSTOPPED WNOWAIT signo CLD EXITED KILLED page
 % 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
+% LocalWords:  SIGKILL static RLIMIT preemption PREEMPT VOLUNTARY IDLE RTPRIO
+% LocalWords:  Completely Fair compat Uniform CFQ Queuing elevator dev cfq RT
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
+% LocalWords:  Documentation block syscall ioprio IPRIO CLASS