+\label{sec:proc_perms}
+
+In questa sezione esamineremo le problematiche relative al controllo di
+accesso dal punto di vista del processi; vedremo quali sono gli identificatori
+usati, come questi possono essere modificati nella creazione e nel lancio di
+nuovi processi, le varie funzioni per la loro manipolazione diretta e tutte le
+problematiche connesse ad una gestione accorta dei privilegi.
+
+
+\subsection{Gli identificatori del controllo di accesso}
+\label{sec:proc_access_id}
+
+Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in
+ realtà già esistono estensioni di questo modello base, che lo rendono più
+ flessibile e controllabile, come le \textit{capabilities}, le ACL per i file
+ o il \textit{Mandatory Access Control} di SELinux; inoltre basandosi sul
+ lavoro effettuato con SELinux, a partire dal kernel 2.5.x, è iniziato lo
+ sviluppo di una infrastruttura di sicurezza, il \textit{Linux Security
+ Modules}, o LSM, in grado di fornire diversi agganci a livello del kernel
+ per modularizzare tutti i possibili controlli di accesso.} di sicurezza di
+un sistema unix-like è fondato sui concetti di utente e gruppo, e sulla
+separazione fra l'amministratore (\textsl{root}, detto spesso anche
+\textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli
+utenti, per i quali invece vengono effettuati i vari controlli di accesso.
+
+%Benché il sistema sia piuttosto semplice (è basato su un solo livello di
+% separazione) il sistema permette una
+%notevole flessibilità,
+
+Abbiamo già accennato come il sistema associ ad ogni utente e gruppo due
+identificatori univoci, lo user-ID ed il group-ID; questi servono al kernel per
+identificare uno specifico utente o un gruppo di utenti, per poi poter
+controllare che essi siano autorizzati a compiere le operazioni richieste. Ad
+esempio in \secref{sec:file_access_control} vedremo come ad ogni file vengano
+associati un utente ed un gruppo (i suoi \textsl{proprietari}, indicati
+appunto tramite un \acr{uid} ed un \acr{gid}) che vengono controllati dal
+kernel nella gestione dei permessi di accesso.
+
+Dato che tutte le operazioni del sistema vengono compiute dai processi, è
+evidente che per poter implementare un controllo sulle operazioni occorre
+anche poter identificare chi è che ha lanciato un certo programma, e pertanto
+anche a ciascun processo dovrà essere associato ad un utente e ad un gruppo.
+
+Un semplice controllo di una corrispondenza fra identificativi non garantisce
+però sufficiente flessibilità per tutti quei casi in cui è necessario poter
+disporre di privilegi diversi, o dover impersonare un altro utente per un
+limitato insieme di operazioni. Per questo motivo in generale tutti gli Unix
+prevedono che i processi abbiano almeno due gruppi di identificatori, chiamati
+rispettivamente \textit{real} ed \textit{effective} (cioè \textsl{reali} ed
+\textsl{effettivi}). Nel caso di Linux si aggiungono poi altri due gruppi, il
+\textit{saved} (\textsl{salvati}) ed il \textit{filesystem} (\textsl{di
+ filesystem}), secondo la situazione illustrata in \tabref{tab:proc_uid_gid}.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|c|c|l|p{7.3cm}|}
+ \hline
+ \textbf{Suffisso} & \textbf{Gruppo} & \textbf{Denominazione}
+ & \textbf{Significato} \\
+ \hline
+ \hline
+ \acr{uid} & \textit{real} & \textsl{user-ID reale}
+ & indica l'utente che ha lanciato il programma\\
+ \acr{gid} & '' &\textsl{group-ID reale}
+ & indica il gruppo principale dell'utente che ha lanciato
+ il programma \\
+ \hline
+ \acr{euid} & \textit{effective} &\textsl{user-ID effettivo}
+ & indica l'utente usato nel controllo di accesso \\
+ \acr{egid} & '' & \textsl{group-ID effettivo}
+ & indica il gruppo usato nel controllo di accesso \\
+ -- & -- & \textsl{group-ID supplementari}
+ & indicano gli ulteriori gruppi cui l'utente appartiene \\
+ \hline
+ -- & \textit{saved} & \textsl{user-ID salvato}
+ & è una copia dell'\acr{euid} iniziale\\
+ -- & '' & \textsl{group-ID salvato}
+ & è una copia dell'\acr{egid} iniziale \\
+ \hline
+ \acr{fsuid} & \textit{filesystem} &\textsl{user-ID di filesystem}
+ & indica l'utente effettivo per l'accesso al filesystem \\
+ \acr{fsgid} & '' & \textsl{group-ID di filesystem}
+ & indica il gruppo effettivo per l'accesso al filesystem \\
+ \hline
+ \end{tabular}
+ \caption{Identificatori di utente e gruppo associati a ciascun processo con
+ indicazione dei suffissi usati dalle varie funzioni di manipolazione.}
+ \label{tab:proc_uid_gid}
+\end{table}
+
+Al primo gruppo appartengono l'\textsl{user-ID reale} ed il \textsl{group-ID
+ reale}: questi vengono impostati al login ai valori corrispondenti
+all'utente con cui si accede al sistema (e relativo gruppo principale).
+Servono per l'identificazione dell'utente e normalmente non vengono mai
+cambiati. In realtà vedremo (in \secref{sec:proc_setuid}) che è possibile
+modificarli, ma solo ad un processo che abbia i privilegi di amministratore;
+questa possibilità è usata proprio dal programma \cmd{login} che, una volta
+completata la procedura di autenticazione, lancia una shell per la quale
+imposta questi identificatori ai valori corrispondenti all'utente che entra
+nel sistema.
+
+Al secondo gruppo appartengono lo \textsl{user-ID effettivo} ed il
+\textsl{group-ID effettivo} (a cui si aggiungono gli eventuali \textsl{group-ID
+ supplementari} dei gruppi dei quali l'utente fa parte). Questi sono invece
+gli identificatori usati nella verifiche dei permessi del processo e per il
+controllo di accesso ai file (argomento affrontato in dettaglio in
+\secref{sec:file_perm_overview}).
+
+Questi identificatori normalmente sono identici ai corrispondenti del gruppo
+\textit{real} tranne nel caso in cui, come accennato in
+\secref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit
+\acr{suid} o \acr{sgid} impostati (il significato di questi bit è affrontato
+in dettaglio in \secref{sec:file_suid_sgid}). In questo caso essi saranno
+impostati all'utente e al gruppo proprietari del file. Questo consente, per
+programmi in cui ci sia necessità, di dare a qualunque utente normale
+privilegi o permessi di un'altro (o dell'amministratore).
+
+Come nel caso del \acr{pid} e del \acr{ppid}, anche tutti questi
+identificatori possono essere letti attraverso le rispettive funzioni:
+\funcd{getuid}, \funcd{geteuid}, \funcd{getgid} e \funcd{getegid}, i loro
+prototipi sono:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{sys/types.h}
+ \funcdecl{uid\_t getuid(void)} Restituisce l'\textsl{user-ID reale} del
+ processo corrente.
+
+ \funcdecl{uid\_t geteuid(void)} Restituisce l'\textsl{user-ID effettivo} del
+ processo corrente.
+
+ \funcdecl{gid\_t getgid(void)} Restituisce il \textsl{group-ID reale} del
+ processo corrente.
+
+ \funcdecl{gid\_t getegid(void)} Restituisce il \textsl{group-ID effettivo}
+ del processo corrente.
+
+ \bodydesc{Queste funzioni non riportano condizioni di errore.}
+\end{functions}
+
+In generale l'uso di privilegi superiori deve essere limitato il più
+possibile, per evitare abusi e problemi di sicurezza, per questo occorre anche
+un meccanismo che consenta ad un programma di rilasciare gli eventuali
+maggiori privilegi necessari, una volta che si siano effettuate le operazioni
+per i quali erano richiesti, e a poterli eventualmente recuperare in caso
+servano di nuovo.
+
+Questo in Linux viene fatto usando altri gli altri due gruppi di
+identificatori, il \textit{saved} ed il \textit{filesystem}. Il primo gruppo è
+lo stesso usato in SVr4, e previsto dallo standard POSIX quando è definita la
+costante \macro{\_POSIX\_SAVED\_IDS},\footnote{in caso si abbia a cuore la
+ portabilità del programma su altri Unix è buona norma controllare sempre la
+ disponibilità di queste funzioni controllando se questa costante è
+ definita.} il secondo gruppo è specifico di Linux e viene usato per
+migliorare la sicurezza con NFS.
+
+L'\textsl{user-ID salvato} ed il \textsl{group-ID salvato} sono copie
+dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo} del processo
+padre, e vengono impostati dalla funzione \func{exec} all'avvio del processo,
+come copie dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo}
+dopo che questo sono stati impostati tenendo conto di eventuali \acr{suid} o
+\acr{sgid}. Essi quindi consentono di tenere traccia di quale fossero utente
+e gruppo effettivi all'inizio dell'esecuzione di un nuovo programma.
+
+L'\textsl{user-ID di filesystem} e il \textsl{group-ID di filesystem} sono
+un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS
+(torneremo sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una
+replica dei corrispondenti identificatori del gruppo \textit{effective}, ai
+quali si sostituiscono per tutte le operazioni di verifica dei permessi
+relativi ai file (trattate in \secref{sec:file_perm_overview}). Ogni
+cambiamento effettuato sugli identificatori effettivi viene automaticamente
+riportato su di essi, per cui in condizioni normali si può tranquillamente
+ignorarne l'esistenza, in quanto saranno del tutto equivalenti ai precedenti.
+
+
+\subsection{Le funzioni \func{setuid} e \func{setgid}}
+\label{sec:proc_setuid}
+
+Le due funzioni che vengono usate per cambiare identità (cioè utente e gruppo
+di appartenenza) ad un processo sono rispettivamente \funcd{setuid} e
+\funcd{setgid}; come accennato in \secref{sec:proc_access_id} in Linux esse
+seguono la semantica POSIX che prevede l'esistenza dell'\textit{user-ID
+ salvato} e del \textit{group-ID salvato}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int setuid(uid\_t uid)} Imposta l'\textsl{user-ID} del processo
+corrente.
+
+\funcdecl{int setgid(gid\_t gid)} Imposta il \textsl{group-ID} del processo
+corrente.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \errval{EPERM}.}
+\end{functions}
+
+Il funzionamento di queste due funzioni è analogo, per cui considereremo solo
+la prima; la seconda si comporta esattamente allo stesso modo facendo
+riferimento al \textsl{group-ID} invece che all'\textsl{user-ID}. Gli
+eventuali \textsl{group-ID supplementari} non vengono modificati.
+
+L'effetto della chiamata è diverso a seconda dei privilegi del processo; se
+l'\textsl{user-ID effettivo} è zero (cioè è quello dell'amministratore di
+sistema) allora tutti gli identificatori (\textit{real}, \textit{effective} e
+\textit{saved}) vengono impostati al valore specificato da \param{uid},
+altrimenti viene impostato solo l'\textsl{user-ID effettivo}, e soltanto se il
+valore specificato corrisponde o all'\textsl{user-ID reale} o
+all'\textsl{user-ID salvato}. Negli altri casi viene segnalato un errore (con
+\errcode{EPERM}).
+
+Come accennato l'uso principale di queste funzioni è quello di poter
+consentire ad un programma con i bit \acr{suid} o \acr{sgid} impostati (vedi
+\secref{sec:file_suid_sgid}) di riportare l'\textsl{user-ID effettivo} a quello
+dell'utente che ha lanciato il programma, effettuare il lavoro che non
+necessita di privilegi aggiuntivi, ed eventualmente tornare indietro.
+
+Come esempio per chiarire l'uso di queste funzioni prendiamo quello con cui
+viene gestito l'accesso al file \file{/var/log/utmp}. In questo file viene
+registrato chi sta usando il sistema al momento corrente; chiaramente non può
+essere lasciato aperto in scrittura a qualunque utente, che potrebbe
+falsificare la registrazione. Per questo motivo questo file (e l'analogo
+\file{/var/log/wtmp} su cui vengono registrati login e logout) appartengono ad
+un gruppo dedicato (\acr{utmp}) ed i programmi che devono accedervi (ad
+esempio tutti i programmi di terminale in X, o il programma \cmd{screen} che
+crea terminali multipli su una console) appartengono a questo gruppo ed hanno
+il bit \acr{sgid} impostato.
+
+Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato, la
+situazione degli identificatori è la seguente:
+\begin{eqnarray*}
+ \label{eq:1}
+ \textsl{group-ID reale} &=& \textrm{\acr{gid} (del chiamante)} \\
+ \textsl{group-ID effettivo} &=& \textrm{\acr{utmp}} \\
+ \textsl{group-ID salvato} &=& \textrm{\acr{utmp}}
+\end{eqnarray*}
+in questo modo, dato che il \textsl{group-ID effettivo} è quello giusto, il
+programma può accedere a \file{/var/log/utmp} in scrittura ed aggiornarlo. A
+questo punto il programma può eseguire una \code{setgid(getgid())} per
+impostare il \textsl{group-ID effettivo} a quello dell'utente (e dato che il
+\textsl{group-ID reale} corrisponde la funzione avrà successo), in questo modo
+non sarà possibile lanciare dal terminale programmi che modificano detto file,
+in tal caso infatti la situazione degli identificatori sarebbe:
+\begin{eqnarray*}
+ \label{eq:2}
+ \textsl{group-ID reale} &=& \textrm{\acr{gid} (invariato)} \\
+ \textsl{group-ID effettivo} &=& \textrm{\acr{gid}} \\
+ \textsl{group-ID salvato} &=& \textrm{\acr{utmp} (invariato)}
+\end{eqnarray*}
+e ogni processo lanciato dal terminale avrebbe comunque \acr{gid} come
+\textsl{group-ID effettivo}. All'uscita dal terminale, per poter di nuovo
+aggiornare lo stato di \file{/var/log/utmp} il programma eseguirà una
+\code{setgid(utmp)} (dove \var{utmp} è il valore numerico associato al gruppo
+\acr{utmp}, ottenuto ad esempio con una precedente \func{getegid}), dato che
+in questo caso il valore richiesto corrisponde al \textsl{group-ID salvato} la
+funzione avrà successo e riporterà la situazione a:
+\begin{eqnarray*}
+ \label{eq:3}
+ \textsl{group-ID reale} &=& \textrm{\acr{gid} (invariato)} \\
+ \textsl{group-ID effettivo} &=& \textrm{\acr{utmp}} \\
+ \textsl{group-ID salvato} &=& \textrm{\acr{utmp} (invariato)}
+\end{eqnarray*}
+consentendo l'accesso a \file{/var/log/utmp}.
+
+Occorre però tenere conto che tutto questo non è possibile con un processo con
+i privilegi di root, in tal caso infatti l'esecuzione una \func{setuid}
+comporta il cambiamento di tutti gli identificatori associati al processo,
+rendendo impossibile riguadagnare i privilegi di amministratore. Questo
+comportamento è corretto per l'uso che ne fa \cmd{login} una volta che crea
+una nuova shell per l'utente; ma quando si vuole cambiare soltanto
+l'\textsl{user-ID effettivo} del processo per cedere i privilegi occorre
+ricorrere ad altre funzioni (si veda ad esempio \secref{sec:proc_seteuid}).
+
+
+\subsection{Le funzioni \func{setreuid} e \func{setresuid}}
+\label{sec:proc_setreuid}
+
+Queste due funzioni derivano da BSD che, non supportando\footnote{almeno fino
+ alla versione 4.3+BSD TODO, FIXME verificare e aggiornare la nota.} gli
+identificatori del gruppo \textit{saved}, le usa per poter scambiare fra di
+loro \textit{effective} e \textit{real}. I loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Imposta l'\textsl{user-ID
+ reale} e l'\textsl{user-ID effettivo} del processo corrente ai valori
+specificati da \param{ruid} e \param{euid}.
+
+\funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Imposta il \textsl{group-ID
+ reale} ed il \textsl{group-ID effettivo} del processo corrente ai valori
+specificati da \param{rgid} e \param{egid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \errval{EPERM}.}
+\end{functions}
+
+La due funzioni sono analoghe ed il loro comportamento è identico; quanto
+detto per la prima prima riguardo l'user-ID, si applica immediatamente alla
+seconda per il group-ID. I processi non privilegiati possono impostare solo i
+valori del loro user-ID effettivo o reale; valori diversi comportano il
+fallimento della chiamata; l'amministratore invece può specificare un valore
+qualunque. Specificando un argomento di valore -1 l'identificatore
+corrispondente verrà lasciato inalterato.
+
+Con queste funzioni si possono scambiare fra loro gli user-ID reale e
+effettivo, e pertanto è possibile implementare un comportamento simile a
+quello visto in precedenza per \func{setgid}, cedendo i privilegi con un primo
+scambio, e recuperandoli, eseguito il lavoro non privilegiato, con un secondo
+scambio.
+
+In questo caso però occorre porre molta attenzione quando si creano nuovi
+processi nella fase intermedia in cui si sono scambiati gli identificatori, in
+questo caso infatti essi avranno un user-ID reale privilegiato, che dovrà
+essere esplicitamente eliminato prima di porre in esecuzione un nuovo
+programma (occorrerà cioè eseguire un'altra chiamata dopo la \func{fork} e
+prima della \func{exec} per uniformare l'user-ID reale a quello effettivo) in
+caso contrario il nuovo programma potrebbe a sua volta effettuare uno scambio
+e riottenere privilegi non previsti.
+
+Lo stesso problema di propagazione dei privilegi ad eventuali processi figli
+si pone per l'user-ID salvato: questa funzione deriva da un'implementazione che
+non ne prevede la presenza, e quindi non è possibile usarla per correggere la
+situazione come nel caso precedente. Per questo motivo in Linux tutte le volte
+che si imposta un qualunque valore diverso da quello dall'user-ID reale
+corrente, l'user-ID salvato viene automaticamente uniformato al valore
+dell'user-ID effettivo.
+
+
+\subsection{Le funzioni \funcd{seteuid} e \funcd{setegid}}
+\label{sec:proc_seteuid}
+
+Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
+supportate dalla maggior parte degli Unix) e vengono usate per cambiare gli
+identificatori del gruppo \textit{effective}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int seteuid(uid\_t uid)} Imposta l'user-ID effettivo del processo
+corrente a \param{uid}.
+
+\funcdecl{int setegid(gid\_t gid)} Imposta il group-ID effettivo del processo
+corrente a \param{gid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore è \errval{EPERM}.}
+\end{functions}
+
+Come per le precedenti le due funzioni sono identiche, per cui tratteremo solo
+la prima. Gli utenti normali possono impostare l'user-ID effettivo solo al
+valore dell'user-ID reale o dell'user-ID salvato, l'amministratore può
+specificare qualunque valore. Queste funzioni sono usate per permettere
+all'amministratore di impostare solo l'user-ID effettivo, dato che l'uso
+normale di \func{setuid} comporta l'impostazione di tutti gli identificatori.
+
+
+\subsection{Le funzioni \funcd{setresuid} e \funcd{setresgid}}
+\label{sec:proc_setresuid}
+
+Queste due funzioni sono un'estensione introdotta in Linux dal kernel 2.1.44,
+e permettono un completo controllo su tutti gli identificatori (\textit{real},
+\textit{effective} e \textit{saved}), i prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Imposta
+l'user-ID reale, l'user-ID effettivo e l'user-ID salvato del processo corrente
+ai valori specificati rispettivamente da \param{ruid}, \param{euid} e
+\param{suid}.
+
+\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Imposta il
+group-ID reale, il group-ID effettivo ed il group-ID salvato del processo
+corrente ai valori specificati rispettivamente da \param{rgid}, \param{egid} e
+\param{sgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore è \errval{EPERM}.}
+\end{functions}
+
+Le due funzioni sono identiche, quanto detto per la prima riguardo gli user-ID
+si applica alla seconda per i group-ID. I processi non privilegiati possono
+cambiare uno qualunque degli user-ID solo ad un valore corrispondente o
+all'user-ID reale, o a quello effettivo o a quello salvato, l'amministratore
+può specificare i valori che vuole; un valore di -1 per un qualunque parametro
+lascia inalterato l'identificatore corrispondente.
+
+Per queste funzioni esistono anche due controparti che permettono di leggere
+in blocco i vari identificatori: \funcd{getresuid} e \funcd{getresgid}; i loro
+prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int getresuid(uid\_t *ruid, uid\_t *euid, uid\_t *suid)} Legge
+l'user-ID reale, l'user-ID effettivo e l'user-ID salvato del processo corrente.
+
+\funcdecl{int getresgid(gid\_t *rgid, gid\_t *egid, gid\_t *sgid)} Legge il
+group-ID reale, il group-ID effettivo e il group-ID salvato del processo
+corrente.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+ fallimento: l'unico errore possibile è \errval{EFAULT} se gli indirizzi delle
+ variabili di ritorno non sono validi.}
+\end{functions}
+
+Anche queste funzioni sono un'estensione specifica di Linux, e non richiedono
+nessun privilegio. I valori sono restituiti negli argomenti, che vanno
+specificati come puntatori (è un'altro esempio di \textit{value result
+ argument}). Si noti che queste funzioni sono le uniche in grado di leggere
+gli identificatori del gruppo \textit{saved}.
+
+
+\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
+\label{sec:proc_setfsuid}
+
+Queste funzioni sono usate per impostare gli identificatori del gruppo
+\textit{filesystem} che usati da Linux per il controllo dell'accesso ai file.
+Come già accennato in \secref{sec:proc_access_id} Linux definisce questo
+ulteriore gruppo di identificatori, che di norma sono assolutamente
+equivalenti a quelli del gruppo \textit{effective}, dato che ogni cambiamento
+di questi ultimi viene immediatamente riportato su di essi.
+
+C'è un solo caso in cui si ha necessità di introdurre una differenza fra gli
+identificatori dei gruppi \textit{effective} e \textit{filesystem}, ed è per
+ovviare ad un problema di sicurezza che si presenta quando si deve
+implementare un server NFS. Il server NFS infatti deve poter cambiare
+l'identificatore con cui accede ai file per assumere l'identità del singolo
+utente remoto, ma se questo viene fatto cambiando l'user-ID effettivo o
+l'user-ID reale il server si espone alla ricezione di eventuali segnali ostili
+da parte dell'utente di cui ha temporaneamente assunto l'identità. Cambiando
+solo l'user-ID di filesystem si ottengono i privilegi necessari per accedere ai
+file, mantenendo quelli originari per quanto riguarda tutti gli altri
+controlli di accesso, così che l'utente non possa inviare segnali al server
+NFS.
+
+Le due funzioni usate per cambiare questi identificatori sono \funcd{setfsuid}
+e \funcd{setfsgid}, ovviamente sono specifiche di Linux e non devono essere
+usate se si intendono scrivere programmi portabili; i loro prototipi sono:
+\begin{functions}
+\headdecl{sys/fsuid.h}
+
+\funcdecl{int setfsuid(uid\_t fsuid)} Imposta l'user-ID di filesystem del
+processo corrente a \param{fsuid}.
+
+\funcdecl{int setfsgid(gid\_t fsgid)} Imposta il group-ID di filesystem del
+processo corrente a \param{fsgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \errval{EPERM}.}
+\end{functions}
+\noindent queste funzioni hanno successo solo se il processo chiamante ha i
+privilegi di amministratore o, per gli altri utenti, se il valore specificato
+coincide con uno dei di quelli del gruppo \textit{real}, \textit{effective} o
+\textit{saved}.
+
+
+\subsection{Le funzioni \func{setgroups} e \func{getgroups}}
+\label{sec:proc_setgroups}
+
+Le ultime funzioni che esamineremo sono quelle che permettono di operare sui
+gruppi supplementari. Ogni processo può avere fino a \const{NGROUPS\_MAX}
+gruppi supplementari in aggiunta al gruppo primario, questi vengono ereditati
+dal processo padre e possono essere cambiati con queste funzioni.
+
+La funzione che permette di leggere i gruppi supplementari è
+\funcd{getgroups}; questa funzione è definita nello standard POSIX ed il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{unistd.h}
+
+ \funcdecl{int getgroups(int size, gid\_t list[])}
+
+ Legge gli identificatori dei gruppi supplementari.
+
+ \bodydesc{La funzione restituisce il numero di gruppi letti 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{EINVAL}] il valore di \param{size} è diverso da zero ma
+ minore del numero di gruppi supplementari del processo.
+ \end{errlist}}
+\end{functions}
+
+La funzione legge gli identificatori dei gruppi supplementari del processo sul
+vettore \param{list} di dimensione \param{size}. Non è specificato se la
+funzione inserisca o meno nella lista il group-ID effettivo del processo. Se si
+specifica un valore di \param{size} uguale a 0 \param{list} non viene
+modificato, ma si ottiene il numero di gruppi supplementari.
+
+Una seconda funzione, \funcd{getgrouplist}, può invece essere usata per
+ottenere tutti i gruppi a cui appartiene un utente; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int getgrouplist(const char *user, gid\_t group, gid\_t *groups,
+ int *ngroups)} Legge i gruppi supplementari.
+
+ \bodydesc{La funzione legge fino ad un massimo di \param{ngroups} valori,
+ restituisce 0 in caso di successo e -1 in caso di fallimento.}
+\end{functions}
+
+La funzione legge i gruppi supplementari dell'utente \param{user} eseguendo
+una scansione del database dei gruppi (si veda \secref{sec:sys_user_group}) e
+ritorna in \param{groups} la lista di quelli a cui l'utente appartiene. Si
+noti che \param{ngroups} è passato come puntatore perché qualora il valore
+specificato sia troppo piccolo la funzione ritorna -1, passando indietro il
+numero dei gruppi trovati.
+
+Per impostare i gruppi supplementari di un processo ci sono due funzioni, che
+possono essere usate solo se si hanno i privilegi di amministratore. La prima
+delle due è \funcd{setgroups}, ed il suo prototipo è:
+\begin{functions}
+ \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
+\secref{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
+\file{/etc/groups}) 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}.
+
+
+\section{La gestione della priorità di esecuzione}
+\label{sec:proc_priority}
+
+In questa sezione tratteremo più approfonditamente i meccanismi con il quale
+lo \textit{scheduler}\index{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.
+
+
+\subsection{I meccanismi di \textit{scheduling}}
+\label{sec:proc_sched}
+
+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 \textit{prehemptive multitasking}: questo significa che al
+contrario di altri sistemi (che usano invece il cosiddetto \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
+\secref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione
+apposita del kernel, lo \textit{scheduler}\index{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
+\tabref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato
+\textit{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.8cm}|c|p{10cm}|}
+ \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 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. \\
+ \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
+\secref{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
+\secref{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, 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 tutti i processi ordinari hanno la stessa priorità
+assoluta. Quello che determina quale, fra tutti i processi in attesa di
+esecuzione, sarà eseguito per primo, è la priorità dinamica, che è chiamata
+così proprio perché varia nel corso dell'esecuzione di un processo. Oltre a
+questo la priorità dinamica determina quanto a lungo un processo continuerà ad
+essere eseguito, e quando un processo potrà subentrare ad un altro
+nell'esecuzione.
+
+Il meccanismo usato da Linux è piuttosto semplice, ad ogni processo è
+assegnata una \textit{time-slice}, cioè in intervallo di tempo (letteralmente
+una fetta) per il quale esso deve essere eseguito. Il valore della
+\textit{time-slice} è controllato dalla cosiddetta \textit{nice} (o
+\textit{niceness}) del processo. Essa è contenuta nel campo \var{nice} di
+\struct{task\_struct}; tutti i processi vengono creati con lo stesso valore,
+ed essa specifica il valore della durata iniziale della \textit{time-slice}
+che viene assegnato ad un altro campo della struttura (\var{counter}) quando
+il processo viene eseguito per la prima volta e diminuito progressivamente ad
+ogni interruzione del timer.
+
+Quando lo scheduler\index{scheduler} viene eseguito scandisce la coda dei
+processi in stato \textit{runnable} associando, sulla base del valore di
+\var{counter}, un peso a ciascun processo in attesa di esecuzione,\footnote{il
+ calcolo del peso in realtà è un po' più complicato, ad esempio nei sistemi
+ multiprocessore viene favorito un processo che è eseguito sulla stessa CPU,
+ e a parità del valore di \var{counter} viene favorito chi ha una priorità
+ più elevata.} chi ha il peso più alto verrà posto in esecuzione, ed il
+precedente processo sarà spostato in fondo alla coda. Dato che ad ogni
+interruzione del timer il valore di \var{counter} del processo corrente viene
+diminuito, questo assicura che anche i processi con priorità più bassa
+verranno messi in esecuzione.
+
+La priorità di un processo è così controllata attraverso il valore di
+\var{nice}, che stabilisce la durata della \textit{time-slice}; per il
+meccanismo appena descritto infatti un valore più lungo infatti 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 è:
+\begin{prototype}{unistd.h}
+{int nice(int inc)}
+ Aumenta il valore di \var{nice} per il processo corrente.
+
+ \bodydesc{La funzione ritorna zero in caso 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.
+ \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.
+
+In SUSv2 la funzione ritorna il nuovo valore di \var{nice}; Linux non segue
+questa convenzione, e per leggere il nuovo valore occorre invece usare la
+funzione \funcd{getpriority}, derivata da BSD, il cui 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 (in 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 di leggere la priorità di un processo, di un gruppo di
+processi (vedi \secref{sec:sess_proc_group}) o di un utente, a seconda del
+valore di \param{which}, secondo la legenda di \tabref{tab:proc_getpriority},
+specificando un corrispondente valore per \param{who}; 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 \secref{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 poterlo 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 \secref{sec:proc_mem_lock}), il primo
+non è superabile e può comportare ritardi non prevedibili riguardo ai tempi di
+esecuzione di qualunque processo.
+
+In ogni caso 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
+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{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 (vale solo per \const{SCHED\_FIFO} e
+ \const{SCHED\_RR}).
+ \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.
+Solo un processo con i privilegi di amministratore può impostare delle
+priorità assolute diverse da zero. La politica di scheduling è specificata
+dall'argomento \param{policy} i cui possibili valori sono riportati in
+\tabref{tab:proc_sched_policy}; un valore negativo per \param{policy} mantiene
+la politica di scheduling corrente.
+
+\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 \figref{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}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct sched_param {
+ int sched_priority;
+};
+ \end{lstlisting}
+ \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} è invalido.
+ \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 la quanto elencato in
+\tabref{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 \figref{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.
+
+
+\section{Problematiche di programmazione multitasking}
+\label{sec:proc_multi_prog}
+
+Benché i processi siano strutturati in modo da apparire il più possibile come
+indipendenti l'uno dall'altro, nella programmazione in un sistema multitasking
+occorre tenere conto di una serie di problematiche che normalmente non
+esistono quando si ha a che fare con un sistema in cui viene eseguito un solo
+programma alla volta.
+
+Pur essendo questo argomento di carattere generale, ci è parso opportuno
+introdurre sinteticamente queste problematiche, che ritroveremo a più riprese
+in capitoli successivi, in questa sezione conclusiva del capitolo in cui
+abbiamo affrontato la gestione dei processi.
+
+
+\subsection{Le operazioni atomiche}
+\label{sec:proc_atom_oper}
+
+La nozione di \textsl{operazione atomica} deriva dal significato greco della
+parola atomo, cioè indivisibile; si dice infatti che un'operazione è atomica
+quando si ha la certezza che, qualora essa venga effettuata, tutti i passaggi
+che devono essere compiuti per realizzarla verranno eseguiti senza possibilità
+di interruzione in una fase intermedia.
+
+In un ambiente multitasking il concetto è essenziale, dato che un processo può
+essere interrotto in qualunque momento dal kernel che mette in esecuzione un
+altro processo o dalla ricezione di un segnale; occorre pertanto essere
+accorti nei confronti delle possibili
+\textit{race condition}\index{race condition} (vedi
+\secref{sec:proc_race_cond}) derivanti da operazioni interrotte in una fase in
+cui non erano ancora state completate.
+
+Nel caso dell'interazione fra processi la situazione è molto più semplice, ed
+occorre preoccuparsi della atomicità delle operazioni solo quando si ha a che
+fare con meccanismi di intercomunicazione (che esamineremo in dettaglio in
+\capref{cha:IPC}) o nelle operazioni con i file (vedremo alcuni esempi in
+\secref{sec:file_atomic}). In questi casi in genere l'uso delle appropriate
+funzioni di libreria per compiere le operazioni necessarie è garanzia
+sufficiente di atomicità in quanto le system call con cui esse sono realizzate
+non possono essere interrotte (o subire interferenze pericolose) da altri
+processi.
+
+Nel caso dei segnali invece la situazione è molto più delicata, in quanto lo
+stesso processo, e pure alcune system call, possono essere interrotti in
+qualunque momento, e le operazioni di un eventuale \textit{signal handler}
+sono compiute nello stesso spazio di indirizzi del processo. Per questo, anche
+il solo accesso o l'assegnazione di una variabile possono non essere più
+operazioni atomiche (torneremo su questi aspetti in
+\secref{sec:sig_control}).
+
+In questo caso il sistema provvede un tipo di dato, il \type{sig\_atomic\_t},
+il cui accesso è assicurato essere atomico. In pratica comunque si può
+assumere che, in ogni piattaforma su cui è implementato Linux, il tipo
+\ctyp{int}, gli altri interi di dimensione inferiore ed i puntatori sono
+atomici. Non è affatto detto che lo stesso valga per interi di dimensioni
+maggiori (in cui l'accesso può comportare più istruzioni in assembler) o per
+le strutture. In tutti questi casi è anche opportuno marcare come
+\direct{volatile} le variabili che possono essere interessate ad accesso
+condiviso, onde evitare problemi con le ottimizzazioni del codice.
+
+
+
+\subsection{Le \textit{race condition}\index{race condition} e i
+ \textit{deadlock}\index{deadlock}}
+\label{sec:proc_race_cond}
+
+Si definiscono \textit{race condition}\index{race condition} tutte quelle
+situazioni in cui processi diversi operano su una risorsa comune, ed in cui il
+risultato viene a dipendere dall'ordine in cui essi effettuano le loro
+operazioni. Il caso tipico è quello di un'operazione che viene eseguita da un
+processo in più passi, e può essere compromessa dall'intervento di un altro
+processo che accede alla stessa risorsa quando ancora non tutti i passi sono
+stati completati.
+
+Dato che in un sistema multitasking ogni processo può essere interrotto in
+qualunque momento per farne subentrare un'altro in esecuzione, niente può
+assicurare un preciso ordine di esecuzione fra processi diversi o che una
+sezione di un programma possa essere eseguita senza interruzioni da parte di
+altri. Queste situazioni comportano pertanto errori estremamente subdoli e
+difficili da tracciare, in quanto nella maggior parte dei casi tutto
+funzionerà regolarmente, e solo occasionalmente si avranno degli errori.
+
+Per questo occorre essere ben consapevoli di queste problematiche, e del fatto
+che l'unico modo per evitarle è quello di riconoscerle come tali e prendere
+gli adeguati provvedimenti per far sì che non si verifichino. Casi tipici di
+\textit{race condition}\index{race condition} si hanno quando diversi processi
+accedono allo stesso file, o nell'accesso a meccanismi di intercomunicazione
+come la memoria condivisa. In questi casi, se non si dispone della possibilità
+di eseguire atomicamente le operazioni necessarie, occorre che quelle parti di
+codice in cui si compiono le operazioni sulle risorse condivise (le cosiddette
+\textsl{sezioni critiche}\index{sezioni critiche}) del programma, siano
+opportunamente protette da meccanismi di sincronizzazione (torneremo su queste
+problematiche di questo tipo in \capref{cha:IPC}).
+
+Un caso particolare di \textit{race condition}\index{race condition} sono poi
+i cosiddetti \textit{deadlock}\index{deadlock}, particolarmente gravi in
+quanto comportano spesso il blocco completo di un servizio, e non il
+fallimento di una singola operazione. Per definizione un
+\textit{deadlock}\index{deadlock} è una situazione in cui due o più processi
+non sono più in grado di proseguire perché ciascuno aspetta il risultato di
+una operazione che dovrebbe essere eseguita dall'altro.
+
+
+L'esempio tipico di una situazione che può condurre ad un
+\textit{deadlock}\index{deadlock} è quello in cui un flag di
+``\textsl{occupazione}'' viene rilasciato da un evento asincrono (come un
+segnale o un altro processo) fra il momento in cui lo si è controllato
+(trovandolo occupato) e la successiva operazione di attesa per lo sblocco. In
+questo caso, dato che l'evento di sblocco del flag è avvenuto senza che ce ne
+accorgessimo proprio fra il controllo e la messa in attesa, quest'ultima
+diventerà perpetua (da cui il nome di \textit{deadlock}\index{deadlock}).
+
+In tutti questi casi è di fondamentale importanza il concetto di atomicità
+visto in \secref{sec:proc_atom_oper}; questi problemi infatti possono essere
+risolti soltanto assicurandosi, quando essa sia richiesta, che sia possibile
+eseguire in maniera atomica le operazioni necessarie.
+
+
+\subsection{Le funzioni rientranti}
+\label{sec:proc_reentrant}
+
+Si dice \textsl{rientrante} una funzione che può essere interrotta in
+qualunque punto della sua esecuzione ed essere chiamata una seconda volta da
+un altro thread di esecuzione senza che questo comporti nessun problema
+nell'esecuzione della stessa. La problematica è comune nella programmazione
+multi-thread, ma si hanno gli stessi problemi quando si vogliono chiamare
+delle funzioni all'interno dei gestori dei segnali.
+
+Fintanto che una funzione opera soltanto con le variabili locali è rientrante;
+queste infatti vengono allocate nello stack, e un'altra invocazione non fa
+altro che allocarne un'altra copia. Una funzione può non essere rientrante
+quando opera su memoria che non è nello stack. Ad esempio una funzione non è
+mai rientrante se usa una variabile globale o statica.