Aggiornamento dello scheduling realtime, con varie correzioni.
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 13 Jun 2009 17:55:03 +0000 (17:55 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 13 Jun 2009 17:55:03 +0000 (17:55 +0000)
biblio.bib
prochand.tex

index 53ba68aec13b968c111d3a57c573a00f2df8cb9a..65f7318358715cc496477c3576bbeae597bc538f 100644 (file)
   OPTyear =     {},
   OPTnote =     {},
   OPTannote =   {}
   OPTyear =     {},
   OPTnote =     {},
   OPTannote =   {}
-}
\ No newline at end of file
+}
+@Book{LinuxNutshell,
+  author =       {Greg Kroah-Hartman},
+  editor =       {O'Reilly},
+  title =        {Linux kernel in a Nutshell},
+  publisher =    {O'Reilly},
+  year =         {2006},
+  OPTkey =       {},
+  OPTvolume =    {1},
+  OPTnumber =    {},
+  OPTseries =    {},
+  OPTaddress =   {},
+  OPTedition =   {},
+  OPTmonth =     {},
+  OPTnote =      {},
+  OPTannote =    {}
+}
+@Book{LinKernDev,
+  author =       {Robert Love},
+  editor =       {O'Reilly},
+  title =        {Linux Kernel Development},
+  publisher =    {O'Reilly},
+  year =         {},
+  OPTkey =       {},
+  OPTvolume =    {1},
+  OPTnumber =    {},
+  OPTseries =    {},
+  OPTaddress =   {},
+  OPTedition =   {},
+  OPTmonth =     {},
+  OPTnote =      {},
+  OPTannote =    {}
+}
index 27d7d064b490e5f7736568c417d4593fc1475829..510e69ac8f11c3262149395d7b955f753e1c93cc 100644 (file)
@@ -494,7 +494,7 @@ avendo cos
 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
 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
 
 Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
 processi completamente separati, le modifiche delle variabili nei processi
@@ -629,7 +629,8 @@ comune dopo l'esecuzione di una \func{fork} 
 \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 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
+\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*}
   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*}
@@ -2230,7 +2231,8 @@ bisogno della CPU.
 \subsection{Il meccanismo di \textit{scheduling} standard}
 \label{sec:proc_sched_stand}
 
 \subsection{Il meccanismo di \textit{scheduling} standard}
 \label{sec:proc_sched_stand}
 
-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
 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 +2249,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
   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.
 \begin{prototype}{unistd.h}
 {int nice(int inc)}
   Aumenta il valore di \var{nice} per il processo corrente.
@@ -2288,42 +2300,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}
     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}
 
   \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
 
 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
 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
 \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)}
   
 \begin{prototype}{sys/resource.h}
 {int getpriority(int which, int who)}
   
@@ -2386,22 +2406,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{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
   \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
     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}}
 
 
 \subsection{Il meccanismo di \textit{scheduling real-time}}
@@ -2424,14 +2465,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.
 
 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à
 
 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 +2503,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
 \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
   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}
 
   \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.
   
 \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.
     di errore, nel qual caso \var{errno} può assumere i valori:
     \begin{errlist}
     \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
@@ -2478,14 +2530,12 @@ prototipo 
 \end{prototype}
 
 La funzione esegue l'impostazione per il processo specificato dall'argomento
 \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
 
 \begin{table}[htb]
   \centering
@@ -2498,10 +2548,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}. \\
     \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\_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
     \hline
   \end{tabular}
   \caption{Valori dell'argomento \param{policy} per la funzione
@@ -2509,14 +2561,41 @@ da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}.
   \label{tab:proc_sched_policy}
 \end{table}
 
   \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
 
 \begin{figure}[!bht]
   \footnotesize \centering
@@ -2528,11 +2607,11 @@ nullo 
   \label{fig:sig_sched_param}
 \end{figure}
 
   \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
 
 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 +2629,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
   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}
 
     \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
 
 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
 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.
 
 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}
 
 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.
     \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}
 
   \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
 \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.
     \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}
 
 \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
 
 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
 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:
   
   \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 +2751,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.
 
 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)} 
   
 \begin{prototype}{sched.h}
   {int sched\_yield(void)} 
   
@@ -2662,12 +2763,14 @@ volontariamente la CPU; questo viene fatto attraverso la funzione
     nel qual caso \var{errno} viene impostata opportunamente.}
 \end{prototype}
 
     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 in modalità \textit{fifo}, per permettere
+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
 
 % 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
@@ -3030,7 +3133,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:  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
 % 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 +3175,10 @@ 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:  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
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
-% LocalWords:  next cat for COMMAND pts bash defunct