+I processi non privilegiati possono cambiare uno qualunque degli
+identificatori usando uno qualunque dei valori correnti di \textit{real id},
+\textit{effective id} o \textit{saved id}, 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: \func{getresuid} e \func{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 il
+\textit{real user id}, l'\textit{effective user id} e il \textit{saved user
+ id} del processo corrente.
+
+\funcdecl{int getresgid(gid\_t *rgid, gid\_t *egid, gid\_t *sgid)} Legge il
+\textit{real group id}, l'\textit{effective group id} e il \textit{saved group
+ id} del processo corrente.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+ fallimento: l'unico errore possibile è \macro{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 i
+\textit{saved id}.
+
+
+\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
+\label{sec:proc_setfsuid}
+
+Queste funzioni sono usate per settare gli identificatori usati da Linux per
+il controllo dell'accesso ai file. Come già accennato in
+\secref{sec:proc_access_id} in Linux è definito questo ulteriore gruppo di
+identificatori, che di norma sono assolutamente equivalenti agli
+\textit{effective id}, dato che ogni cambiamento di questi ultimi viene
+immediatamente riportato sui \textit{filesystem id}.
+
+C'è un solo caso in cui si ha necessità di introdurre una differenza fra
+\textit{effective id} e \textit{filesystem id}, 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'\textit{effective id} o il \textit{real id} il server si
+espone alla ricezione di eventuali segnali ostili da parte dell'utente di cui
+ha temporaneamente assunto l'identità. Cambiando solo il \textit{filesystem
+ id} 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 \func{setfsuid}
+e \func{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)} Setta il \textit{filesystem user id} del
+processo corrente a \var{fsuid}.
+
+\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group id} del
+processo corrente a \var{fsgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \macro{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 \textit{real}, \textit{effective} o \textit{saved id}.
+
+
+\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 \macro{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 è \func{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 del processo sul vettore \param{list} di dimensione
+ \param{size}.
+
+ \bodydesc{La funzione restituisce il numero di gruppi letti in caso di
+ successo e -1 in caso di fallimento, nel qual caso \var{errno} viene
+ settata a:
+ \begin{errlist}
+ \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
+ \item[\macro{EINVAL}] il valore di \param{size} è diverso da zero ma
+ minore del numero di gruppi supplementari del processo.
+ \end{errlist}}
+\end{functions}
+\noindent non è specificato se la funzione inserisca o meno nella lista
+l'\textit{effective user id} 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, \func{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 dell'utente \param{user}.
+
+ \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}
+\noindent la funzione esegue 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 settare 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 è \func{setgroups}, ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int setgroups(size\_t size, gid\_t *list)} Setta i gruppi
+ supplementari del processo ai valori specificati in \param{list}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ fallimento, nel qual caso \var{errno} viene settata a:
+ \begin{errlist}
+ \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
+ \item[\macro{EPERM}] il processo non ha i privilegi di amministratore.
+ \item[\macro{EINVAL}] il valore di \param{size} è maggiore del valore
+ massimo (\macro{NGROUPS}, che per Linux è 32).
+ \end{errlist}}
+\end{functions}
+
+Se invece si vogliono settare i gruppi supplementari del processo a quelli di
+un utente specifico, si può usare \func{initgroups} il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int initgroups(const char *user, gid\_t group)} Setta i gruppi
+ supplementari del processo a quelli di cui è membro l'utente \param{user},
+ aggiungendo il gruppo addizionale \param{group}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ fallimento, nel qual caso \var{errno} viene settata agli stessi valori di
+ \func{setgroups} più \macro{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 \param{user} e
+costruendo una lista di gruppi supplementari a cui aggiunge \param{group}, che
+poi setta 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}\footnote{che è la parte del kernel che si occupa di
+ stabilire quale processo dovrà essere posto in esecuzione.} 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 ogni caso essa dipende in maniera
+essenziale anche dal tipo di utilizzo che deve essere fatto del sistema.
+
+Si tenga presente comunque che l'utilizzo della CPU è soltanto una delle
+risorse (insieme alla memoria e all'accesso alle periferiche) che sono
+necessarie per l'esecuzione di un programma, e spesso non è neanche la più
+importante. Per questo non è affatto detto che dare ad un programma la massima
+priorità di esecuzione abbia risultati significativi in termini di
+prestazioni.
+
+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 dallo
+\textit{scheduler} il cui scopo è quello di distribuire al meglio il tempo di
+CPU fra i vari processi.
+
+Il Linux un processo può trovarsi in uno degli stati riportati in
+
+
+
+\begin{table}[htb]
+ \centering
+ \begin{tabular}[c]{|l|c|p{8cm}|}
+ \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
+ \macro{SIGSTOP}, o è tracciato.\\
+ \textbf{Zombie} & \texttt{Z} & Il processo è terminato ma il suo stato di
+ terminazione non è ancora stato letto dal padre. \\
+ \hline
+ \end{tabular}
+ \caption{Tabella degli stati possibili per processo in Linux, si sono
+ riportati nella colonna \texttt{STAT} i valori dello stato ottenibili
+ dall'output del comando \cmd{ps}.}
+ \label{tab:proc_proc_states}
+\end{table}
+
+
+
+
+Una delle caratteristiche c
+
+,\footnote{lo stato di un processo
+ è riportato nel campo \texttt{STAT} dell'output del comando \cmd{ps},
+ abbiamo già visto che lo stato di \textit{zombie} è indicato con \texttt{Z},
+ gli stati \textit{runnable}, \textit{sleep} e di I/O (\textit{uninteruttible
+ sleep}) sono invece indicati con \texttt{R}, \texttt{S} e \texttt{D}.})
+la priorità assoluta viene invece ignorata per quelli che sono bloccati su una
+richiesta di I/O o in stato di \textit{sleep}
+
+
+La cosa è resa ancora più complicata dal fatto che con le architetture
+multi-processore si introduce anche la problematica dovuta alla scelta di
+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 occorrono
+ meccanismi per determinare quale è la migliore scelta fra le diverse CPU.}
+Tutto questo comunque appartiene alle sottigliezze dell'implementazione del
+kernel, e 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), si può pensare alle politiche di scheduling come concernenti
+la risorsa \textsl{tempo di esecuzione}, la cui assegnazione sarà governata
+dagli stessi meccanismi di scelta di priorità, solo che nel caso di più
+processori sarà a disposizione di più di un processo alla volta.
+
+
+
+
+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, anche
+quando l'altro è in esecuzione (grazie al \textit{prehemptive scheduling}).
+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 in base ad una priorità dinamica che è
+calcolata indipendentemente. È 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.
+
+
+
+
+\subsection{Il meccanismo di \textit{scheduling real-time}}
+\label{sec:proc_real_time}
+
+Per settare le
+
+
+\footnote{a meno che non si siano installate le patch di RTLinux o RTAI, con i
+ quali è possibile ottenere un sistema effettivamente hard real-time.}
+
+in realtà non si tratta di un vero hard real-time, in quanto
+ la presenza di eventuali interrupt o di page fault può sempre interrompere
+ l'esecuzione di un processo, a meno di non installare le estensioni di
+ RTLinux o RTAI, il normale kernel non è real-time.
+
+
+
+
+
+\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} (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:sign_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
+\type{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
+\type{volatile} le variabili che possono essere interessate ad accesso
+condiviso, onde evitare problemi con le ottimizzazioni del codice.
+
+
+\subsection{Le \textit{race condition} e i \textit{deadlock}}
+\label{sec:proc_race_cond}