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 =   {}
-}
\ 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
-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
@@ -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 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*}
@@ -2230,7 +2231,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 +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
-  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 +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}
-  \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 +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{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 +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.
 
-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 +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
-  \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 +2530,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 +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}. \\
+    \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 +2561,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 +2607,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 +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
-    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 +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.
 
-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,12 +2763,14 @@ 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 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
@@ -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:  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 +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:  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: 
-% LocalWords:  next cat for COMMAND pts bash defunct