occasioni. NDT completare questa parte.} (ma può essere anche attivato
esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato
periodicamente, generando un interrupt periodico secondo la frequenza
-specificata dalla costante \macro{HZ}, definita in \file{asm/param.h}. Il
-valore usuale è 100\footnote{è così per tutte le architetture eccetto l'alpha,
- per la quale è 1000} ed è espresso in Hertz. Si ha cioè un interrupt dal
-timer ogni centesimo di secondo.
+specificata dalla costante \macro{HZ}, definita in \file{asm/param.h}, ed il
+cui valore è espresso in Hertz.\footnote{Il valore usuale di questa costante è
+ 100, per tutte le architetture eccetto l'alpha, per la quale è 1000. Occorre
+ fare attenzione a non confondere questo valore con quello dei clock tick
+ (vedi \secref{sec:sys_unix_time}).}
+%Si ha cioè un interrupt dal timer ogni centesimo di secondo.
Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle
priorità dei vari processi attivi (torneremo su questo in
Normalmente la chiamata a \func{fork} può fallire solo per due ragioni, o ci
sono già troppi processi nel sistema (il che di solito è sintomo che
qualcos'altro non sta andando per il verso giusto) o si è ecceduto il limite
-sul numero totale di processi permessi all'utente (vedi \secref{sec:sys_xxx}).
+sul numero totale di processi permessi all'utente (vedi
+\secref{sec:sys_resource_limit}, ed in particolare
+\tabref{tab:sys_rlimit_values}).
L'uso di \func{fork} avviene secondo due modalità principali; la prima è
quella in cui all'interno di un programma si creano processi figli cui viene
affidata l'esecuzione di una certa sezione di codice, mentre il processo padre
-ne esegue un'altra. È il caso tipico dei server di rete in cui il padre riceve
-ed accetta le richieste da parte dei client, per ciascuna delle quali pone in
-esecuzione un figlio che è incaricato di fornire il servizio.
+ne esegue un'altra. È il caso tipico dei server (il modello
+\textit{client-server} è illustrato in \secref{sec:net_cliserv}) di rete in
+cui il padre riceve ed accetta le richieste da parte dei client, per ciascuna
+delle quali pone in esecuzione un figlio che è incaricato di fornire il
+servizio.
La seconda modalità è quella in cui il processo vuole eseguire un altro
programma; questo è ad esempio il caso della shell. In questo caso il processo
descrizione delle opzioni); il codice completo, compresa la parte che gestisce
le opzioni a riga di comando, è disponibile nel file \file{ForkTest.c},
distribuito insieme agli altri sorgenti degli esempi su
-\href{http://firenze.linux.it/~piccardi/gapil_source.tgz}
-{\texttt{http://firenze.linux.it/\~~\hspace{-2.0mm}piccardi/gapil\_source.tgz}}.
+\href{http://gapil.firenze.linux.it/gapil_source.tgz}
+{\texttt{http://gapil.firenze.linux.it/gapil\_source.tgz}}.
Decifrato il numero di figli da creare, il ciclo principale del programma
(\texttt{\small 24--40}) esegue in successione la creazione dei processi figli
periodo di attesa.
Se eseguiamo il comando senza specificare attese (come si può notare in
-\texttt{\small 17--19} i valori di default specificano di non attendere),
+\texttt{\small 17--19} i valori predefiniti specificano di non attendere),
otterremo come output sul terminale:
\footnotesize
istruzioni del codice fra padre e figli, né sull'ordine in cui questi potranno
essere messi in esecuzione. Se è necessaria una qualche forma di precedenza
occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il
-rischio di incorrere nelle cosiddette \textit{race condition} \index{race
- condition} (vedi \secref{sec:proc_race_cond}.
+rischio di incorrere nelle cosiddette
+\textit{race condition}\index{race condition}
+(vedi \secref{sec:proc_race_cond}).
Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
processi completamente separati, le modifiche delle variabili nei processi
proprietà; la lista dettagliata delle proprietà che padre e figlio hanno in
comune dopo l'esecuzione di una \func{fork} è la seguente:
\begin{itemize*}
-\item i file aperti e gli eventuali flag di \textit{close-on-exec} settati
+\item i file aperti e gli eventuali flag di \textit{close-on-exec} impostati
(vedi \secref{sec:proc_exec} e \secref{sec:file_fcntl}).
\item gli identificatori per il controllo di accesso: il \textit{real user
id}, il \textit{real group id}, l'\textit{effective user id},
\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigmask}) 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}).
+\secref{sec:ipc_shar_mem}).
+\item i limiti sulle risorse (vedi \secref{sec:sys_resource_limit}).
\item le variabili di ambiente (vedi \secref{sec:proc_environ}).
\end{itemize*}
le differenze fra padre e figlio dopo la \func{fork} invece sono:
\begin{itemize*}
\item il valore di ritorno di \func{fork}.
\item il \textit{process id}.
-\item il \textit{parent process id} (quello del figlio viene settato al
+\item il \textit{parent process id} (quello del figlio viene impostato al
\acr{pid} del padre).
-\item i valori dei tempi di esecuzione (vedi \secref{sec:sys_xxx}) che
- nel figlio sono posti a zero.
+\item i valori dei tempi di esecuzione della struttura \var{tms} (vedi
+ \secref{sec:sys_cpu_times}) che 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_gen_beha}), che
\func{fork} veniva fatta solo per poi eseguire una \func{exec}. La funzione
venne introdotta in BSD per migliorare le prestazioni.
-Dato che Linux supporta il \textit{copy on write} la perdita di prestazioni è
-assolutamente trascurabile, e l'uso di questa funzione (che resta un caso
-speciale della funzione \func{clone}), è deprecato; per questo eviteremo di
-trattarla ulteriormente.
+Dato che Linux supporta il \textit{copy on write}\index{copy on write} la
+perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
+funzione (che resta un caso speciale della funzione \func{clone}), è
+deprecato; per questo eviteremo di trattarla ulteriormente.
\subsection{La conclusione di un processo.}
rispetto all'esecuzione di un programma e può avvenire in un qualunque
momento. Per questo motivo, come accennato nella sezione precedente, una delle
azioni prese dal kernel alla conclusione di un processo è quella di mandare un
-segnale di \macro{SIGCHLD} al padre. L'azione di default (si veda
+segnale di \macro{SIGCHLD} al padre. L'azione predefinita (si veda
\secref{sec:sig_base}) per questo segnale è di essere ignorato, ma la sua
generazione costituisce il meccanismo di comunicazione asincrona con cui il
kernel avverte il processo padre che uno dei suoi figli è terminato.
queste funzioni, che diventano accessibili definendo la costante
\macro{\_USE\_BSD}, sono:
\begin{functions}
- \headdecl{sys/times.h}
- \headdecl{sys/types.h}
- \headdecl{sys/wait.h}
- \headdecl{sys/resource.h}
+ \headdecl{sys/times.h} \headdecl{sys/types.h} \headdecl{sys/wait.h}
+ \headdecl{sys/resource.h}
+
\funcdecl{pid\_t wait4(pid\_t pid, int * status, int options, struct rusage
- * rusage)}
- È identica a \func{waitpid} sia per comportamento che per i
- valori dei parametri, ma restituisce in \param{rusage} un sommario delle
- risorse usate dal processo (per i dettagli vedi \secref{sec:sys_xxx})
+ * rusage)}
+ È identica a \func{waitpid} sia per comportamento che per i valori dei
+ parametri, ma restituisce in \param{rusage} un sommario delle risorse usate
+ dal processo.
\funcdecl{pid\_t wait3(int *status, int options, struct rusage *rusage)}
Prima versione, equivalente a \code{wait4(-1, \&status, opt, rusage)} è
\end{functions}
\noindent
la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene
-utilizzata anche dalla funzione \func{getrusage} (vedi \secref{sec:sys_xxx})
-per ottenere le risorse di sistema usate da un processo; la sua definizione è
-riportata in \figref{fig:sys_rusage_struct}.
-
-In genere includere esplicitamente \file{<sys/time.h>} non è più
-necessario, ma aumenta la portabilità, e serve in caso si debba accedere
-ai campi di \var{rusage} definiti come \type{struct timeval}. La
-struttura è ripresa da BSD 4.3, attualmente (con il kernel 2.4.x) i soli
-campi che sono mantenuti sono: \var{ru\_utime}, \var{ru\_stime},
-\var{ru\_minflt}, \var{ru\_majflt}, e \var{ru\_nswap}.
+utilizzata anche dalla funzione \func{getrusage} (vedi
+\secref{sec:sys_resource_use}) per ottenere le risorse di sistema usate da un
+processo; la sua definizione è riportata in \figref{fig:sys_rusage_struct}.
\subsection{Le funzioni \func{exec}}
qual caso \var{errno} può assumere i valori:
\begin{errlist}
\item[\macro{EACCES}] il file non è eseguibile, oppure il filesystem è
- montato in \cmd{noexec}, oppure non è un file normale o un interprete.
+ montato in \cmd{noexec}, oppure non è un file regolare o un interprete.
\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}.
\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_sigpending}).
-\item i limiti sulle risorse (vedi \secref{sec:sys_limits}).
+ \secref{sec:sig_sigmask}).
+\item i limiti sulle risorse (vedi \secref{sec:sys_resource_limit}).
\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
- \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}).
+ \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:sys_cpu_times}).
\end{itemize*}
-Inoltre i segnali che sono stati settati per essere ignorati nel processo
-chiamante mantengono lo stesso settaggio pure nel nuovo programma, 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_gen_beha}).
+Inoltre i segnali che sono stati impostati per essere ignorati nel processo
+chiamante mantengono la stessa impostazione pure nel nuovo programma, tutti
+gli altri segnali vengono impostati alla loro azione predefinita. Un caso
+speciale è il segnale \macro{SIGCHLD} che, quando impostato a
+\macro{SIG\_IGN}, può anche non essere reimpostato a \macro{SIG\_DFL} (si veda
+\secref{sec:sig_gen_beha}).
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
+descriptor. I file per cui è impostato vengono chiusi, tutti gli altri file
+restano aperti. Questo significa che il comportamento predefinito è che i file
restano aperti attraverso una \func{exec}, a meno di una chiamata esplicita a
-\func{fcntl} che setti il suddetto flag.
+\func{fcntl} che imposti 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
-\func{opendir} (vedi \secref{sec:file_dir_read}) che effettua da sola il
-settaggio del flag di \textit{close-on-exec} sulle directory che apre, in
+\func{opendir} (vedi \secref{sec:file_dir_read}) che effettua da sola
+l'impostazione del flag di \textit{close-on-exec} sulle directory che apre, in
maniera trasparente all'utente.
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 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
+impostato, in questo caso l'\textit{effective user id} e l'\textit{effective
+ group id} vengono impostati rispettivamente all'utente o al gruppo cui il file
appartiene (per i dettagli vedi \secref{sec:proc_perms}).
Se il file da eseguire è in formato \emph{a.out} e necessita di librerie
basata la gestione dei processi in Unix: con \func{fork} si crea un nuovo
processo, con \func{exec} si avvia un nuovo programma, con \func{exit} e
\func{wait} si effettua e verifica la conclusione dei programmi. Tutte le
-altre funzioni sono ausiliarie e servono la lettura e il settaggio dei vari
+altre funzioni sono ausiliarie e servono la lettura e l'impostazione dei vari
parametri connessi ai processi.
\end{table}
Al primo gruppo appartengono il \textit{real user id} e il \textit{real group
- id}: questi vengono settati al login ai valori corrispondenti all'utente con
-cui si accede al sistema (e relativo gruppo di default). Servono per
+ id}: 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 ad esempio da \cmd{login} che, una volta completata la
-procedura di autenticazione, lancia una shell per la quale setta questi
+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 l'\textit{effective user id} e
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} settati (il significato di questi bit è affrontato in
-dettaglio in \secref{sec:file_suid_sgid}). In questo caso essi saranno settati
+\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).
Il \textit{saved user id} e il \textit{saved group id} sono copie
dell'\textit{effective user id} e dell'\textit{effective group id} del
-processo padre, e vengono settati dalla funzione \func{exec} all'avvio del
+processo padre, e vengono impostati dalla funzione \func{exec} all'avvio del
processo, come copie dell'\textit{effective user id} e dell'\textit{effective
- group id} dopo che questo sono stati settati tenendo conto di eventuali
+ group id} 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.
\headdecl{unistd.h}
\headdecl{sys/types.h}
-\funcdecl{int setuid(uid\_t uid)} Setta l'\textit{user id} del processo
+\funcdecl{int setuid(uid\_t uid)} Imposta l'\textit{user id} del processo
corrente.
-\funcdecl{int setgid(gid\_t gid)} Setta il \textit{group id} del processo
+\funcdecl{int setgid(gid\_t gid)} Imposta il \textit{group id} del processo
corrente.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
L'effetto della chiamata è diverso a seconda dei privilegi del processo; se
l'\textit{effective user id} è zero (cioè è quello dell'amministratore di
sistema) allora tutti gli identificatori (\textit{real}, \textit{effective}
-e \textit{saved}) vengono settati al valore specificato da \var{uid},
-altrimenti viene settato solo l'\textit{effective user id}, e soltanto se il
+e \textit{saved}) vengono impostati al valore specificato da \var{uid},
+altrimenti viene impostato solo l'\textit{effective user id}, e soltanto se il
valore specificato corrisponde o al \textit{real user id} o al \textit{saved
user id}. Negli altri casi viene segnalato un errore (con \macro{EPERM}).
Come accennato l'uso principale di queste funzioni è quello di poter
-consentire ad un programma con i bit \acr{suid} o \acr{sgid} settati di
+consentire ad un programma con i bit \acr{suid} o \acr{sgid} impostati di
riportare l'\textit{effective user id} a quello dell'utente che ha lanciato il
programma, effettuare il lavoro che non necessita di privilegi aggiuntivi, ed
eventualmente tornare indietro.
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.
+il bit \acr{sgid} impostato.
Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato, la
situazione degli identificatori è la seguente:
\end{eqnarray*}
in questo modo, dato che l'\textit{effective group id} è 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 settare
+questo punto il programma può eseguire una \code{setgid(getgid())} per impostare
l'\textit{effective group id} a quello dell'utente (e dato che il \textit{real
group id} corrisponde la funzione avrà successo), in questo modo non sarà
possibile lanciare dal terminale programmi che modificano detto file, in tal
\headdecl{unistd.h}
\headdecl{sys/types.h}
-\funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Setta il \textit{real user
+\funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Imposta il \textit{real user
id} e l'\textit{effective user id} del processo corrente ai valori
specificati da \var{ruid} e \var{euid}.
-\funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Setta il \textit{real group
+\funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Imposta il \textit{real group
id} e l'\textit{effective group id} del processo corrente ai valori
specificati da \var{rgid} e \var{egid}.
di fallimento: l'unico errore possibile è \macro{EPERM}.}
\end{functions}
-I processi non privilegiati possono settare i \textit{real id} soltanto ai
+I processi non privilegiati possono impostare i \textit{real id} soltanto ai
valori dei loro \textit{effective id} o \textit{real id} e gli
\textit{effective id} ai valori dei loro \textit{real id}, \textit{effective
id} o \textit{saved id}; valori diversi comportano il fallimento della
usarle per correggere la situazione come nel caso precedente. Per questo
motivo in Linux tutte le volte che tali funzioni vengono usate per modificare
uno degli identificatori ad un valore diverso dal \textit{real id} precedente,
-il \textit{saved id} viene sempre settato al valore dell'\textit{effective
+il \textit{saved id} viene sempre impostato al valore dell'\textit{effective
id}.
\headdecl{unistd.h}
\headdecl{sys/types.h}
-\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user id} del
+\funcdecl{int seteuid(uid\_t uid)} Imposta l'\textit{effective user id} del
processo corrente a \var{uid}.
-\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group id} del
+\funcdecl{int setegid(gid\_t gid)} Imposta l'\textit{effective group id} del
processo corrente a \var{gid}.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
di fallimento: l'unico errore possibile è \macro{EPERM}.}
\end{functions}
-Gli utenti normali possono settare l'\textit{effective id} solo al valore del
+Gli utenti normali possono impostare l'\textit{effective id} solo al valore del
\textit{real id} o del \textit{saved id}, l'amministratore può specificare
-qualunque valore. Queste funzioni sono usate per permettere a root di settare
+qualunque valore. Queste funzioni sono usate per permettere a root di impostare
solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta
-il settaggio di tutti gli identificatori.
+l'impostazione di tutti gli identificatori.
\subsection{Le funzioni \func{setresuid} e \func{setresgid}}
\headdecl{unistd.h}
\headdecl{sys/types.h}
-\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Setta il
+\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Imposta il
\textit{real user id}, l'\textit{effective user id} e il \textit{saved user
id} del processo corrente ai valori specificati rispettivamente da
\var{ruid}, \var{euid} e \var{suid}.
-\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Setta il
+\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Imposta il
\textit{real group id}, l'\textit{effective group id} e il \textit{saved group
id} del processo corrente ai valori specificati rispettivamente da
\var{rgid}, \var{egid} e \var{sgid}.
\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
\label{sec:proc_setfsuid}
-Queste funzioni sono usate per settare gli identificatori usati da Linux per
+Queste funzioni sono usate per impostare 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
\begin{functions}
\headdecl{sys/fsuid.h}
-\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user id} del
+\funcdecl{int setfsuid(uid\_t fsuid)} Imposta il \textit{filesystem user id} del
processo corrente a \var{fsuid}.
-\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group id} del
+\funcdecl{int setfsgid(gid\_t fsgid)} Imposta l'\textit{filesystem group id} del
processo corrente a \var{fsgid}.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
\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:
+ impostata 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
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
+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 è \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
+ \funcdecl{int setgroups(size\_t size, gid\_t *list)} Imposta 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:
+ fallimento, nel qual caso \var{errno} viene impostata a:
\begin{errlist}
\item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
\item[\macro{EPERM}] il processo non ha i privilegi di amministratore.
\end{errlist}}
\end{functions}
-Se invece si vogliono settare i gruppi supplementari del processo a quelli di
+Se invece si vogliono impostare 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
+ \funcdecl{int initgroups(const char *user, gid\_t group)} Imposta 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
+ fallimento, nel qual caso \var{errno} viene impostata 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}.
+poi imposta 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
assegnazione sarà governata dai meccanismi di scelta delle priorità che
restano gli stessi indipendentemente dal numero di processori.
-I processi non devono solo eseguire del codice, ad esempio molto spesso
-saranno impegnati in operazioni di I/O, possono venire bloccati da un comando
-dal terminale, 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.
+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
\hline
\end{tabular}
\caption{Elenco dei possibili stati di un processo in Linux, nella colonna
- \texttt{STAT} si è riportata la corripondente lettera usata dal comando
+ \texttt{STAT} si è riportata la corrispondente lettera usata dal comando
\cmd{ps} nell'omonimo campo.}
\label{tab:proc_proc_states}
\end{table}
zero.
Analoga a \func{getpriority} la funzione \func{setpriority} permette di
-settare la priorità di uno o più processi; il suo prototipo è:
+impostare la priorità di uno o più processi; il suo prototipo è:
\begin{prototype}{sys/resource.h}
{int setpriority(int which, int who, int prio)}
- Setta la priorità per l'insieme dei processi specificati.
+ 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:
\end{errlist}}
\end{prototype}
-La funzione setta la priorità al valore specificato da \param{prio} per tutti
+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 il real o l'effective user id del processo
chiamante corrispondano al real user id (e solo quello) del processo di cui si
-vuole cambiare la prorità; per i sistemi derivati da BSD invece (SunOS,
+vuole cambiare la priorità; per i sistemi derivati da BSD invece (SunOS,
Ultrix, *BSD) la corrispondenza può essere anche con l'effective user id.
interrupt vengono intercettati dall'interfaccia real-time, e gestiti
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 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.
-
-L'interfaccia POSIX.1b comunque permette di assicurare ai processi che ne
-hanno necessità una priorità assoluta superiore a quella dei normali processi.
-In ogni caso occorre usare questo meccanismo con molta attenzione: se si dà ad
-un processo una priorità assoluta e questo finisce in un loop infinito, dato
-che fintanto che non esegue dell'I/O o viene messo in attesa nessun altro
-processo potrà essere eseguito, esso resterà esecuzione assorbendo tutto il
-tempo di esecuzione della CPU e non si avrà 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.
+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 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 due
-processi con la stessa priorità assoluta tocca al kernel decidere quale dei
-due deve essere eseguito. Questo viene fatto secondo la politica di scheduling
-che ciascuno di questi processi ha; lo standard ne prevede due:
-\begin{description}
-\item[\textit{Round robin}] ciascun processo viene eseguito a turno per un
+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{3cm}\desclabelstyle{\nextlinelabel}}
+\item[\textit{FIFO}] 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{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.
-\item[\textit{FIFO}] il processo che ha atteso di più ha la precedenza e viene
- eseguito fintanto che non cede volontariamente la CPU, si blocca, finisce o
- viene interrotto da un processo a priorità più alta.
-\end{description}
+\end{basedescript}
-La funzione per settare politica di scheduling ed i relativi parametri è
-\func{sched\_setscheduler}; il suo prototipo è:
+La funzione per impostare le politiche di scheduling (sia real-time che
+ordinarie) ed i relativi parametri è \func{sched\_setscheduler}; il suo
+prototipo è:
\begin{prototype}{sched.h}
{int sched\_setscheduler(pid\_t pid, int policy, const struct sched\_param *p)}
- Setta priorità e politica di scheduling per il processo \param{pid}.
+ Imposta priorità e politica di scheduling per il 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[\macro{ESRCH}] non c'è nessun processo che corrisponda ai valori di
- \param{which} e \param{who}.
- \item[\macro{EINVAL}] il valore di \param{which} non è valido.
- \item[\macro{EPERM}] un processo senza i privilegi di amministratore ha
- specificato un valore di \param{inc} negativo.
- \item[\macro{EACCESS}] un processo senza i privilegi di amministratore ha
- cercato di modificare la priorità di un processo di un altro utente.
+ \begin{errlist}
+ \item[\macro{ESRCH}] il processo \param{pid} non esiste.
+ \item[\macro{EINVAL}] il valore di \param{policy} non esiste o il relativo
+ valore di \param{p} non è valido.
+ \item[\macro{EPERM}] il processo non ha i privilegi per attivare la
+ politica richiesta (vale solo per \macro{SCHED\_FIFO} e
+ \macro{SCHED\_RR}).
\end{errlist}}
\end{prototype}
+La funzione esegue l'impostazione per il processo specificato; un valore nullo
+di \param{pid} 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
+ \macro{SCHED\_FIFO} & Scheduling real-time con politica \textit{FIFO} \\
+ \macro{SCHED\_RR} & Scheduling real-time con politica \textit{Round
+ Robin} \\
+ \macro{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 \var{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 1 e 99 (il valore zero è legale, ma
+indica i processi normali). Lo standard POSIX.1b prevede comunque che questi
+due valori possano essere ottenuti per ciascuna politica di scheduling dalle
+funzioni \func{sched\_get\_priority\_max} e \func{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[\macro{EINVAL}] il valore di \param{policy} è invalido.
+ \end{errlist}}
+\end{functions}
+I processi con politica di scheduling \macro{SCHED\_OTHER} devono specificare
+un valore nullo (altrimenti si avrà un errore \macro{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.
+\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 \var{sched\_param}.}
+ \label{fig:sig_sched_param}
+\end{figure}
+
+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 è \macro{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
+\func{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[\macro{ESRCH}] il processo \param{pid} non esiste.
+ \item[\macro{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 \func{sched\_setparam} e \func{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[\macro{ESRCH}] il processo \param{pid} non esiste.
+ \item[\macro{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 \macro{sched.h}.
+
+L'ultima funzione che permette di leggere le informazioni relative ai processi
+real-time è \func{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[\macro{ESRCH}] il processo \param{pid} non esiste.
+ \item[\macro{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 \var{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
+\func{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 si 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}
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
+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.
-\subsection{Le \textit{race condition} e i \textit{deadlock}}
+\subsection{Le \textit{race condition}\index{race condition} e i
+ \textit{deadlock}}
\label{sec:proc_race_cond}
Si definiscono \textit{race condition} tutte quelle situazioni in cui processi