+ \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} & 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; 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} 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 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.
+ \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.
+
+
+
+\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
+page fault\index{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.
+
+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.
+
+Quando c'è un processo con priorità assoluta lo scheduler\index{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 è scelto; lo standard ne prevede due:
+\begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\textit{FIFO}] \textit{First In First Out}. Il processo viene eseguito
+ fintanto che non cede volontariamente la CPU, si blocca, finisce o viene
+ interrotto da un processo a priorità più alta.
+\item[\textit{RR}] \textit{Round Robin}. Ciascun processo viene eseguito a
+ turno per un certo periodo di tempo (una \textit{time slice}). Solo i
+ processi con la stessa priorità ed in stato \textit{runnable} entrano nel
+ circolo.
+\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 è:
+\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
+ 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 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 può impostare priorità
+assolute diverse da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|c|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} \\
+ \const{SCHED\_OTHER}& Scheduling ordinario\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{policy} per la funzione
+ \func{sched\_setscheduler}. }
+ \label{tab:proc_sched_policy}
+\end{table}
+
+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
+zero è legale, ma indica i processi normali).
+
+\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}
+
+Lo standard POSIX.1b prevede comunque che i due valori della massima e minima
+priorità statica possano essere ottenuti, per ciascuna delle politiche di
+scheduling realtime, tramite le due funzioni \funcd{sched\_get\_priority\_max}
+e \funcd{sched\_get\_priority\_min}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{sched.h}
+
+ \funcdecl{int sched\_get\_priority\_max(int policy)} Legge il valore
+ massimo della priorità statica per la politica di scheduling \param{policy}.
+
+
+ \funcdecl{int sched\_get\_priority\_min(int policy)} Legge il valore minimo
+ 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:
+ \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.
+
+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
+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}
+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.
+
+La priorità assoluta può essere riletta indietro dalla 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:
+ \begin{errlist}
+ \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+ \item[\errcode{EINVAL}] il valore di \param{pid} è negativo.
+ \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.
+
+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
+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\_getparam(pid\_t pid, struct sched\_param *p)}
+ Legge la priorità assoluta 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:
+ \begin{errlist}
+ \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+ \item[\errcode{EINVAL}] il valore di \param{pid} è negativo.
+ \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}.
+
+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};
+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}.
+
+ \bodydesc{La funzione ritorna 0in 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{ENOSYS}] la system call non è stata implementata.
+ \end{errlist}}
+\end{prototype}
+
+La funzione restituisce il valore dell'intervallo di tempo usato per la
+politica \textit{round robin} in una struttura \struct{timespec}, (la cui
+definizione si può trovare in fig.~\ref{fig:sys_timeval_struct}).
+
+
+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 è:
+\begin{prototype}{sched.h}
+ {int sched\_yield(void)}
+
+ Rilascia volontariamente l'esecuzione.
+
+ \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+ 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.