Aggiornamento al 2010 delle note di copyright
[gapil.git] / prochand.tex
index 27d7d064b490e5f7736568c417d4593fc1475829..7fe061ffcb81b5d369b937932b4b05c5fa44438b 100644 (file)
@@ -1,6 +1,6 @@
 %% prochand.tex
 %%
-%% Copyright (C) 2000-2009 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2010 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Un preambolo",
@@ -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
@@ -181,11 +181,11 @@ essere posto in esecuzione fino alla successiva invocazione.
 \subsection{Una panoramica sulle funzioni fondamentali}
 \label{sec:proc_handling_intro}
 
-In un sistema unix-like i processi vengono sempre creati da altri processi
-tramite la funzione \func{fork}; il nuovo processo (che viene chiamato
-\textsl{figlio}) creato dalla \func{fork} è una copia identica del processo
-processo originale (detto \textsl{padre}), ma ha un nuovo \acr{pid} e viene
-eseguito in maniera indipendente (le differenze fra padre e figlio sono
+Tradizionalmente in un sistema unix-like i processi vengono sempre creati da
+altri processi tramite la funzione \func{fork}; il nuovo processo (che viene
+chiamato \textsl{figlio}) creato dalla \func{fork} è una copia identica del
+processo processo originale (detto \textsl{padre}), ma ha un nuovo \acr{pid} e
+viene eseguito in maniera indipendente (le differenze fra padre e figlio sono
 affrontate in dettaglio in sez.~\ref{sec:proc_fork}).
 
 Se si vuole che il processo padre si fermi fino alla conclusione del processo
@@ -308,10 +308,18 @@ affrontato in dettaglio in sez.~\ref{sec:proc_perms}.
 \label{sec:proc_fork}
 
 La funzione \funcd{fork} è la funzione fondamentale della gestione dei
-processi: come si è detto l'unico modo di creare un nuovo processo è
-attraverso l'uso di questa funzione, essa quindi riveste un ruolo centrale
-tutte le volte che si devono scrivere programmi che usano il multitasking.  Il
-prototipo della funzione è:
+processi: come si è detto tradizionalmente l'unico modo di creare un nuovo
+processo era attraverso l'uso di questa funzione,\footnote{in realtà oggi la
+  system call usata più comunemente da Linux per creare nuovi processi è
+  \func{clone} (vedi \ref{sec:process_clone}) , anche perché a partire dalle
+  \acr{glibc} 2.3.3 non viene più usata la system call originale, ma la stessa
+  \func{fork} viene implementata tramite \func{clone}, cosa che consente una
+  migliore interazione coi \textit{thread}.} essa quindi riveste un ruolo
+centrale tutte le volte che si devono scrivere programmi che usano il
+multitasking.\footnote{oggi questa rilevanza, con la diffusione dell'uso dei
+  \textit{thread} che tratteremo al cap.~\ref{cha:threads}, è in parte minore,
+  ma \func{fork} resta comunque la funzione principale per la creazione di
+  processi.} Il prototipo della funzione è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{unistd.h} 
@@ -489,12 +497,15 @@ fosse stato creato solo per eseguire una \func{exec}, in tal caso infatti si
 invocherebbe un altro programma scartando completamente lo spazio degli
 indirizzi, rendendo superflua la copia della memoria modificata dal padre.
 
+% TODO spiegare l'ulteriore cambiamento in ponte con il 2.6.32, che fa girare
+% prima il padre per questioni di caching nella CPU
+
 Eseguendo sempre per primo il figlio la \func{exec} verrebbe effettuata subito
 avendo così la certezza che il \itindex{copy~on~write} \textit{copy on write}
 viene utilizzato solo quando necessario. Quanto detto in precedenza vale
 allora soltanto per i kernel fino al 2.4; per mantenere la portabilità è però
 opportuno non fare affidamento su questo comportamento, che non si riscontra
-in altri Unix e nelle versioni del kernel precendenti a quella indicata.
+in altri Unix e nelle versioni del kernel precedenti a quella indicata.
 
 Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
 processi completamente separati, le modifiche delle variabili nei processi
@@ -596,7 +607,7 @@ file senza una qualche forma di sincronizzazione in quanto, come visto anche
 con il nostro esempio, le varie scritture risulteranno mescolate fra loro in
 una sequenza impredicibile. Per questo le modalità con cui in genere si usano
 i file dopo una \func{fork} sono sostanzialmente due:
-\begin{enumerate}
+\begin{enumerate*}
 \item Il processo padre aspetta la conclusione del figlio. In questo caso non
   è necessaria nessuna azione riguardo ai file, in quanto la sincronizzazione
   della posizione corrente dopo eventuali operazioni di lettura e scrittura
@@ -604,7 +615,7 @@ i file dopo una \func{fork} sono sostanzialmente due:
 \item L'esecuzione di padre e figlio procede indipendentemente. In questo caso
   ciascuno dei due processi deve chiudere i file che non gli servono una volta
   che la \func{fork} è stata eseguita, per evitare ogni forma di interferenza.
-\end{enumerate}
+\end{enumerate*}
 
 Oltre ai file aperti i processi figli ereditano dal padre una serie di altre
 proprietà; la lista dettagliata delle proprietà che padre e figlio hanno in
@@ -622,32 +633,48 @@ comune dopo l'esecuzione di una \func{fork} 
   ed il terminale di controllo (vedi sez.~\ref{sec:sess_proc_group});
 \item la directory di lavoro e la directory radice (vedi
   sez.~\ref{sec:file_work_dir} e sez.~\ref{sec:file_chroot});
-\item la maschera dei permessi di creazione (vedi
+\item la maschera dei permessi di creazione dei file (vedi
   sez.~\ref{sec:file_perm_management});
 \item la maschera dei segnali bloccati (vedi sez.~\ref{sec:sig_sigmask}) e le
   azioni installate (vedi sez.~\ref{sec:sig_gen_beha});
 \item i segmenti di memoria condivisa agganciati al processo (vedi
   sez.~\ref{sec:ipc_sysv_shm});
 \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
-\item le priorità real-time e le affinità di processore (vedi
-  sez.~\ref{sec:proc_real_time} e sez.\ref{sec:proc_sched_multiprocess});
+\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});
 \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:
+Le differenze fra padre e figlio dopo la \func{fork} invece sono:\footnote{a
+  parte le ultime quattro, relative a funzionalità specifiche di Linux, le
+  altre sono esplicitamente menzionate dallo standard POSIX.1-2001.}
 \begin{itemize*}
 \item il valore di ritorno di \func{fork};
-\item il \acr{pid} (\textit{process id});
+\item il \acr{pid} (\textit{process id}), assegnato ad un nuovo valore univoco;
 \item il \acr{ppid} (\textit{parent process id}), quello del figlio viene
   impostato al \acr{pid} del padre;
-\item i valori dei tempi di esecuzione della struttura \struct{tms} (vedi
-  sez.~\ref{sec:sys_cpu_times}) che nel figlio sono posti a zero;
-\item i \textit{lock} sui file (vedi sez.~\ref{sec:file_locking}), che non
-  vengono ereditati dal figlio;
-\item gli allarmi ed i segnali pendenti (vedi sez.~\ref{sec:sig_gen_beha}), che
-  per il figlio vengono cancellati.
+\item i valori dei tempi di esecuzione (vedi sez.~\ref{sec:sys_cpu_times}) e
+  delle risorse usate (vedi sez.~\ref{sec:sys_resource_use}), che nel figlio
+  sono posti a zero;
+\item i \textit{lock} sui file (vedi sez.~\ref{sec:file_locking}) e sulla
+  memoria (vedi sez.~\ref{sec:proc_mem_lock}), che non vengono ereditati dal
+  figlio;
+\item gli allarmi (vedi sez.~\ref{sec:sig_alarm_abort}) ed i segnali pendenti
+  (vedi sez.~\ref{sec:sig_gen_beha}), che per il figlio vengono cancellati.
+\item le operazioni di I/O asincrono in corso (vedi
+  sez.~\ref{sec:file_asyncronous_io}) che non vengono ereditate dal figlio;
+\item gli aggiustamenti fatti dal padre ai semafori con \func{semop} (vedi
+  sez.~\ref{sec:ipc_sysv_sem}).
+\item le notifiche sui cambiamenti delle directory con \textit{dnotify} (vedi
+  sez.~\ref{sec:sig_notification}), che non vengono ereditate dal figlio;
+\item le mappature di memoria marcate come \const{MADV\_DONTFORK} (vedi
+  sez.~\ref{sec:file_memory_map}) che non vengono ereditate dal figlio;
+\item l'impostazione con \func{prctl} (vedi sez.~\ref{sec:prctl_xxx}) che
+  notifica al figlio la terminazione del padre viene cancellata;
+\item il segnale di terminazione del figlio è sempre \const{SIGCHLD} anche
+  qualora nel padre fosse stato modificato (vedi sez.~\ref{sec:process_clone}). 
 \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
@@ -665,8 +692,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
-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}
@@ -695,7 +723,7 @@ Qualunque sia la modalit
 comunque una serie di operazioni: chiude tutti i file aperti, rilascia la
 memoria che stava usando, e così via; l'elenco completo delle operazioni
 eseguite alla chiusura di un processo è il seguente:
-\begin{itemize}
+\begin{itemize*}
 \item tutti i file descriptor sono chiusi;
 \item viene memorizzato lo stato di terminazione del processo;
 \item ad ogni processo figlio viene assegnato un nuovo padre (in genere
@@ -710,7 +738,7 @@ eseguite alla chiusura di un processo 
     group} ciascun membro del gruppo viene bloccato, e poi gli vengono
   inviati in successione i segnali \const{SIGHUP} e \const{SIGCONT}
   (vedi ancora sez.~\ref{sec:sess_ctrl_term}).
-\end{itemize}
+\end{itemize*}
 
 Oltre queste operazioni è però necessario poter disporre di un meccanismo
 ulteriore che consenta di sapere come la terminazione è avvenuta: dato che in
@@ -741,8 +769,6 @@ che sia cos
 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
@@ -949,19 +975,14 @@ sono riportate anche le costanti definite per indicare alcuni di essi.
 
 Il comportamento di \func{waitpid} può inoltre essere modificato passando alla
 funzione delle opportune opzioni tramite l'argomento \param{options}; questo
-deve essere specificato come maschera binaria dei flag riportati in
-tab.~\ref{tab:proc_waitpid_options},\footnote{oltre a queste in Linux sono
-  previste del altre opzioni non standard, relative al comportamento con i
-  \itindex{thread} \textit{thread}, che riprenderemo in
-  sez.~\ref{sec:thread_xxx}.} che possono essere combinati fra loro con un OR
-aritmetico.
-
-L'uso dell'opzione \const{WNOHANG} consente di prevenire il blocco della
-funzione qualora nessun figlio sia uscito (o non si siano verificate le altre
-condizioni per l'uscita della funzione); in tal caso la funzione ritornerà un
-valore nullo anziché positivo.\footnote{anche in questo caso un valore
-  positivo indicherà il \acr{pid} del processo di cui si è ricevuto lo stato
-  ed un valore negativo un errore.}
+deve essere specificato come maschera binaria dei flag riportati nella prima
+parte in tab.~\ref{tab:proc_waitpid_options} che possono essere combinati fra
+loro con un OR aritmetico. Nella seconda parte della stessa tabella si sono
+riportati anche alcuni valori non standard specifici di Linux, che consentono
+un controllo più dettagliato per i processi creati con la system call generica
+\func{clone} (vedi sez.~\ref{sec:process_clone}) usati principalmente per la
+gestione della terminazione dei \itindex{thread} \textit{thread} (vedi
+sez.~\ref{sec:thread_xxx}).
 
 \begin{table}[!htb]
   \centering
@@ -977,6 +998,14 @@ valore nullo anzich
     \const{WCONTINUED}& Ritorna anche quando un processo figlio che era stato
                         fermato ha ripreso l'esecuzione.\footnotemark \\
     \hline
+    \const{\_\_WCLONE}& Attende solo per i figli creati con \func{clone},
+                        vale a dire processi che non emettono nessun segnale
+                        o emettono un segnale diverso da \const{SIGCHL} alla
+                        terminazione. \\
+    \const{\_\_WALL}  & Attende per qualunque processo figlio. \\
+    \const{\_\_WNOTHREAD}& Non attende per i figli di altri \textit{thread}
+                        dello stesso gruppo. \\
+    \hline
   \end{tabular}
   \caption{Costanti che identificano i bit dell'argomento \param{options}
     della funzione \func{waitpid}.} 
@@ -985,6 +1014,13 @@ valore nullo anzich
 
 \footnotetext{disponibile solo a partire dal kernel 2.6.10.}
 
+L'uso dell'opzione \const{WNOHANG} consente di prevenire il blocco della
+funzione qualora nessun figlio sia uscito (o non si siano verificate le altre
+condizioni per l'uscita della funzione); in tal caso la funzione ritornerà un
+valore nullo anziché positivo.\footnote{anche in questo caso un valore
+  positivo indicherà il \acr{pid} del processo di cui si è ricevuto lo stato
+  ed un valore negativo un errore.}
+
 Le altre due opzioni \const{WUNTRACED} e \const{WCONTINUED} consentono
 rispettivamente di tracciare non la terminazione di un processo, ma il fatto
 che esso sia stato fermato, o fatto ripartire, e sono utilizzate per la
@@ -1033,34 +1069,6 @@ modo, indipendentemente dal fatto \const{SIGCHLD} sia ignorato o meno:
 attendono la terminazione di un processo figlio e ritornano il relativo
 \acr{pid} e lo stato di terminazione nell'argomento \param{status}.
 
-In generale in un programma non si vuole essere forzati ad attendere la
-conclusione di un processo figlio per proseguire l'esecuzione, specie se tutto
-questo serve solo per leggerne lo stato di chiusura (ed evitare eventualmente
-la presenza di \index{zombie} \textit{zombie}). Per questo la modalità più
-comune di chiamare queste funzioni è quella di utilizzarle all'interno di un
-\textit{signal handler} (vedremo un esempio di come gestire \const{SIGCHLD}
-con i segnali in sez.~\ref{sec:sig_example}). In questo caso infatti, dato che
-il segnale è generato dalla terminazione di un figlio, avremo la certezza che
-la chiamata a \func{waitpid} non si bloccherà.
-
-Come accennato sia \func{wait} che \func{waitpid} restituiscono lo stato di
-terminazione del processo tramite il puntatore \param{status} (se non
-interessa memorizzare lo stato si può passare un puntatore nullo). Il valore
-restituito da entrambe le funzioni dipende dall'implementazione, ma
-tradizionalmente alcuni bit (in genere 8) sono riservati per memorizzare lo
-stato di uscita, e altri per indicare il segnale che ha causato la
-terminazione (in caso di conclusione anomala), uno per indicare se è stato
-generato un \itindex{core~dump} \textit{core dump}, ecc.\footnote{le
-  definizioni esatte si possono trovare in \file{<bits/waitstatus.h>} ma
-  questo file non deve mai essere usato direttamente, esso viene incluso
-  attraverso \file{<sys/wait.h>}.}
-
-Lo standard POSIX.1 definisce una serie di macro di preprocessore da usare per
-analizzare lo stato di uscita. Esse sono definite sempre in
-\file{<sys/wait.h>} ed elencate in tab.~\ref{tab:proc_status_macro} (si tenga
-presente che queste macro prendono come parametro la variabile di tipo
-\ctyp{int} puntata da \param{status}).
-
 \begin{table}[!htb]
   \centering
   \footnotesize
@@ -1108,17 +1116,48 @@ presente che queste macro prendono come parametro la variabile di tipo
   \label{tab:proc_status_macro}
 \end{table}
 
-\footnotetext[18]{questa macro non è definita dallo standard POSIX.1-2001, ma è
+\footnotetext[20]{questa macro non è definita dallo standard POSIX.1-2001, ma è
   presente come estensione sia in Linux che in altri Unix, deve essere
   pertanto utilizzata con attenzione (ad esempio è il caso di usarla in un
   blocco \texttt{\#ifdef WCOREDUMP ... \#endif}.}
 
 \footnotetext{è presente solo a partire dal kernel 2.6.10.}
 
+In generale in un programma non si vuole essere forzati ad attendere la
+conclusione di un processo figlio per proseguire l'esecuzione, specie se tutto
+questo serve solo per leggerne lo stato di chiusura (ed evitare eventualmente
+la presenza di \index{zombie} \textit{zombie}). 
+
+Per questo la modalità più comune di chiamare queste funzioni è quella di
+utilizzarle all'interno di un \textit{signal handler} (vedremo un esempio di
+come gestire \const{SIGCHLD} con i segnali in sez.~\ref{sec:sig_example}). In
+questo caso infatti, dato che il segnale è generato dalla terminazione di un
+figlio, avremo la certezza che la chiamata a \func{waitpid} non si bloccherà.
+
+Come accennato sia \func{wait} che \func{waitpid} restituiscono lo stato di
+terminazione del processo tramite il puntatore \param{status} (se non
+interessa memorizzare lo stato si può passare un puntatore nullo). Il valore
+restituito da entrambe le funzioni dipende dall'implementazione, ma
+tradizionalmente alcuni bit (in genere 8) sono riservati per memorizzare lo
+stato di uscita, e altri per indicare il segnale che ha causato la
+terminazione (in caso di conclusione anomala), uno per indicare se è stato
+generato un \itindex{core~dump} \textit{core dump}, ecc.\footnote{le
+  definizioni esatte si possono trovare in \file{<bits/waitstatus.h>} ma
+  questo file non deve mai essere usato direttamente, esso viene incluso
+  attraverso \file{<sys/wait.h>}.}
+
+Lo standard POSIX.1 definisce una serie di macro di preprocessore da usare per
+analizzare lo stato di uscita. Esse sono definite sempre in
+\file{<sys/wait.h>} ed elencate in tab.~\ref{tab:proc_status_macro}; si tenga
+presente che queste macro prevedono che gli si passi come parametro la
+variabile di tipo \ctyp{int} puntata dall'argomento \param{status} restituito
+da \func{wait} o \func{waitpid}.
+
 Si tenga conto che nel caso di conclusione anomala il valore restituito da
-\val{WTERMSIG} può essere confrontato con le costanti definite in
-\file{signal.h} ed elencate in tab.~\ref{tab:sig_signal_list}, e stampato
-usando le apposite funzioni trattate in sez.~\ref{sec:sig_strsignal}.
+\val{WTERMSIG} può essere confrontato con le costanti che identificano i
+segnali definite in \file{signal.h} ed elencate in
+tab.~\ref{tab:sig_signal_list}, e stampato usando le apposite funzioni
+trattate in sez.~\ref{sec:sig_strsignal}.
 
 A partire dal kernel 2.6.9, sempre in conformità allo standard POSIX.1-2001, è
 stata introdotta una nuova funzione di attesa che consente di avere un
@@ -1148,13 +1187,12 @@ suo prototipo 
 \end{functions}
 
 La funzione prevede che si specifichi quali processi si intendono osservare
-usando i due argomenti \param{idtype} ed \param{id}; il primo indica se si
-vuole porsi in attesa su un singolo processo, un gruppo di processi o un
+usando i due argomenti \param{idtype} ed \param{id}; il primo indica se ci si
+vuole porre in attesa su un singolo processo, un gruppo di processi o un
 processo qualsiasi, e deve essere specificato secondo uno dei valori di
 tab.~\ref{tab:proc_waitid_idtype}; il secondo indica, a seconda del valore del
 primo, quale processo o quale gruppo di processi selezionare.
 
-
 \begin{table}[!htb]
   \centering
   \footnotesize
@@ -1415,7 +1453,7 @@ indicato dall'argomento \param{path}, che viene interpretato come il
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=15cm]{img/exec_rel}
+  \includegraphics[width=12cm]{img/exec_rel}
   \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.}
   \label{fig:proc_exec_relat}
 \end{figure}
@@ -1429,9 +1467,9 @@ sez.~\ref{sec:proc_environ}) del processo di partenza per costruire
 l'ambiente.
 
 Oltre a mantenere lo stesso \acr{pid}, il nuovo programma fatto partire da
-\func{exec} assume anche una serie di altre proprietà del processo chiamante;
-la lista completa è la seguente:
-\begin{itemize}
+\func{exec} mantiene la gran parte delle proprietà del processo chiamante; una
+lista delle più significative è la seguente:
+\begin{itemize*}
 \item il \textit{process id} (\acr{pid}) ed il \textit{parent process id}
   (\acr{ppid});
 \item l'\textsl{user-ID reale}, il \textit{group-ID reale} ed i
@@ -1445,43 +1483,99 @@ la lista completa 
 \item la maschera di creazione dei file \itindex{umask} (\textit{umask}, vedi
   sez.~\ref{sec:file_perm_management}) ed i \textit{lock} sui file (vedi
   sez.~\ref{sec:file_locking});
-\item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
-  sez.~\ref{sec:sig_sigmask});
 \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
-\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
-  \var{tms\_cutime}, \var{tms\_ustime} (vedi sez.~\ref{sec:sys_cpu_times}).
-\end{itemize}
-
-Inoltre i segnali che sono stati impostati per essere ignorati nel processo
-chiamante mantengono la stessa impostazione pure nel nuovo programma, tutti
-gli altri segnali vengono impostati alla loro azione predefinita. Un caso
-speciale è il segnale \const{SIGCHLD} che, quando impostato a
-\const{SIG\_IGN}, può anche non essere reimpostato a \const{SIG\_DFL} (si veda
-sez.~\ref{sec:sig_gen_beha}).
-
-La gestione dei file aperti dipende dal valore che ha il flag di
-\itindex{close-on-exec} \textit{close-on-exec} (vedi anche
-sez.~\ref{sec:file_fcntl}) per ciascun file descriptor. I file per cui è
-impostato vengono chiusi, tutti gli altri file restano aperti. Questo
-significa che il comportamento predefinito è che i file restano aperti
-attraverso una \func{exec}, a meno di una chiamata esplicita a \func{fcntl}
-che imposti il suddetto flag.  Per le directory, lo standard POSIX.1 richiede
-che esse vengano chiuse attraverso una \func{exec}, in genere questo è fatto
-dalla funzione \func{opendir} (vedi sez.~\ref{sec:file_dir_read}) che effettua
-da sola l'impostazione del flag di \itindex{close-on-exec}
-\textit{close-on-exec} sulle directory che apre, in maniera trasparente
-all'utente.
-
-Abbiamo detto che l'\textsl{user-ID reale} ed il \textsl{group-ID reale}
-restano gli stessi all'esecuzione di \func{exec}; normalmente vale lo stesso
-anche per l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} (il
-significato di questi identificatori è trattato in
-sez.~\ref{sec:proc_access_id}), tranne quando il file di cui viene chiesta
-l'esecuzione ha o il \itindex{suid~bit} \acr{suid} bit o lo \itindex{sgid~bit}
-\acr{sgid} bit impostato, in questo caso l'\textsl{user-ID effettivo} ed il
-\textsl{group-ID effettivo} vengono impostati rispettivamente all'utente o al
-gruppo cui il file appartiene (per i dettagli di questo comportamento si veda
-sez.~\ref{sec:proc_perms}).
+\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime};
+  \var{tms\_cutime}, \var{tms\_ustime} (vedi sez.~\ref{sec:sys_cpu_times});
+% TODO ===========Importante=============
+% TODO questo sotto è incerto, verificare
+% TODO ===========Importante=============
+\item la maschera dei segnali (si veda sez.~\ref{sec:sig_sigmask}).
+\end{itemize*}
+
+Una serie di proprietà del processo originale, che non avrebbe senso mantenere
+in un programma che esegue un codice completamente diverso in uno spazio di
+indirizzi totalmente indipendente e ricreato da zero, vengono perse con
+l'esecuzione di \func{exec}; lo standard POSIX.1-2001 prevede che le seguenti
+proprietà non vengano preservate:
+\begin{itemize*}
+\item l'insieme dei segnali pendenti (vedi sez.~\ref{sec:sig_gen_beha}), che
+  viene cancellato;
+\item gli eventuali stack alternativi per i segnali (vedi
+  sez.~\ref{sec:sig_specific_features});
+\item i \textit{directory stream} (vedi sez.~\ref{sec:file_dir_read}), che
+  vengono chiusi;
+\item le mappature dei file in memoria (vedi sez.~\ref{sec:file_memory_map});
+\item i segmenti di memoria condivisa SysV (vedi sez.~\ref{sec:ipc_sysv_shm})
+  e POSIX (vedi sez.~\ref{sec:ipc_posix_shm});
+\item i blocchi sulla memoria (vedi sez.~\ref{sec:proc_mem_lock});
+\item le funzioni registrate all'uscita (vedi sez.~\ref{sec:proc_atexit});
+\item i semafori e le code di messaggi POSIX (vedi
+  sez.~\ref{sec:ipc_posix_sem} e sez.~\ref{sec:ipc_posix_mq});
+\item i timer POSIX (vedi sez.~\ref{sec:sig_timer_adv}).
+\end{itemize*}
+
+I segnali che sono stati impostati per essere ignorati nel processo chiamante
+mantengono la stessa impostazione pure nel nuovo programma, ma tutti gli altri
+segnali, ed in particolare quelli per i quali è stato installato un gestore
+vengono impostati alla loro azione predefinita (vedi
+sez.~\ref{sec:sig_gen_beha}). Un caso speciale è il segnale \const{SIGCHLD}
+che, quando impostato a \const{SIG\_IGN}, potrebbe anche essere reimpostato a
+\const{SIG\_DFL}, anche se questo con Linux non avviene.\footnote{lo standard
+  POSIX.1-2001 prevede che questo comportamento sia deciso dalla singola
+  implementazione, quella di Linux è di non modificare l'impostazione
+  precedente.}
+
+Oltre alle precedenti che sono completamente generali e disponibili anche su
+altri sistemi unix-like, esistono altre proprietà dei processi, attinenti
+caratteristiche specifiche di Linux, che non vengono preservate
+nell'esecuzione della funzione \func{exec}, queste sono:
+\begin{itemize*}
+\item le operazione di I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_io})
+  pendenti vengono cancellate;
+\item le \itindex{capabilities} \textit{capabilities} vengono modificate come
+  illustrato in sez.~\ref{sec:proc_capabilities};
+\item tutti i \itindex{thread} \textit{thread} tranne il chiamante (vedi
+  sez.~\ref{sec:thread_xxx}) sono cancellati e tutti gli oggetti ad essi
+  relativi (vedi sez.~\ref{sec:thread_xxx}) rimossi;
+\item viene impostato il flag \const{PR\_SET\_DUMPABLE} di \func{prctl} (vedi
+  sez.~\ref{sec:prctl_xxx}) a meno che il programma da eseguire non sia
+  \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid} (vedi
+  sez.~\ref{sec:proc_access_id});
+\item il flag \const{PR\_SET\_KEEPCAPS} di \func{prctl} (vedi
+  sez.~\ref{sec:prctl_xxx}) viene cancellato;
+\item il nome del processo viene impostato al nome del file contenente il
+  programma messo in esecuzione;
+\item il segnale di terminazione viene reimpostato a \const{SIGCHLD};
+\item l'ambiente viene reinizializzato impostando le variabili attinenti alla
+  localizzazione al valore di default POSIX. 
+\end{itemize*}
+
+La gestione dei file aperti nel passaggio al nuovo programma lanciato con
+\func{exec} dipende dal valore che ha il flag di \itindex{close-on-exec}
+\textit{close-on-exec} (vedi anche sez.~\ref{sec:file_fcntl}) per ciascun file
+descriptor. I file per cui è impostato vengono chiusi, tutti gli altri file
+restano aperti. Questo significa che il comportamento predefinito è che i file
+restano aperti attraverso una \func{exec}, a meno di una chiamata esplicita a
+\func{fcntl} che imposti il suddetto flag.  Per le directory, lo standard
+POSIX.1 richiede che esse vengano chiuse attraverso una \func{exec}, in genere
+questo è fatto dalla funzione \func{opendir} (vedi
+sez.~\ref{sec:file_dir_read}) che effettua da sola l'impostazione del flag di
+\itindex{close-on-exec} \textit{close-on-exec} sulle directory che apre, in
+maniera trasparente all'utente.
+
+Il comportamento della funzione in relazione agli identificatori relativi al
+controllo di accesso verrà trattato in dettaglio in sez.~\ref{sec:proc_perms},
+qui è sufficiente anticipare (si faccia riferimento a
+sez.~\ref{sec:proc_access_id} per la definizione di questi identificatori)
+come l'\textsl{user-ID reale} ed il \textsl{group-ID reale} restano sempre gli
+stessi, mentre l'\textsl{user-ID salvato} ed il \textsl{group-ID salvato}
+vengono impostati rispettivamente all'\textsl{user-ID effettivo} ed il
+\textsl{group-ID effettivo}, questi ultimi normalmente non vengono modificati,
+a meno che il file di cui viene chiesta l'esecuzione non abbia o il
+\itindex{suid~bit} \acr{suid} bit o lo \itindex{sgid~bit} \acr{sgid} bit
+impostato, in questo caso l'\textsl{user-ID effettivo} ed il \textsl{group-ID
+  effettivo} vengono impostati rispettivamente all'utente o al gruppo cui il
+file appartiene.
 
 Se il file da eseguire è in formato \emph{a.out} e necessita di librerie
 condivise, viene lanciato il \textit{linker} dinamico \cmd{/lib/ld.so} prima
@@ -2086,16 +2180,16 @@ compila con il flag \cmd{-ansi}, 
 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
-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}
@@ -2147,21 +2241,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
@@ -2171,7 +2265,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ò
-                                    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
@@ -2180,8 +2275,6 @@ fintanto che esso si trova in uno qualunque degli altri stati.
   \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
@@ -2230,7 +2323,8 @@ bisogno della CPU.
 \subsection{Il meccanismo di \textit{scheduling} standard}
 \label{sec:proc_sched_stand}
 
-A meno che non si abbiano esigenze specifiche, l'unico meccanismo di
+A meno che non si abbiano esigenze specifiche,\footnote{per alcune delle quali
+  sono state introdotte delle varianti specifiche.} l'unico meccanismo di
 scheduling con il quale si avrà a che fare è quello tradizionale, che prevede
 solo priorità dinamiche. È di questo che, di norma, ci si dovrà preoccupare
 nella programmazione.  Come accennato in Linux i processi ordinari hanno tutti
@@ -2247,39 +2341,49 @@ Il meccanismo usato da Linux 
   ed è stata anche introdotta la possibilità di usare diversi algoritmi,
   selezionabili sia in fase di compilazione, che, nelle versioni più recenti,
   all'avvio (addirittura è stato ideato un sistema modulare che permette di
-  cambiare lo scheduler al volo, che comunque non è incluso nel kernel
-  ufficiale).} ma a grandi linee si può dire che ad ogni processo è assegnata
-una \textit{time-slice}, cioè un intervallo di tempo (letteralmente una fetta)
-per il quale, a meno di eventi esterni, esso viene eseguito senza essere
-interrotto.  Il valore della \textit{time-slice} è stabilito dalla sua
-cosiddetta \textit{nice} (o \textit{niceness}) del processo.  Questo è un
-valore, che di default è nullo, e che oltre a essere associato alla lunghezza
-della \textit{timesllce} viene anche sommato alla priorità dinamica di ciascun
-processo. Questa viene calcolata dallo scheduler e viene \textsl{diminuita}
-tutte le volte che un processo è in stato \textbf{Runnable} ma non viene posto
-in esecuzione. Lo scheduler infatti mette sempre in esecuzione, fra tutti i
-processi in stato \textbf{Runnable}, quello che ha la priorità dinamica più
-bassa.\footnote{in realtà il calcolo della priorità dinamica e la scelta di
-  quale processo mettere in esecuzione avviene con un algoritmo più
-  complicato, (per una buona trattazione vedi \cite{XXX}), ad esempio nei
-  sistemi multiprocessore viene favorito un processo eseguito sulla stessa
-  CPU.}
-
-La priorità di un processo è così controllata attraverso il valore di
-\var{nice}, che stabilisce la durata della \textit{time-slice} (un valore di
-nice più alto corrisponde ad una \textit{time-sl}, ed ovviamente
-più questa è ampia e più lungo sarà il tempo che esso resta in esecuzione in
-esecuzione. Ma per il meccanismo appana descritto, andando a sommarsi alla
-priorità dianamica, essa tenderà anche a sfavorire (o fa
-
-per il
-meccanismo appena descritto infatti un valore più lungo assicura una maggiore
-attribuzione di CPU.  L'origine del nome di questo parametro sta nel fatto che
-generalmente questo viene usato per diminuire la priorità di un processo, come
-misura di cortesia nei confronti degli altri.  I processi infatti vengono
-creati dal sistema con lo stesso valore di \var{nice} (nullo) e nessuno è
-privilegiato rispetto agli altri; il valore può essere modificato solo
-attraverso la funzione \funcd{nice}, il cui prototipo è:
+  cambiare lo scheduler a sistema attivo).} ma a grandi linee si può dire che
+ad ogni processo è assegnata una \textit{time-slice}, cioè un intervallo di
+tempo (letteralmente una fetta) per il quale, a meno di eventi esterni, esso
+viene eseguito senza essere interrotto.  Inoltre la priorità dinamica viene
+calcolata dallo scheduler a partire da un valore iniziale che viene
+\textsl{diminuito} tutte le volte che un processo è in stato \textbf{Runnable}
+ma non viene posto in esecuzione.\footnote{in realtà il calcolo della priorità
+  dinamica e la conseguente scelta di quale processo mettere in esecuzione
+  avviene con un algoritmo molto più complicato, che tiene conto anche della
+  \textsl{interattività} del processo, utilizzando diversi fattori, questa è
+  una brutale semplificazione per rendere l'idea del funzionamento, per una
+  trattazione più dettagliata, anche se non aggiornatissima, dei meccanismi di
+  funzionamento dello scheduler si legga il quarto capitolo di
+  \cite{LinKernDev}.} Lo scheduler infatti mette sempre in esecuzione, fra
+tutti i processi in stato \textbf{Runnable}, quello che ha il valore di
+priorità dinamica più basso.\footnote{con le priorità dinamiche il significato
+  del valore numerico ad esse associato è infatti invertito, un valore più
+  basso significa una priorità maggiore.} Il fatto che questo valore venga
+diminuito quando un processo non viene posto in esecuzione pur essendo pronto,
+significa che la priorità dei processi che non ottengono l'uso del processore
+viene progressivamente incrementata, così che anche questi alla fine hanno la
+possibilità di essere eseguiti.
+
+Sia la dimensione della \textit{time-slice} che il valore di partenza della
+priorità dinamica sono determinate dalla cosiddetta \textit{nice} (o
+\textit{niceness}) del processo.\footnote{questa è una delle tante proprietà
+  che ciascun processo si porta dietro, essa viene ereditata dai processi
+  figli e mantenuta attraverso una \func{exec}; fino alla serie 2.4 essa era
+  mantenuta nell'omonimo campo \texttt{nice} della \texttt{task\_struct}, con
+  la riscrittura dello scheduler eseguita nel 2.6 viene mantenuta nel campo
+  \texttt{static\_prio} come per le priorità statiche.} L'origine del nome di
+questo parametro sta nel fatto che generalmente questo viene usato per
+\textsl{diminuire} la priorità di un processo, come misura di cortesia nei
+confronti degli altri.  I processi infatti vengono creati dal sistema con un
+valore di \var{nice} nullo e nessuno è privilegiato rispetto agli altri;
+specificando un valore positivo si avrà una \textit{time-slice} più breve ed
+un valore di priorità dinamica iniziale più alto, mentre un valore negativo
+darà una \textit{time-slice} più lunga ed un valore di priorità dinamica
+iniziale più basso.
+
+Esistono diverse funzioni che consentono di modificare la \textit{niceness} di
+un processo; la più semplice è funzione \funcd{nice}, che opera sul processo
+corrente, il suo prototipo è:
 \begin{prototype}{unistd.h}
 {int nice(int inc)}
   Aumenta il valore di \var{nice} per il processo corrente.
@@ -2288,42 +2392,50 @@ attraverso la funzione \funcd{nice}, il cui prototipo 
     di successo e -1 in caso di errore, nel qual caso \var{errno} può assumere
     i valori:
   \begin{errlist}
-  \item[\errcode{EPERM}] un processo senza i privilegi di amministratore ha
-    specificato un valore di \param{inc} negativo.
+  \item[\errcode{EPERM}] non si ha il permesso di specificare un valore
+    di \param{inc} negativo. 
   \end{errlist}}
 \end{prototype}
 
-L'argomento \param{inc} indica l'incremento del valore di \var{nice}:
-quest'ultimo può assumere valori compresi fra \const{PRIO\_MIN} e
-\const{PRIO\_MAX} (che nel caso di Linux sono $-19$ e $20$), ma per
-\param{inc} si può specificare un valore qualunque, positivo o negativo, ed il
-sistema provvederà a troncare il risultato nell'intervallo consentito. Valori
-positivi comportano maggiore \textit{cortesia} e cioè una diminuzione della
-priorità, ogni utente può solo innalzare il valore di un suo processo. Solo
-l'amministratore può specificare valori negativi che permettono di aumentare
-la priorità di un processo.
+L'argomento \param{inc} indica l'incremento da effettuare rispetto al valore
+di \var{nice} corrente: quest'ultimo può assumere valori compresi fra
+\const{PRIO\_MIN} e \const{PRIO\_MAX}; nel caso di Linux sono fra $-20$ e
+$19$,\footnote{in realtà l'intervallo varia a seconda delle versioni di
+  kernel, ed è questo a partire dal kernel 1.3.43, anche se oggi si può avere
+  anche l'intervallo fra $-20$ e $20$.} ma per \param{inc} si può specificare
+un valore qualunque, positivo o negativo, ed il sistema provvederà a troncare
+il risultato nell'intervallo consentito. Valori positivi comportano maggiore
+\textit{cortesia} e cioè una diminuzione della priorità, valori negativi
+comportano invece un aumento della priorità. Con i kernel precedenti il
+2.6.12 solo l'amministratore\footnote{o un processo con la
+  \itindex{capabilities} \textit{capability} \const{CAP\_SYS\_NICE}, vedi
+  sez.~\ref{sec:proc_capabilities}.} può specificare valori negativi
+di \param{inc} che permettono di aumentare la priorità di un processo, a
+partire da questa versione è consentito anche agli utenti normali alzare
+(entro certi limiti, che vedremo più avanti) la priorità dei propri processi.
 
 Gli standard SUSv2 e POSIX.1 prevedono che la funzione ritorni il nuovo valore
 di \var{nice} del processo; tuttavia la system call di Linux non segue questa
-convenzione e restituisce sempre 0 in caso di successo, questo perché $-1$ è
-un valore di \var{nice} legittimo e questo comporta una confusione con una
-eventuale condizione di errore. 
-
+convenzione e restituisce sempre 0 in caso di successo e $-1$ in caso di
+errore; questo perché $-1$ è un valore di \var{nice} legittimo e questo
+comporta una confusione con una eventuale condizione di errore. La system call
+originaria inoltre non consente, se non dotati di adeguati privilegi, di
+diminuire un valore di \var{nice} precedentemente innalzato.
 Fino alle \acr{glibc} 2.2.4 la funzione di libreria riportava direttamente il
-valore ottenuto dalla system call, violando lo standard, per cui per ottenere
-il nuovo valore occorreva una successiva chiamata alla funzione
+risultato dalla system call, violando lo standard, per cui per ottenere il
+nuovo valore occorreva una successiva chiamata alla funzione
 \func{getpriority}. A partire dalla \acr{glibc} 2.2.4 \func{nice} è stata
-reimplementata come funzione di libreria, e restituisce il valore di
-\var{nice} come richiesto dallo standard.\footnote{questo viene fatto
-  chiamando al suo interno \func{getpriority}, ed è questo il motivo delle due
-  possibilità per i valori di ritorno citati nella descrizione del prototipo.}
-In questo caso l'unico modo per rilevare in maniera affidabile una condizione
-di errore è quello di azzerare \var{errno} prima della chiamata della funzione
-e verificarne il valore quando \func{nice} restituisce $-1$.
-
-
-Per leggere il valore di nice di un processo occorre usare la funzione
-\funcd{getpriority}, derivata da BSD; il suo prototipo è:
+reimplementata e non viene più chiamata la omonima system call, con questa
+versione viene restituito come valore di ritorno il valore di \var{nice}, come
+richiesto dallo standard.\footnote{questo viene fatto chiamando al suo interno
+  \func{setpriority}, che tratteremo a breve.}  In questo caso l'unico modo
+per rilevare in maniera affidabile una condizione di errore è quello di
+azzerare \var{errno} prima della chiamata della funzione e verificarne il
+valore quando \func{nice} restituisce $-1$.
+
+Per leggere il valore di \textit{nice} di un processo occorre usare la
+funzione \funcd{getpriority}, derivata da BSD; il suo prototipo è:
 \begin{prototype}{sys/resource.h}
 {int getpriority(int which, int who)}
   
@@ -2386,22 +2498,43 @@ impostare la priorit
   \item[\errcode{ESRCH}] non c'è nessun processo che corrisponda ai valori di
   \param{which} e \param{who}.
   \item[\errcode{EINVAL}] il valore di \param{which} non è valido.
+  \item[\errcode{EACCES}] si è richiesto un aumento di priorità senza avere
+    sufficienti privilegi.
   \item[\errcode{EPERM}] un processo senza i privilegi di amministratore ha
-    specificato un valore di \param{inc} negativo.
-  \item[\errcode{EACCES}] un processo senza i privilegi di amministratore ha
     cercato di modificare la priorità di un processo di un altro utente.
   \end{errlist}}
 \end{prototype}
 
 La funzione imposta la priorità al valore specificato da \param{prio} per
-tutti i processi indicati dagli argomenti \param{which} e \param{who}.  La
-gestione dei permessi dipende dalle varie implementazioni; in Linux, secondo
-le specifiche dello standard SUSv3, e come avviene per tutti i sistemi che
-derivano da SysV, è richiesto che l'user-ID reale o effettivo del processo
-chiamante corrispondano al real user-ID (e solo quello) del processo di cui si
-vuole cambiare la priorità; per i sistemi derivati da BSD invece (SunOS,
-Ultrix, *BSD) la corrispondenza può essere anche con l'user-ID effettivo.
-
+tutti i processi indicati dagli argomenti \param{which} e \param{who}. In
+questo caso come valore di \param{prio} deve essere specificato il valore di
+\textit{nice} da assegnare, e non un incremento (positivo o negativo) come nel
+caso di \func{nice}. La funzione restituisce il valore di \textit{nice}
+assegnato in caso di successo e $-1$ in caso di errore, e come per \func{nice}
+anche in questo caso per rilevare un errore occorre sempre porre a zero
+\var{errno} prima della chiamata della funzione, essendo $-1$ un valore di
+\textit{nice} valido. 
+
+Si tenga presente che solo l'amministratore\footnote{o più precisamente un
+  processo con la \itindex{capabilities} \textit{capability}
+  \const{CAP\_SYS\_NICE}, vedi sez.~\ref{sec:proc_capabilities}.} ha la
+possibilità di modificare arbitrariamente le priorità di qualunque
+processo. Un utente normale infatti può modificare solo la priorità dei suoi
+processi ed in genere soltanto diminuirla.  Fino alla versione di kernel
+2.6.12 Linux ha seguito le specifiche dello standard SUSv3, e come per tutti i
+sistemi derivati da SysV veniva richiesto che l'user-ID reale o quello
+effettivo del processo chiamante corrispondessero all'user-ID reale (e solo a
+quello) del processo di cui si intendeva cambiare la priorità. A partire dalla
+versione 2.6.12 è stata adottata la semantica in uso presso i sistemi derivati
+da BSD (SunOS, Ultrix, *BSD), in cui la corrispondenza può essere anche con
+l'user-ID effettivo.
+
+Sempre a partire dal kernel 2.6.12 è divenuto possibile anche per gli utenti
+ordinari poter aumentare la priorità dei propri processi specificando un
+valore di \param{prio} negativo. Questa operazione non è possibile però in
+maniera indiscriminata, ed in particolare può essere effettuata solo
+nell'intervallo consentito dal valore del limite \const{RLIMIT\_NICE}
+(torneremo su questo in sez.~\ref{sec:sys_resource_limit}).
 
 
 \subsection{Il meccanismo di \textit{scheduling real-time}}
@@ -2424,14 +2557,24 @@ funzioni di controllo della memoria virtuale (vedi
 sez.~\ref{sec:proc_mem_lock}), il primo non è superabile e può comportare
 ritardi non prevedibili riguardo ai tempi di esecuzione di qualunque processo.
 
-Occorre usare le priorità assolute con molta attenzione: se si dà ad un
-processo una priorità assoluta e questo finisce in un loop infinito, nessun
-altro processo potrà essere eseguito, ed esso sarà mantenuto in esecuzione
-permanentemente assorbendo tutta la CPU e senza nessuna possibilità di
-riottenere l'accesso al sistema. Per questo motivo è sempre opportuno, quando
-si lavora con processi che usano priorità assolute, tenere attiva una shell
-cui si sia assegnata la massima priorità assoluta, in modo da poter essere
-comunque in grado di rientrare nel sistema.
+Nonostante questo, ed in particolare con una serie di miglioramenti che sono
+stati introdotti nello sviluppo del kernel,\footnote{in particolare a partire
+  dalla versione 2.6.18 sono stati inserite nel kernel una serie di modifiche
+  che consentono di avvicinarsi sempre di più ad un vero e proprio sistema
+  \textit{real-time} estendendo il concetto di \textit{preemption} alle
+  operazioni dello stesso kernel; esistono vari livelli a cui questo può
+  essere fatto, ottenibili attivando in fase di compilazione una fra le
+  opzioni \texttt{CONFIG\_PREEMPT\_NONE}, \texttt{CONFIG\_PREEMPT\_VOLUNTARY}
+  e \texttt{CONFIG\_PREEMPT\_DESKTOP}.} si può arrivare ad una ottima
+approssimazione di sistema real-time usando le priorità assolute; occorre
+farlo però con molta attenzione: se si dà ad un processo una priorità assoluta
+e questo finisce in un loop infinito, nessun altro processo potrà essere
+eseguito, ed esso sarà mantenuto in esecuzione permanentemente assorbendo
+tutta la CPU e senza nessuna possibilità di riottenere l'accesso al
+sistema. Per questo motivo è sempre opportuno, quando si lavora con processi
+che usano priorità assolute, tenere attiva una shell cui si sia assegnata la
+massima priorità assoluta, in modo da poter essere comunque in grado di
+rientrare nel sistema.
 
 Quando c'è un processo con priorità assoluta lo scheduler lo metterà in
 esecuzione prima di ogni processo normale. In caso di più processi sarà
@@ -2452,21 +2595,22 @@ scelta; lo standard ne prevede due:
 \item[\textsf{RR}] \textit{Round Robin}. Il comportamento è del tutto analogo
   a quello precedente, con la sola differenza che ciascun processo viene
   eseguito al massimo per un certo periodo di tempo (la cosiddetta
-  \textit{time slice}) dopo di che viene automaticamente posto in fondo alla
+  \textit{time-slice}) dopo di che viene automaticamente posto in fondo alla
   coda dei processi con la stessa priorità. In questo modo si ha comunque una
   esecuzione a turno di tutti i processi, da cui il nome della politica. Solo
-  i processi con la stessa priorità ed in stato \textit{runnable} entrano nel
+  i processi con la stessa priorità ed in stato \textbf{Runnable} entrano nel
   \textsl{girotondo}.
 \end{basedescript}
 
-La funzione per impostare le politiche di scheduling (sia real-time che
-ordinarie) ed i relativi parametri è \funcd{sched\_setscheduler}; il suo
-prototipo è:
+Lo standard POSIX.1-2001 prevede una funzione che consenta sia di modificare
+le politiche di scheduling, passando da real-time a ordinarie o viceversa, che
+di specificare, in caso di politiche real-time, la eventuale priorità statica;
+la funzione è \funcd{sched\_setscheduler} ed il suo prototipo è:
 \begin{prototype}{sched.h}
 {int sched\_setscheduler(pid\_t pid, int policy, const struct sched\_param *p)}
   Imposta priorità e politica di scheduling.
   
-  \bodydesc{La funzione ritorna la priorità in caso di successo e -1 in caso
+  \bodydesc{La funzione ritorna la priorità in caso di successo e $-$1 in caso
     di errore, nel qual caso \var{errno} può assumere i valori:
     \begin{errlist}
     \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
@@ -2478,14 +2622,12 @@ prototipo 
 \end{prototype}
 
 La funzione esegue l'impostazione per il processo specificato dall'argomento
-\param{pid}; un valore nullo esegue l'impostazione per il processo corrente.
-La politica di scheduling è specificata dall'argomento \param{policy} i cui
-possibili valori sono riportati in tab.~\ref{tab:proc_sched_policy}; un valore
-negativo per \param{policy} mantiene la politica di scheduling corrente.  Solo
-un processo con i privilegi di amministratore\footnote{più precisamente con la
-  \itindex{capabilities} \textit{capability} \const{CAP\_SYS\_NICE}, vedi
-  sez.~\ref{sec:proc_capabilities}.} può impostare priorità assolute diverse
-da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}.
+\param{pid}; un valore nullo di questo argomento esegue l'impostazione per il
+processo corrente.  La politica di scheduling è specificata
+dall'argomento \param{policy} i cui possibili valori sono riportati in
+tab.~\ref{tab:proc_sched_policy}; la parte alta della tabella indica le
+politiche real-time, quella bassa le politiche ordinarie. Un valore negativo
+per \param{policy} mantiene la politica di scheduling corrente.
 
 \begin{table}[htb]
   \centering
@@ -2498,10 +2640,12 @@ da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}.
     \const{SCHED\_FIFO} & Scheduling real-time con politica \textit{FIFO}. \\
     \const{SCHED\_RR}   & Scheduling real-time con politica \textit{Round
       Robin}. \\
+    \hline
     \const{SCHED\_OTHER}& Scheduling ordinario.\\
     \const{SCHED\_BATCH}& Scheduling ordinario con l'assunzione ulteriore di
                           lavoro \textit{CPU intensive}.\footnotemark\\
-    \const{SCHED\_IDLE} & Scheduling di priorità estremamente bassa.\\
+    \const{SCHED\_IDLE} & Scheduling di priorità estremamente
+                          bassa.\footnotemark\\
     \hline
   \end{tabular}
   \caption{Valori dell'argomento \param{policy} per la funzione
@@ -2509,14 +2653,41 @@ da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}.
   \label{tab:proc_sched_policy}
 \end{table}
 
-\footnotetext{introdotto con il kernel 2.6.16.}
-
-Il valore della priorità è passato attraverso la struttura
-\struct{sched\_param} (riportata in fig.~\ref{fig:sig_sched_param}), il cui
-solo campo attualmente definito è \var{sched\_priority}, che nel caso delle
-priorità assolute deve essere specificato nell'intervallo fra un valore
-massimo ed uno minimo, che nel caso sono rispettivamente 1 e 99; il valore
-nullo è legale, ma indica i processi normali.
+\footnotetext[41]{introdotto con il kernel 2.6.16.}
+\footnotetext{introdotto con il kernel 2.6.23.}
+
+Con le versioni più recenti del kernel sono state introdotte anche delle
+varianti sulla politica di scheduling tradizionale per alcuni carichi di
+lavoro specifici, queste due nuove politiche sono specifiche di Linux e non
+devono essere usate se si vogliono scrivere programmi portabili.
+
+La politica \const{SCHED\_BATCH} è una variante della politica ordinaria con
+la sola differenza che i processi ad essa soggetti non ottengono, nel calcolo
+delle priorità dinamiche fatto dallo scheduler, il cosiddetto bonus di
+interattività che mira a favorire i processi che si svegliano dallo stato di
+\textbf{Sleep}.\footnote{cosa che accade con grande frequenza per i processi
+  interattivi, dato che essi sono per la maggior parte del tempo in attesa di
+  dati in ingresso da parte dell'utente.} La si usa pertanto, come indica il
+nome, per processi che usano molta CPU (come programmi di calcolo) che in
+questo modo sono leggermente sfavoriti rispetto ai processi interattivi che
+devono rispondere a dei dati in ingresso, pur non perdendo il loro valore di
+\textit{nice}.
+
+La politica \const{SCHED\_IDLE} invece è una politica dedicata ai processi che
+si desidera siano eseguiti con la più bassa priorità possibile, ancora più
+bassa di un processo con il minimo valore di \textit{nice}. In sostanza la si
+può utilizzare per processi che devono essere eseguiti se non c'è niente altro
+da fare. Va comunque sottolineato che anche un processo \const{SCHED\_IDLE}
+avrà comunque una sua possibilità di utilizzo della CPU, sia pure in
+percentuale molto bassa.
+
+Qualora si sia richiesta una politica real-time il valore della priorità
+statica viene impostato attraverso la struttura \struct{sched\_param},
+riportata in fig.~\ref{fig:sig_sched_param}, il cui solo campo attualmente
+definito è \var{sched\_priority}. Il campo deve contenere il valore della
+priorità statica da assegnare al processo; lo standard prevede che questo
+debba essere assegnato all'interno di un intervallo fra un massimo ed un
+minimo che nel caso di Linux sono rispettivamente 1 e 99.  
 
 \begin{figure}[!bht]
   \footnotesize \centering
@@ -2528,11 +2699,11 @@ nullo 
   \label{fig:sig_sched_param}
 \end{figure}
 
-Si tenga presente che quando si imposta una politica di scheduling real-time
-per un processo (o se ne cambia la priorità con \func{sched\_setparam}) questo
-viene messo in cima alla lista dei processi con la stessa priorità; questo
-comporta che verrà eseguito subito, interrompendo eventuali altri processi con
-la stessa priorità in quel momento in esecuzione.
+I processi con politica di scheduling ordinaria devono sempre specificare un
+valore nullo di \var{sched\_priority} altrimenti si avrà un errore
+\errcode{EINVAL}, questo valore infatti non ha niente a che vedere con la
+priorità dinamica determinata dal valore di \textit{nice}, che deve essere
+impostato con le funzioni viste in precedenza.
 
 Lo standard POSIX.1b prevede comunque che i due valori della massima e minima
 priorità statica possano essere ottenuti, per ciascuna delle politiche di
@@ -2550,90 +2721,112 @@ prototipi sono:
   della priorità statica per la politica di scheduling \param{policy}.
   
   \bodydesc{La funzioni ritornano il valore della priorità in caso di successo
-    e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori:
+    e $-1$ in caso di errore, nel qual caso \var{errno} può assumere i valori:
     \begin{errlist}
     \item[\errcode{EINVAL}] il valore di \param{policy} non è valido.
   \end{errlist}}
 \end{functions}
 
-
-I processi con politica di scheduling \const{SCHED\_OTHER} devono specificare
-un valore nullo (altrimenti si avrà un errore \errcode{EINVAL}), questo valore
-infatti non ha niente a che vedere con la priorità dinamica determinata dal
-valore di \var{nice}, che deve essere impostato con le funzioni viste in
-precedenza.
+Si tenga presente che quando si imposta una politica di scheduling real-time
+per un processo o se ne cambia la priorità statica questo viene messo in cima
+alla lista dei processi con la stessa priorità; questo comporta che verrà
+eseguito subito, interrompendo eventuali altri processi con la stessa priorità
+in quel momento in esecuzione.
 
 Il kernel mantiene i processi con la stessa priorità assoluta in una lista, ed
 esegue sempre il primo della lista, mentre un nuovo processo che torna in
-stato \textit{runnable} viene sempre inserito in coda alla lista. Se la
+stato \textbf{Runnable} viene sempre inserito in coda alla lista. Se la
 politica scelta è \const{SCHED\_FIFO} quando il processo viene eseguito viene
 automaticamente rimesso in coda alla lista, e la sua esecuzione continua
 fintanto che non viene bloccato da una richiesta di I/O, o non rilascia
-volontariamente la CPU (in tal caso, tornando nello stato \textit{runnable}
+volontariamente la CPU (in tal caso, tornando nello stato \textbf{Runnable}
 sarà reinserito in coda alla lista); l'esecuzione viene ripresa subito solo
 nel caso che esso sia stato interrotto da un processo a priorità più alta.
 
-Se si intende operare solo sulla priorità assoluta di un processo si possono
-usare le funzioni \funcd{sched\_setparam} e \funcd{sched\_getparam}, i cui
+Solo un processo con i privilegi di amministratore\footnote{più precisamente
+  con la \itindex{capabilities} capacità \const{CAP\_SYS\_NICE}, vedi
+  sez.~\ref{sec:proc_capabilities}.} può impostare senza restrizioni priorità
+assolute diverse da zero o politiche \const{SCHED\_FIFO} e
+\const{SCHED\_RR}. Un utente normale può modificare solo le priorità di
+processi che gli appartengono; è cioè richiesto che l'user-ID effettivo del
+processo chiamante corrisponda all'user-ID reale o effettivo del processo
+indicato con \param{pid}.
+
+Fino al kernel 2.6.12 gli utenti normali non potevano impostare politiche
+real-time o modificare la eventuale priorità statica di un loro processo. A
+partire da questa versione è divenuto possibile anche per gli utenti normali
+usare politiche real-time fintanto che la priorità assoluta che si vuole
+impostare è inferiore al limite \const{RLIMIT\_RTPRIO} (vedi
+sez.~\ref{sec:sys_resource_limit}) ad essi assegnato. Unica eccezione a questa
+possibilità sono i processi \const{SCHED\_IDLE}, che non possono cambiare
+politica di scheduling indipendentemente dal valore di
+\const{RLIMIT\_RTPRIO}. Inoltre, in caso di processo già sottoposto ad una
+politica real-time, un utente può sempre, indipendentemente dal valore di
+\const{RLIMIT\_RTPRIO}, diminuirne la priorità o portarlo ad una politica
+ordinaria.
+
+Se si intende operare solo sulla priorità statica di un processo si possono
+usare le due funzioni \funcd{sched\_setparam} e \funcd{sched\_getparam} che
+consentono rispettivamente di impostarne e leggerne il valore, i loro
 prototipi sono:
 \begin{functions}
   \headdecl{sched.h}
 
-  \funcdecl{int sched\_setparam(pid\_t pid, const struct sched\_param *p)}
-  Imposta la priorità assoluta del processo \param{pid}.
+  \funcdecl{int sched\_setparam(pid\_t pid, const struct sched\_param *param)}
+  Imposta la priorità statica del processo \param{pid}.
 
-  \funcdecl{int sched\_getparam(pid\_t pid, struct sched\_param *p)}
-  Legge la priorità assoluta del processo \param{pid}.
+  \funcdecl{int sched\_getparam(pid\_t pid, struct sched\_param *param)}
+  Legge la priorità statica del processo \param{pid}.
 
-  \bodydesc{La funzione ritorna la priorità  in caso di successo
-    e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori:
+  \bodydesc{Entrambe le funzioni ritornano 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}] il processo \param{pid} non esiste.
-    \item[\errcode{EINVAL}] il valore di \param{p} non ha senso per la
-      politica scelta.
-    \item[\errcode{EPERM}] il processo non ha i privilegi sufficienti per
-      eseguire l'operazione.
+    \item[\errcode{EINVAL}] il valore di \param{param} non ha senso per la
+      politica usata dal processo.
+    \item[\errcode{EPERM}] non si hanno privilegi sufficienti per eseguire
+      l'operazione.
   \end{errlist}}
 \end{functions}
 
-L'uso di \func{sched\_setparam} che è del tutto equivalente a
-\func{sched\_setscheduler} con \param{priority} uguale a -1. Come per
-\func{sched\_setscheduler} specificando 0 come valore di \param{pid} si opera
-sul processo corrente. La disponibilità di entrambe le funzioni può essere
-verificata controllando la macro \macro{\_POSIX\_PRIORITY\_SCHEDULING} che è
-definita nell'header \file{sched.h}. 
-
-Si tenga presente che per eseguire la funzione il processo chiamante deve
-avere un user-ID effettivo uguale all'user-ID reale o a quello effettivo del
-processo di cui vuole cambiare la priorità, oppure deve avere i privilegi di
-amministratore (con la capacità \const{CAP\_SYS\_NICE}).
-
-La priorità assoluta può essere riletta indietro dalla funzione
-\funcd{sched\_getscheduler}, il cui prototipo è:
+L'uso di \func{sched\_setparam}, compresi i controlli di accesso che vi si
+applicano, è del tutto equivalente a quello di \func{sched\_setscheduler} con
+argomento \param{policy} uguale a -1. Come per \func{sched\_setscheduler}
+specificando 0 come valore dell'argomento \param{pid} si opera sul processo
+corrente. Benché la funzione sia utilizzabile anche con processi sottoposti a
+politica ordinaria essa ha senso soltanto per quelli real-time, dato che per i
+primi la priorità statica può essere soltanto nulla.  La disponibilità di
+entrambe le funzioni può essere verificata controllando la macro
+\macro{\_POSIX\_PRIORITY\_SCHEDULING} che è definita nell'header
+\file{sched.h}.
+
+Se invece si vuole sapere quale è politica di scheduling di un processo si può
+usare la funzione \funcd{sched\_getscheduler}, il cui prototipo è:
 \begin{prototype}{sched.h}
 {int sched\_getscheduler(pid\_t pid)}
   Legge la politica di scheduling per il processo \param{pid}.
   
   \bodydesc{La funzione ritorna la politica di scheduling in caso di successo
-    e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori:
+    e $-1$ in caso di errore, nel qual caso \var{errno} può assumere i valori:
     \begin{errlist}
     \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
-    \item[\errcode{EINVAL}] il valore di \param{pid} è negativo.
-  \end{errlist}}
+    \item[\errcode{EPERM}] non si hanno privilegi sufficienti per eseguire
+      l'operazione.
+  \end{errlist}}  
 \end{prototype}
 
-La funzione restituisce il valore (secondo quanto elencato in
-tab.~\ref{tab:proc_sched_policy}) della politica di scheduling per il processo
-specificato; se \param{pid} è nullo viene restituito quello del processo
-chiamante.
+La funzione restituisce il valoresecondo quanto elencato in
+tab.~\ref{tab:proc_sched_policy}, della politica di scheduling per il processo
+specificato; se l'argomento \param{pid} è nullo viene restituito il valore
+relativo al processo chiamante.
 
 L'ultima funzione che permette di leggere le informazioni relative ai processi
 real-time è \funcd{sched\_rr\_get\_interval}, che permette di ottenere la
-lunghezza della \textit{time slice} usata dalla politica \textit{round robin};
+lunghezza della \textit{time-slice} usata dalla politica \textit{round robin};
 il suo prototipo è:
 \begin{prototype}{sched.h}
   {int sched\_rr\_get\_interval(pid\_t pid, struct timespec *tp)} Legge in
-  \param{tp} la durata della \textit{time slice} per il processo \param{pid}.
+  \param{tp} la durata della \textit{time-slice} per il processo \param{pid}.
   
   \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
     nel qual caso \var{errno} può assumere i valori:
@@ -2650,9 +2843,9 @@ dato che in Linux questo intervallo di tempo 
 questa funzione ritorna sempre un valore di 150 millisecondi, e non importa
 specificare il PID di un processo reale.
 
-Come accennato ogni processo che usa lo scheduling real-time può rilasciare
-volontariamente la CPU; questo viene fatto attraverso la funzione
-\funcd{sched\_yield}, il cui prototipo è:
+Come accennato ogni processo può rilasciare volontariamente la CPU in modo da
+consentire agli altri processi di essere eseguiti; la funzione che consente di
+fare tutto ciò è \funcd{sched\_yield}, il cui prototipo è:
 \begin{prototype}{sched.h}
   {int sched\_yield(void)} 
   
@@ -2662,16 +2855,27 @@ volontariamente la CPU; questo viene fatto attraverso la funzione
     nel qual caso \var{errno} viene impostata opportunamente.}
 \end{prototype}
 
-La funzione fa sì che il processo rilasci la CPU, in modo da essere rimesso in
-coda alla lista dei processi da eseguire, e permettere l'esecuzione di un
-altro processo; 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 l'esecuzione degli altri processi
-con pari priorità quando la sezione più urgente è finita.
+Questa funzione ha un utilizzo effettivo soltanto quando si usa lo scheduling
+real-time, e serve a far sì che il processo corrente rilasci la CPU, in modo
+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 con politica \const{SCHED\_FIFO}, per permettere
+l'esecuzione degli altri processi con pari priorità quando la sezione più
+urgente è finita.
+
+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}.}
+
 
-% 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.
 
 \subsection{Il controllo dello \textit{scheduler} per i sistemi
   multiprocessore}
@@ -2781,8 +2985,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
-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
@@ -2864,6 +3068,210 @@ non avranno alcun risultato effettivo.
 \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 \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 verificare http://lwn.net/Articles/355987/
+
+%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}
@@ -3030,7 +3438,7 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso
 % LocalWords:  parent kernel init pstree keventd kswapd table struct linux call
 % LocalWords:  nell'header scheduler system interrupt timer HZ asm Hertz clock
 % LocalWords:  l'alpha tick fork wait waitpid exit exec image glibc int pgid ps
-% LocalWords:  sid thread Ingo Molnar ppid getpid getppid sys unistd LD
+% LocalWords:  sid thread Ingo Molnar ppid getpid getppid sys unistd LD threads
 % LocalWords:  void ForkTest tempnam pathname sibling cap errno EAGAIN ENOMEM
 % LocalWords:  stack read only copy write tab client spawn forktest sleep PATH
 % LocalWords:  source LIBRARY scheduling race condition printf descriptor dup
@@ -3072,9 +3480,14 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso
 % LocalWords:  waitid NOCLDSTOP ENOCHLD WIFCONTINUED ifdef endif idtype siginfo
 % 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 RTPRIO
+% LocalWords:  Completely Fair compat Uniform CFQ Queuing elevator dev cfq RT
+% LocalWords:  Documentation block syscall ioprio IPRIO CLASS class best effort
+% LocalWords:  refresh semop dnotify MADV DONTFORK prctl WCLONE SIGCHL WALL
+% LocalWords:  WNOTHREAD DUMPABLE KEEPCAPS
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
-% LocalWords:  next cat for COMMAND pts bash defunct