seguente la \func{fork}; il processo figlio è però una copia del padre, e
riceve una copia dei segmenti di testo, stack e dati (vedi
\secref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del
-padre, ma la memoria è copiata, non condivisa\footnote{In generale il segmento
+padre, ma la memoria è copiata, non condivisa,\footnote{In generale il segmento
di testo, che è identico, è condiviso e tenuto in read-only, Linux poi
utilizza la tecnica del \textit{copy-on-write}, per cui la memoria degli
altri segmenti viene copiata dal kernel per il nuovo processo solo in caso
di scrittura, rendendo molto più efficiente il meccanismo della creazione di
- un nuovo processo.}, pertanto padre e figlio vedono variabili diverse.
+ un nuovo processo.} pertanto padre e figlio vedono variabili diverse.
La differenza che si ha nei due processi è che nel processo padre il valore di
ritorno della funzione \func{fork} è il \acr{pid} del processo figlio, mentre
\item la directory di lavoro e la directory radice (vedi
\secref{sec:file_work_dir} e \secref{sec:file_chroot}).
\item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
-\item la maschera dei segnali bloccati e le azioni installate (vedi
-\secref{sec:sig_xxx}).
+\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigpending}) e le
+ azioni installate (vedi \secref{sec:sig_gen_beha}).
\item i segmenti di memoria condivisa agganciati al processo (vedi
\secref{sec:ipc_xxx}).
\item i limiti sulle risorse (vedi \secref{sec:sys_xxx}).
nel figlio sono posti a zero.
\item i \textit{file lock} (vedi \secref{sec:file_locking}), che non
vengono ereditati dal figlio.
-\item gli allarmi ed i segnali pendenti (vedi \secref{sec:sig_xxx}), che per il figlio vengono cancellati.
+\item gli allarmi ed i segnali pendenti (vedi \secref{sec:sig_gen_beha}), che
+ per il figlio vengono cancellati.
\end{itemize*}
\subsection{Le funzioni \func{wait3} e \func{wait4}}
\label{sec:proc_wait4}
-Linux, seguendo una estensione di BSD, supporta altre due funzioni,
-\func{wait} e \func{waitpd}, per la lettura dello stato di terminazione di un
-processo, analoghe alle precedenti ma che prevedono un ulteriore parametro
-attraverso il quale il kernel può restituire al padre informazioni sulle
-risorse usate dal processo terminato e dai vari figli. I prototipi di queste
-funzioni, che diventano accessibili definendo la costante \macro{\_USE\_BSD},
-sono:
+Linux, seguendo una estensione di BSD, supporta altre due funzioni per la
+lettura dello stato di terminazione di un processo \func{wait3} e
+\func{wait4}, analoghe alle precedenti ma che prevedono un ulteriore
+parametro attraverso il quale il kernel può restituire al padre informazioni
+sulle risorse usate dal processo terminato e dai vari figli. I prototipi di
+queste funzioni, che diventano accessibili definendo la costante
+\macro{\_USE\_BSD}, sono:
\begin{functions}
\headdecl{sys/times.h}
\headdecl{sys/types.h}
\begin{errlist}
\item[\macro{EACCES}] il file non è eseguibile, oppure il filesystem è
montato in \cmd{noexec}, oppure non è un file normale o un interprete.
- \item[\macro{EPERM}] il file ha i bit \acr{suid} o \acr{sgid} ma l'utente non
- è root o il filesystem è montato con \cmd{nosuid}, oppure
+ \item[\macro{EPERM}] il file ha i bit \acr{suid} o \acr{sgid}, l'utente non
+ è root, e o il processo viene tracciato, o il filesystem è montato con
+ l'opzione \cmd{nosuid}.
\item[\macro{ENOEXEC}] il file è in un formato non eseguibile o non
riconosciuto come tale, o compilato per un'altra architettura.
\item[\macro{ENOENT}] il file o una delle librerie dinamiche o l'interprete
\secref{sec:file_umask}) ed i \textit{lock} sui file (vedi
\secref{sec:file_locking}).
\item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
- \secref{sec:sig_xxx}).
+ \secref{sec:sig_sigpending}).
\item i limiti sulle risorse (vedi \secref{sec:sys_limits}).
\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
\var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}).
tutti gli altri segnali vengono settati alla loro azione di default. Un caso
speciale è il segnale \macro{SIGCHLD} che, quando settato a \macro{SIG\_IGN},
può anche non essere resettato a \macro{SIG\_DFL} (si veda
-\secref{sec:sig_xxx}).
+\secref{sec:sig_gen_beha}).
-La gestione dei file aperti dipende dal valore del flag di
-\textit{close-on-exec} per ciascun file descriptor (si veda
-\secref{sec:file_fcntl}); i file per cui è settato vengono chiusi, tutti gli
-altri file restano aperti. Questo significa che il comportamento di default è
-che i file restano aperti attraverso una \func{exec}, a meno di una chiamata
-esplicita a \func{fcntl} che setti il suddetto flag.
+La gestione dei file aperti dipende dal valore che ha il flag di
+\textit{close-on-exec} (trattato in \secref{sec:file_fcntl}) per ciascun file
+descriptor. I file per cui è settato vengono chiusi, tutti gli altri file
+restano aperti. Questo significa che il comportamento di default è che i file
+restano aperti attraverso una \func{exec}, a meno di una chiamata esplicita a
+\func{fcntl} che setti il suddetto flag.
Per le directory lo standard POSIX.1 richiede che esse vengano chiuse
attraverso una \func{exec}, in genere questo è fatto dalla funzione
Abbiamo detto che il \textit{real user id} ed il \textit{real group id}
restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per
-l'\textit{effective user id} ed l'\textit{effective group id}, tranne il caso
-in cui il file che si va ad eseguire ha o il \acr{suid} bit o lo \acr{sgid}
-bit settato, nel qual caso \textit{effective user id} e \textit{effective
+l'\textit{effective user id} ed l'\textit{effective group id}, tranne quando
+il file che si va ad eseguire abbia o il \acr{suid} bit o lo \acr{sgid} bit
+settato, in questo caso l'\textit{effective user id} e l'\textit{effective
group id} vengono settati rispettivamente all'utente o al gruppo cui il file
appartiene (per i dettagli vedi \secref{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, e le varie funzioni per la loro manipolazione diretta e tutte
-le problematiche connesse ad una gestione accorta dei privilegi.
+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}
anche poter identificare chi è che ha lanciato un certo programma, e pertanto
anche a ciascun processo è associato un utente e a un gruppo.
-Un semplice controllo di una corrispondenza fra identificativi però 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}.
+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}.
\begin{table}[htb]
\footnotesize
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 ad esempio da \cmd{login} che una volta completata la
-procedura di autenticazione lancia una shell per la quale setta questi
+possibilità è usata ad esempio da \cmd{login} che, una volta completata la
+procedura di autenticazione, lancia una shell per la quale setta questi
identificatori ai valori corrispondenti all'utente che entra nel sistema.
Al secondo gruppo appartengono l'\textit{effective user id} e
\secref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit
\acr{suid} o \acr{sgid} settati (il significato di questi bit è affrontato in
dettaglio in \secref{sec:file_suid_sgid}). In questo caso essi saranno settati
-all'utente e al gruppo proprietari del file; questo consente, per programmi in
+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).
Il funzionamento di queste due funzioni è analogo, per cui considereremo solo
la prima; la seconda si comporta esattamente allo stesso modo facendo
riferimento al \textit{group id} invece che all'\textit{user id}. Gli
-eventuali \textit{supplementary group id} non vengono modificati da nessuna
-delle funzioni che tratteremo in questa sezione.
+eventuali \textit{supplementary group id} non vengono modificati.
L'effetto della chiamata è diverso a seconda dei privilegi del processo; se
programma, effettuare il lavoro che non necessita di privilegi aggiuntivi, ed
eventualmente tornare indietro.
-Come esempio per chiarire dell'uso di queste funzioni prediamo quello con cui
+Come esempio per chiarire dell'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} settato.
+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} settato.
Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato la
situazione degli identificatori è la seguente:
\label{sec:proc_setreuid}
Queste due funzioni derivano da BSD che, non supportando\footnote{almeno fino
- alla versione 4.3+BSD TODO, verificare e aggiornare la nota.} i
+ alla versione 4.3+BSD TODO, FIXME verificare e aggiornare la nota.} i
\textit{saved id}, le usava per poter scambiare fra di loro \textit{effective}
e \textit{real id}. I loro prototipi sono:
\begin{functions}
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_xxx}) e ritorna in \param{groups} la lista di quelli a cui
-l'utente appartiene. Si noti che \param{ngroups} è passato come puntatore
+\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
e passando indietro il numero dei gruppi trovati.
\label{sec:proc_priority}
In questa sezione tratteremo più approfonditamente i meccanismi con il quale
-lo \textit{scheduler} assegna la CPU ai vari processi attivi, illustrando le
-varie funzioni che permettono di leggere e modificare le priorità di
-esecuzione dei programmi.
-
+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 prendremo in esame i vari meccanismi
+con cui viene gestita l'assgnazione 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.
+
+La cosa è resa ancora più complicata dal fatto che con sistemi
+multi-processore si introduce anche la complessità 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
+ determininare 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 di può pensare sempre
+alla risorsa tempo di esecuzione, governata dagli stessi mecca, che nel caso
+di più processori sarà a disposizione di più di un processo alla volta.
+
+Si tenga presente inoltre 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 politica tradizionale di scheduling di Unix (che tratteremo in
+\secref{sec:proc_sched_stand}) è sempre stata basata su delle priorità
+dinamiche, che assicurassaro che tutti i processi, anche i meno importanti,
+potessero ricevere un po' di tempo di CPU.
+
+Lo standard POSIX però per tenere conto dei sistemi real-time,\footnote{per
+ sistema real-time si intende un sistema in grado di eseguire operazioni in
+ tempo reale; 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 in che devono essere
+eseguiti in un determinato momento non debbano aspettare la conclusione di un
+altri processi che non hanno questa necessità, ha introdotto il concetto di
+\textsl{priorità assoluta}, chimata anche \textsl{priorità statica}, in
+contrapposizione con la normale priorità dinamica.
+
+Il concetto di prorità assoluta dice che quando due processi si contendono
+l'esecuzione, vince sempre quello con la priorità assoluta più alta, anche,
+grazie al \textit{prehemptive scheduling}, se l'altro è in esecuzione.
+Ovviamente questo avviene solo per i processi che sono pronti per essere
+eseguiti (cioè nello stato \textit{runnable}\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}.
+
+Questa viene in genere indicata con un numero
+
+
+
+
+\subsection{Il meccanismo di \textit{scheduling} standard}
+\label{sec:proc_sched_stand}
+
+In Linux tutti i processi hanno sostanzialmente la stessa priorità; benché sia
+possibile specificare una priorità assoluta secondo lo standard POSIX
+(argomento che tratteremo più avanti) l'uso comune segue quello che è il
+meccanismo tradizionale con cui i sistemi
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, in questa sezione
-conclusiva del capitolo in cui abbiamo affrontato la gestione dei processi ci
-è parso opportuno introdurre sinteticamente queste problematiche, che
-ritroveremo a più riprese in capitoli successivi, dando una breve descrizione
-delle loro caratteristiche principali e della terminologia relativa.
+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}
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 nella operazioni con i file (vedremo alcuni esempi 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
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} (e gli altri interi di dimensione inferiore) ed i puntatori sono
+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 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.
+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}}
Si definiscono \textit{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 è quella di una operazione che viene eseguita da un processo in più
+tipico è quello di una 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.
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 critiche sulle risorse condivise, le cosiddette
-\textsl{sezioni critiche} del programma, siano opportunamente protette da
+cui si compiono le operazioni sulle risorse condivise (le cosiddette
+\textsl{sezioni critiche}) del programma, siano opportunamente protette da
meccanismi di sincronizzazione (torneremo su queste problematiche di questo
tipo in \secref{sec:ipc_semaph}).
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, proteggendo con gli
-adeguati meccanismi le \textsl{sezioni critiche} del programma.
+eseguire in maniera atomica le operazioni necessarie.
\subsection{Le funzioni rientranti}