+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int setgroups(size\_t size, gid\_t *list)}
+
+ Imposta i gruppi supplementari del processo.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ fallimento, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EFAULT}] \param{list} non ha un indirizzo valido.
+ \item[\errcode{EPERM}] il processo non ha i privilegi di amministratore.
+ \item[\errcode{EINVAL}] il valore di \param{size} è maggiore del valore
+ massimo consentito.
+ \end{errlist}}
+\end{functions}
+
+La funzione imposta i gruppi supplementari del processo corrente ai valori
+specificati nel vettore passato con l'argomento \param{list}, di dimensioni
+date dall'argomento \param{size}. Il numero massimo di gruppi supplementari è
+un parametro di sistema, che può essere ricavato con le modalità spiegate in
+sez.~\ref{sec:sys_characteristics}.
+
+Se invece si vogliono impostare i gruppi supplementari del processo a quelli di
+un utente specifico, si può usare \funcd{initgroups} il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int initgroups(const char *user, gid\_t group)}
+
+ Inizializza la lista dei gruppi supplementari.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ fallimento, nel qual caso \var{errno} assumerà gli stessi valori di
+ \func{setgroups} più \errval{ENOMEM} quando non c'è memoria sufficiente
+ per allocare lo spazio per informazioni dei gruppi.}
+\end{functions}
+
+La funzione esegue la scansione del database dei gruppi (usualmente
+\conffile{/etc/group}) cercando i gruppi di cui è membro l'utente \param{user}
+con cui costruisce una lista di gruppi supplementari, a cui aggiunge anche
+\param{group}, infine imposta questa lista per il processo corrente usando
+\func{setgroups}. Si tenga presente che sia \func{setgroups} che
+\func{initgroups} non sono definite nello standard POSIX.1 e che pertanto non
+è possibile utilizzarle quando si definisce \macro{\_POSIX\_SOURCE} o si
+compila con il flag \cmd{-ansi}, è pertanto meglio evitarle se si vuole
+scrivere codice portabile.
+
+
+\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. Tratteremo infine anche le altre priorità dei processi (come quelle
+per l'accesso a disco) divenute disponibili con i kernel più recenti.
+
+
+\subsection{I meccanismi di \textit{scheduling}}
+\label{sec:proc_sched}
+
+\itindbeg{scheduler}
+
+La scelta di un meccanismo che sia in grado di distribuire in maniera efficace
+il tempo di CPU per l'esecuzione dei processi è sempre una questione delicata,
+ed oggetto di numerose ricerche; in generale essa dipende in maniera
+essenziale anche dal tipo di utilizzo che deve essere fatto del sistema, per
+cui non esiste un meccanismo che sia valido per tutti gli usi.
+
+La caratteristica specifica di un sistema multitasking come Linux è quella del
+cosiddetto \itindex{preemptive~multitasking} \textit{preemptive
+ multitasking}: questo significa che al contrario di altri sistemi (che usano
+invece il cosiddetto \itindex{cooperative~multitasking} \textit{cooperative
+ multitasking}) non sono i singoli processi, ma il kernel stesso a decidere
+quando la CPU deve essere passata ad un altro processo. Come accennato in
+sez.~\ref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione
+apposita del kernel, lo \textit{scheduler}, il cui scopo è quello di
+distribuire al meglio il tempo di CPU fra i vari processi.
+
+La cosa è resa ancora più complicata dal fatto che con le architetture
+multi-processore si deve anche scegliere quale sia la CPU più opportuna da
+utilizzare.\footnote{nei processori moderni la presenza di ampie cache può
+ rendere poco efficiente trasferire l'esecuzione di un processo da una CPU ad
+ un'altra, per cui effettuare la migliore scelta fra le diverse CPU non è
+ banale.} Tutto questo comunque appartiene alle sottigliezze
+dell'implementazione del kernel; dal punto di vista dei programmi che girano
+in user space, anche quando si hanno più processori (e dei processi che sono
+eseguiti davvero in contemporanea), le politiche di scheduling riguardano
+semplicemente l'allocazione della risorsa \textsl{tempo di esecuzione}, la cui
+assegnazione sarà governata dai meccanismi di scelta delle priorità che
+restano gli stessi indipendentemente dal numero di processori.
+
+Si tenga conto poi che i processi non devono solo eseguire del codice: ad
+esempio molto spesso saranno impegnati in operazioni di I/O, o potranno
+venire bloccati da un comando dal terminale, o sospesi per un certo periodo di
+tempo. In tutti questi casi la CPU diventa disponibile ed è compito dello
+kernel provvedere a mettere in esecuzione un altro processo.
+
+Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del
+processo, in Linux un processo può trovarsi in uno degli stati riportati in
+tab.~\ref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato
+\textbf{Runnable} concorrono per l'esecuzione. Questo vuol dire che, qualunque
+sia la sua priorità, un processo non potrà mai essere messo in esecuzione
+fintanto che esso si trova in uno qualunque degli altri stati.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \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).\\
+ \textbf{Sleep} & \texttt{S} & Il processo è in attesa di un
+ risposta dal sistema, ma può essere
+ 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.\\
+ \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
+ suo stato di terminazione non è ancora
+ stato letto dal padre.\\
+ \textbf{Killable}& \texttt{D} & Un nuovo stato introdotto con il kernel
+ 2.6.25, sostanzialmente identico
+ all'\textbf{Uninterrutible Sleep} con la
+ sola differenza che il processo può
+ 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
+ \texttt{STAT} si è riportata la corrispondente lettera usata dal comando
+ \cmd{ps} nell'omonimo campo.}
+ \label{tab:proc_proc_states}
+\end{table}
+
+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
+programmi dipendono in maniera molto più critica dall'I/O). Per questo motivo
+non è affatto detto che dare ad un programma la massima priorità di esecuzione
+abbia risultati significativi in termini di prestazioni.
+
+Il meccanismo tradizionale di scheduling di Unix (che tratteremo in
+sez.~\ref{sec:proc_sched_stand}) è sempre stato basato su delle
+\textsl{priorità dinamiche}, in modo da assicurare che tutti i processi, anche
+i meno importanti, possano ricevere un po' di tempo di CPU. In sostanza quando
+un processo ottiene la CPU la sua priorità viene diminuita. In questo modo
+alla fine, anche un processo con priorità iniziale molto bassa, finisce per
+avere una priorità sufficiente per essere eseguito.
+
+Lo standard POSIX.1b però ha introdotto il concetto di \textsl{priorità
+ assoluta}, (chiamata anche \textsl{priorità statica}, in contrapposizione
+alla normale priorità dinamica), per tenere conto dei sistemi
+real-time,\footnote{per sistema real-time si intende un sistema in grado di
+ eseguire operazioni in un tempo ben determinato; in genere si tende a
+ distinguere fra l'\textit{hard real-time} in cui è necessario che i tempi di
+ esecuzione di un programma siano determinabili con certezza assoluta (come
+ nel caso di meccanismi di controllo di macchine, dove uno sforamento dei
+ tempi avrebbe conseguenze disastrose), e \textit{soft-real-time} in cui un
+ occasionale sforamento è ritenuto accettabile.} in cui è vitale che i
+processi che devono essere eseguiti in un determinato momento non debbano
+aspettare la conclusione di altri che non hanno questa necessità.
+
+Il concetto di priorità assoluta dice che quando due processi si contendono
+l'esecuzione, vince sempre quello con la priorità assoluta più alta.
+Ovviamente questo avviene solo per i processi che sono pronti per essere
+eseguiti (cioè nello stato \textit{runnable}). La priorità assoluta viene in
+genere indicata con un numero intero, ed un valore più alto comporta una
+priorità maggiore. Su questa politica di scheduling torneremo in
+sez.~\ref{sec:proc_real_time}.
+
+In generale quello che succede in tutti gli Unix moderni è che ai processi
+normali viene sempre data una priorità assoluta pari a zero, e la decisione di
+assegnazione della CPU è fatta solo con il meccanismo tradizionale della
+priorità dinamica. In Linux tuttavia è possibile assegnare anche una priorità
+assoluta, nel qual caso un processo avrà la precedenza su tutti gli altri di
+priorità inferiore, che saranno eseguiti solo quando quest'ultimo non avrà
+bisogno della CPU.
+
+
+\subsection{Il meccanismo di \textit{scheduling} standard}
+\label{sec:proc_sched_stand}
+
+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
+una priorità assoluta nulla; quello che determina quale, fra tutti i processi
+in attesa di esecuzione, sarà eseguito per primo, è la cosiddetta
+\textsl{priorità dinamica},\footnote{quella che viene mostrata nella colonna
+ \texttt{PR} del comando \texttt{top}.} che è chiamata così proprio perché
+varia nel corso dell'esecuzione di un processo.
+
+Il meccanismo usato da Linux è in realtà piuttosto complesso,\footnote{e
+ dipende strettamente dalla versione di kernel; in particolare a partire
+ dalla serie 2.6.x lo scheduler è stato riscritto completamente, con molte
+ modifiche susseguitesi per migliorarne le prestazioni, per un certo periodo
+ 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 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.
+
+ \bodydesc{La funzione ritorna zero o il nuovo valore di \var{nice} in caso
+ di successo e -1 in caso di errore, nel qual caso \var{errno} può assumere
+ i valori:
+ \begin{errlist}
+ \item[\errcode{EPERM}] non si ha il permesso di specificare un valore
+ di \param{inc} negativo.
+ \end{errlist}}
+\end{prototype}
+
+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 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
+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 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)}
+
+Restituisce il valore di \var{nice} per l'insieme dei processi specificati.
+
+ \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}] non c'è nessun processo che corrisponda ai valori di
+ \param{which} e \param{who}.
+ \item[\errcode{EINVAL}] il valore di \param{which} non è valido.
+ \end{errlist}}
+\end{prototype}
+\noindent nelle vecchie versioni può essere necessario includere anche
+\file{<sys/time.h>}, questo non è più necessario con versioni recenti delle
+librerie, ma è comunque utile per portabilità.
+
+La funzione permette, a seconda del valore di \param{which}, di leggere la
+priorità di un processo, di un gruppo di processi (vedi
+sez.~\ref{sec:sess_proc_group}) o di un utente, specificando un corrispondente
+valore per \param{who} secondo la legenda di tab.~\ref{tab:proc_getpriority};
+un valore nullo di quest'ultimo indica il processo, il gruppo di processi o
+l'utente correnti.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|c|c|l|}
+ \hline
+ \param{which} & \param{who} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{PRIO\_PROCESS} & \type{pid\_t} & processo \\
+ \const{PRIO\_PRGR} & \type{pid\_t} & \itindex{process~group}
+ \textit{process group} \\
+ \const{PRIO\_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{getpriority} e
+ \func{setpriority} per le tre possibili scelte.}
+ \label{tab:proc_getpriority}
+\end{table}
+
+La funzione restituisce la priorità più alta (cioè il valore più basso) fra
+quelle dei processi specificati; di nuovo, dato che $-1$ è un valore
+possibile, per poter rilevare una condizione di errore è necessario cancellare
+sempre \var{errno} prima della chiamata alla funzione per verificare che essa
+resti uguale a zero.
+
+Analoga a \func{getpriority} è la funzione \funcd{setpriority} che permette di
+impostare la priorità di uno o più processi; il suo prototipo è:
+\begin{prototype}{sys/resource.h}
+{int setpriority(int which, int who, int prio)}
+ Imposta la priorità per l'insieme dei processi specificati.
+
+ \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+ nel qual caso \var{errno} può assumere i valori:
+ \begin{errlist}
+ \item[\errcode{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
+ 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}. 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}}
+\label{sec:proc_real_time}
+
+Come spiegato in sez.~\ref{sec:proc_sched} lo standard POSIX.1b ha introdotto
+le priorità assolute per permettere la gestione di processi real-time. In
+realtà nel caso di Linux non si tratta di un vero hard real-time, in quanto in
+presenza di eventuali interrupt il kernel interrompe l'esecuzione di un
+processo qualsiasi sia la sua priorità,\footnote{questo a meno che non si
+ siano installate le patch di RTLinux, RTAI o Adeos, con i quali è possibile
+ ottenere un sistema effettivamente hard real-time. In tal caso infatti gli
+ interrupt vengono intercettati dall'interfaccia real-time (o nel caso di
+ Adeos gestiti dalle code del nano-kernel), in modo da poterli controllare
+ direttamente qualora ci sia la necessità di avere un processo con priorità
+ più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un
+\itindex{page~fault} \textit{page fault} si possono avere ritardi non
+previsti. Se l'ultimo problema può essere aggirato attraverso l'uso delle
+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.
+
+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à
+eseguito per primo quello con priorità assoluta più alta. Quando ci sono più
+processi con la stessa priorità assoluta questi vengono tenuti in una coda e
+tocca al kernel decidere quale deve essere eseguito. Il meccanismo con cui
+vengono gestiti questi processi dipende dalla politica di scheduling che si è
+scelta; lo standard ne prevede due:
+\begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\textsf{FIFO}] \textit{First In First Out}. Il processo viene eseguito
+ fintanto che non cede volontariamente la CPU (con \func{sched\_yield}), si
+ blocca, finisce o viene interrotto da un processo a priorità più alta. Se il
+ processo viene interrotto da uno a priorità più alta esso resterà in cima
+ alla lista e sarà il primo ad essere eseguito quando i processi a priorità
+ più alta diverranno inattivi. Se invece lo si blocca volontariamente sarà
+ posto in coda alla lista (ed altri processi con la stessa priorità potranno
+ essere eseguiti).
+\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
+ 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 \textbf{Runnable} entrano nel
+ \textsl{girotondo}.
+\end{basedescript}
+
+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 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{policy} non esiste o il
+ relativo valore di \param{p} non è valido.
+ \item[\errcode{EPERM}] il processo non ha i privilegi per attivare la
+ politica richiesta.
+ \end{errlist}}
+\end{prototype}
+
+La funzione esegue l'impostazione per il processo specificato dall'argomento
+\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
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Policy} & \textbf{Significato} \\
+ \hline
+ \hline
+ \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.\footnotemark\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{policy} per la funzione
+ \func{sched\_setscheduler}.}
+ \label{tab:proc_sched_policy}
+\end{table}
+
+\footnotetext[44]{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{minipage}[c]{15cm}
+ \includestruct{listati/sched_param.c}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{sched\_param}.}
+ \label{fig:sig_sched_param}
+\end{figure}