sono stati creati, questo viene chiamato in genere \acr{ppid} (da
\textit{parent process id}). Questi due identificativi possono essere
ottenuti da programma usando le funzioni:
-
\begin{functions}
\headdecl{sys/types.h}
\headdecl{unistd.h}
\funcdecl{pid\_t getppid(void)} restituisce il pid del padre del processo
corrente.
-Entrambe le funzioni non riportano condizioni di errore.
+\bodydesc{Entrambe le funzioni non riportano condizioni di errore.}
\end{functions}
-esempi dell'uso di queste funzioni sono riportati in
+\noindent esempi dell'uso di queste funzioni sono riportati in
\figref{fig:proc_fork_code}, nel programma di esempio \file{ForkTest.c}.
Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende il
\textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di
sessione}, in cui si raggruppano i processi creati su uno stesso terminale,
o relativi allo stesso login. Torneremo su questo argomento in dettaglio in
-\secref{cap:session}, dove esamineremo gli altri identificativi associati ad
+\secref{cha:session}, dove esamineremo gli altri identificativi associati ad
un processo e le varie relazioni fra processi utilizzate per definire una
sessione.
controllo di accesso, che servono per determinare se il processo può o meno
eseguire le operazioni richieste, a seconda dei privilegi e dell'identità di
chi lo ha posto in esecuzione; su questi torneremo in dettagli più avanti in
-\secref{sec:proc_perm}.
+\secref{sec:proc_perms}.
\subsection{La funzione \func{fork}}
attraverso l'uso di questa funzione, essa quindi riveste un ruolo centrale
tutte le volte che si devono scrivere programmi che usano il multitasking. Il
prototipo della funzione è:
-
\begin{functions}
\headdecl{sys/types.h}
\headdecl{unistd.h}
ritorna -1 al padre (senza creare il figlio) in caso di errore;
\texttt{errno} può assumere i valori:
\begin{errlist}
- \item \macro{EAGAIN} non ci sono risorse sufficienti per creare un'altro
+ \item[\macro{EAGAIN}] non ci sono risorse sufficienti per creare un'altro
processo (per allocare la tabella delle pagine e le strutture del task) o
si è esaurito il numero di processi disponibili.
- \item \macro{ENOMEM} non è stato possibile allocare la memoria per le
+ \item[\macro{ENOMEM}] non è stato possibile allocare la memoria per le
strutture necessarie al kernel per creare il nuovo processo.
\end{errlist}
\end{functions}
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} se settati.
+\item i file aperti e gli eventuali flag di \textit{close-on-exec} (vedi
+\secref{sec:proc_exec} e \secref{sec:file_fcntl}) se settati.
\item gli identificatori per il controllo di accesso: il \textit{real user
id}, il \textit{real group id}, l'\textit{effective user id},
l'\textit{effective group id} e i \textit{supplementary group id} (vedi
\item la directory di lavoro e la directory radice (vedi
\secref{sec:file_work_dir}).
\item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
-\item la maschera dei segnali bloccati e le azioni installate.
-\item i segmenti di memoria condivisa agganciati al processo.
-\item i limiti sulle risorse.
+\item la maschera dei segnali bloccati e le azioni installate (vedi
+\secref{sec:sig_xxx}).
+\item i segmenti di memoria condivisa agganciati al processo (vedi
+\secref{sec:ipc_xxx}).
+\item i limiti sulle risorse (vedi \secref{sec:sys_xxx}).
\item le variabili di ambiente (vedi \secref{sec:proc_environ}).
\end{itemize*}
le differenze fra padre e figlio dopo la \func{fork} invece sono:
\item il \textit{process id}.
\item il \textit{parent process id} (quello del figlio viene settato al
\acr{pid} del padre).
-\item i valori dei tempi di esecuzione (\var{tms\_utime}, \var{tms\_stime},
- \var{tms\_cutime}, \var{tms\_uetime}) che nel figlio sono posti a zero.
-\item i \textit{file lock}, che non vengono ereditati dal figlio.
-\item gli allarmi ed i segnali pendenti, che per il figlio vengono cancellati.
+\item i valori dei tempi di esecuzione (vedi \secref{sec:sys_xxx}) 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_xxx}), che per il figlio vengono cancellati.
\end{itemize*}
\item tutti i descrittori dei file sono chiusi.
\item viene memorizzato lo stato di terminazione del processo.
\item ad ogni processo figlio viene assegnato un nuovo padre.
-\item viene inviato il segnale \macro{SIGCHLD} al processo padre.
+\item viene inviato il segnale \macro{SIGCHLD} al processo padre (vedi
+ \secref{sec:sig_xxx}) .
\item se il processo è un leader di sessione viene mandato un segnale di
- \macro{SIGHUP} a tutti i processi in background e il terminale di controllo
- viene disconnesso.
-\item se la conclusione di un processo rende orfano un \textit{process group}
- ciascun membro del gruppo viene bloccato, e poi gli vengono inviati in
- successione i segnali \macro{SIGHUP} e \macro{SIGCONT}.
+ \macro{SIGHUP} a tutti i processi in background e il terminale di
+ controllo viene disconnesso (vedi \secref{sec:sess_xxx}).
+\item se la conclusione di un processo rende orfano un \textit{process
+ group} ciascun membro del gruppo viene bloccato, e poi gli vengono
+ inviati in successione i segnali \macro{SIGHUP} e \macro{SIGCONT}
+ (vedi \secref{sec:sess_xxx}).
\end{itemize*}
ma al di la di queste operazioni è necessario poter disporre di un meccanismo
ulteriore che consenta di sapere come questa terminazione è avvenuta; dato che
Questo viene fatto mantenendo attiva la voce nella tabella dei processi, e
memorizzando alcuni dati essenziali, come il \acr{pid}, i tempi di CPU usati
-dal processo (vedi \secref{sec:intro_unix_time}) e lo stato di terminazione
+dal processo (vedi \secref{sec:sys_unix_time}) e lo stato di terminazione
\footnote{NdA verificare esattamente cosa c'è!}, mentre la memoria in uso ed i
file aperti vengono rilasciati immediatamente. I processi che sono terminati,
ma il cui stato di terminazione non è stato ancora ricevuto dal padre sono
\textit{zombie} la tabella dei processi; le funzioni deputate a questo compito
sono sostanzialmente due, \func{wait} e \func{waitpid}. La prima, il cui
prototipo è:
-
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/wait.h}
\funcdecl{pid\_t wait(int * status)}
Sospende il processo corrente finché un figlio non è uscito, o finché un
-segnale termina il processo o chiama una funzione di gestione. Se un figlio è
-già uscito la funzione ritorna immediatamente. Al ritorno lo stato di
-termininazione del processo viene salvato nella variabile puntata da
-\var{status} e tutte le informazioni relative al processo (vedi
-\secref{sec:proc_termination}) vengono rilasciate.
+segnale termina il processo o chiama una funzione di gestione.
+
+\bodydesc{
La funzione restituisce il \acr{pid} del figlio in caso di successo e -1 in
caso di errore; \var{errno} può assumere i valori:
\begin{errlist}
- \item \macro{EINTR} la funzione è stata interrotta da un segnale.
+ \item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
\end{errlist}
+}
\end{functions}
-
+\noindent
è presente fin dalle prime versioni di unix; la funzione ritorna alla
-conclusione del primo figlio (o immediatamente se un figlio è già uscito). Nel
-caso un processo abbia più figli il valore di ritorno permette di identificare
-qual'è quello che è uscito.
-
-Questa funzione però ha il difetto di essere poco flessibile, in quanto
-ritorna all'uscita di un figlio qualunque. Nelle occasioni in cui è necessario
-attendere la conclusione di un processo specifico occorre predisporre un
-meccanismo che tenga conto dei processi già terminati, e ripeta la chiamata
-alla funzione nel caso il processo cercato sia ancora attivo.
+conclusione del primo figlio (o immediatamente se un figlio è già
+uscito). Se un figlio è già uscito la funzione ritorna immediatamente.
+
+Al ritorno lo stato di termininazione del processo viene salvato nella
+variabile puntata da \var{status} e tutte le informazioni relative al
+processo (vedi \secref{sec:proc_termination}) vengono rilasciate. Nel
+caso un processo abbia più figli il valore di ritorno permette di
+identificare qual'è quello che è uscito.
+
+Questa funzione ha il difetto di essere poco flessibile, in quanto
+ritorna all'uscita di un figlio qualunque. Nelle occasioni in cui è
+necessario attendere la conclusione di un processo specifico occorre
+predisporre un meccanismo che tenga conto dei processi già terminati, e
+provveda a ripetere la chiamata alla funzione nel caso il processo
+cercato sia ancora attivo.
Per questo motivo lo standard POSIX.1 ha introdotto la funzione \func{waitpid}
che effettua lo stesso servizio, ma dispone di una serie di funzionalità più
ampie, legate anche al controllo di sessione. Dato che è possibile ottenere
lo stesso comportamento di \func{wait} si consiglia di utilizzare sempre
questa funzione; il suo prototipo è:
-
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/wait.h}
specificata l'opzione \macro{WNOHANG} e il processo non è uscito e -1 per un
errore, nel qual caso \var{errno} assumerà i valori:
\begin{errlist}
- \item \macro{EINTR} se non è stata specificata l'opzione \macro{WNOHANG} e
+ \item[\macro{EINTR}] se non è stata specificata l'opzione \macro{WNOHANG} e
la funzione è stata interrotta da un segnale.
- \item \macro{ECHILD} il processo specificato da \var{pid} non esiste o non è
+ \item[\macro{ECHILD}] il processo specificato da \var{pid} non esiste o non è
figlio del processo chiamante.
\end{errlist}
\end{functions}
\label{tab:proc_status_macro}
\end{table}
-
Entrambe le funzioni restituiscono lo stato di terminazione del processo
tramite il puntatore \var{status} (se non interessa memorizzare lo stato si
può passare un puntatore nullo). Il valore restituito da entrambe le funzioni
kernel può restituire al processo padre ulteriori informazioni sulle risorse
usate dal processo terminato e dai vari figli. Queste funzioni, che diventano
accessibili definendo la costante \macro{\_USE\_BSD}, sono:
-
\begin{functions}
\headdecl{sys/times.h}
\headdecl{sys/types.h}
* rusage)}
La funzione è identica a \func{waitpid} sia per comportamento che per i
valori dei parametri, ma restituisce in \var{rusage} un sommario delle
- risorse usate dal processo (per i dettagli vedi \secref{sec:xxx_limit_res})
+ risorse usate dal processo (per i dettagli vedi \secref{sec:sys_xxx})
\funcdecl{pid\_t wait3(int *status, int options, struct rusage *rusage)}
Prima versione, equivalente a \func{wait4(-1, \&status, opt, rusage)} è
ormai deprecata in favore di \func{wait4}.
\noindent
la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene
utilizzata anche dalla funzione \func{getrusage} per ottenere le risorse di
-sistema usate dal processo; in Linux è definita come:
+sistema usate dal processo; la sua definizione è riportata in \nfig.
\begin{figure}[!htb]
\footnotesize
\centering
delle risorse usate da un processo.}
\label{fig:proc_rusage_struct}
\end{figure}
-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 dalla
-versione 4.3 Reno di BSD, 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}.
+
+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}.
\subsection{Le funzioni \func{exec}}
famiglia di funzioni) che possono essere usate per questo compito, che in
realtà (come mostrato in \figref{fig:proc_exec_relat}), costituiscono un
front-end a \func{execve}. Il prototipo di quest'ultima è:
-
\begin{prototype}{unistd.h}
{int execve(const char * filename, char * const argv [], char * const envp[])}
+ Esegue il programma contenuto nel file \param{filename}.
- La funzione esegue il file o lo script indicato da \var{filename},
- passandogli la lista di argomenti indicata da \var{argv} e come ambiente la
- lista di stringhe indicata da \var{envp}; entrambe le liste devono essere
- terminate da un puntatore nullo. I vettori degli argomenti e dell'ambiente
- possono essere acceduti dal nuovo programma quando la sua funzione
- \func{main} è dichiarata nella forma \func{main(int argc, char *argv[], char
- *envp[])}.
-
- La funzione ritorna -1 solo in caso di errore, nel qual caso caso la
- \var{errno} può assumere i valori:
+ \bodydesc{La funzione ritorna -1 solo in caso di errore, nel qual caso
+ caso la \var{errno} può assumere i valori:
\begin{errlist}
- \item \macro{EACCES} il file non è eseguibile, oppure il filesystem è
+ \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
+ \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{ENOEXEC} il file è in un formato non eseguibile o non
+ \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
+ \item[\macro{ENOENT}] il file o una delle librerie dinamiche o l'interprete
necessari per eseguirlo non esistono.
- \item \macro{ETXTBSY} L'eseguibile è aperto in scrittura da uno o più
+ \item[\macro{ETXTBSY}] L'eseguibile è aperto in scrittura da uno o più
processi.
- \item \macro{EINVAL} L'eseguibile ELF ha più di un segmento
- \macro{PF\_INTERP}, cioè chiede di essere eseguito da più di un interprete.
- \item \macro{ELIBBAD} Un interprete ELF non è in un formato riconoscibile.
+ \item[\macro{EINVAL}] L'eseguibile ELF ha più di un segmento
+ \macro{PF\_INTERP}, cioè chiede di essere eseguito da più di un
+ interprete.
+ \item[\macro{ELIBBAD}] Un interprete ELF non è in un formato
+ riconoscibile.
\end{errlist}
ed inoltre anche \macro{EFAULT}, \macro{ENOMEM}, \macro{EIO},
\macro{ENAMETOOLONG}, \macro{E2BIG}, \macro{ELOOP}, \macro{ENOTDIR},
- \macro{ENFILE}, \macro{EMFILE}.
+ \macro{ENFILE}, \macro{EMFILE}.}
\end{prototype}
+La funzione \func{exec} esegue il file o lo script indicato da
+\var{filename}, passandogli la lista di argomenti indicata da \var{argv}
+e come ambiente la lista di stringhe indicata da \var{envp}; entrambe le
+liste devono essere terminate da un puntatore nullo. I vettori degli
+argomenti e dell'ambiente possono essere acceduti dal nuovo programma
+quando la sua funzione \func{main} è dichiarata nella forma
+\func{main(int argc, char *argv[], char *envp[])}.
+
Le altre funzioni della famiglia servono per fornire all'utente una serie
possibile di diverse interfacce per la creazione di un nuovo processo. I loro
prototipi sono:
-
\begin{functions}
\headdecl{unistd.h}
\funcdecl{int execl(const char *path, const char *arg, ...)}
argomento. I parametri successivi consentono di specificare gli argomenti a
linea di comando e l'ambiente ricevuti dal nuovo processo.
-Queste funzioni ritornano solo in caso di errore, restituendo -1; nel qual
-caso \var{errno} andrà ad assumere i valori visti in precedenza per
-\func{execve}.
+\bodydesc{Queste funzioni ritornano solo in caso di errore, restituendo
+ -1; nel qual caso \var{errno} andrà ad assumere i valori visti in
+ precedenza per \func{execve}.}
\end{functions}
Per capire meglio le differenze fra le funzioni della famiglia si può fare
\begin{figure}[htb]
\centering
- \includegraphics[width=13cm]{img/exec_rel.eps}
+ \includegraphics[width=13cm]{img/exec_rel}
\caption{La interrelazione fra le sei funzioni della famiglia \func{exec}}
\label{fig:proc_exec_relat}
\end{figure}
\secref{sec:file_work_dir}).
\item la maschera di creazione dei file (\var{umask}, vedi
\secref{sec:file_umask}) ed i \textit{lock} sui file (vedi
- \secref{sec:file_xxx}).
+ \secref{sec:file_locking}).
\item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
\secref{sec:sig_xxx}).
-\item i limiti sulle risorse (vedi \secref{sec:limits_xxx})..
+\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})..
+ \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}).
\end{itemize*}
Oltre a questo i segnali che sono stati settati per essere ignorati nel
-processo chiamante mantengono lo stesso settaggio pure 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}
+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_xxx}).
La gestione dei file aperti dipende dal valore del flag di
\textit{close-on-exec} per ciascun file descriptor (si veda
-\secref{sec:file_xxx}); i file per cui è settato vengono chiusi, tutti gli
+\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.
tutti gli unix prevedono che i processi abbiano almeno due gruppi di
identificatori, chiamati rispettivamente \textit{real} ed \textit{effective}.
-
\begin{table}[htb]
\footnotesize
\centering
Come nel caso del \acr{pid} e del \acr{ppid} tutti questi identificatori
possono essere letti dal processo attraverso delle opportune funzioni, i cui
prototipi sono i seguenti:
-
\begin{functions}
-\headdecl{unistd.h}
-\headdecl{sys/types.h}
-\funcdecl{uid\_t getuid(void)} restituisce il \textit{real user ID} del
-processo corrente.
-\funcdecl{uid\_t geteuid(void)} restituisce l'\textit{effective user ID} del
-processo corrente.
-\funcdecl{gid\_t getgid(void)} restituisce il \textit{real group ID} del
-processo corrente.
-\funcdecl{gid\_t getegid(void)} restituisce l'\textit{effective group ID} del
-processo corrente.
-
-Queste funzioni non riportano condizioni di errore.
+ \headdecl{unistd.h}
+ \headdecl{sys/types.h}
+ \funcdecl{uid\_t getuid(void)} restituisce il \textit{real user ID} del
+ processo corrente.
+
+ \funcdecl{uid\_t geteuid(void)} restituisce l'\textit{effective user ID} del
+ processo corrente.
+
+ \funcdecl{gid\_t getgid(void)} restituisce il \textit{real group ID} del
+ processo corrente.
+
+ \funcdecl{gid\_t getegid(void)} restituisce l'\textit{effective group ID} 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ù
\func{setgid}; come accennato in \secref{sec:proc_user_group} in Linux esse
seguono la semantica POSIX che prevede l'esistenza di \textit{saved user id} e
\textit{saved group id}; i loro prototipi sono:
-
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
\funcdecl{int setgid(gid\_t gid)} setta il \textit{group ID} del processo
corrente.
-Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento:
-l'unico errore possibile è \macro{EPERM}.
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \macro{EPERM}.}
\end{functions}
Il funzionamento di queste due funzioni è analogo, per cui considereremo solo
alla versione 4.3+BSD TODO, verificare e aggiornare la nota} i \textit{saved
id} le usava per poter scambiare fra di loro effective e real id. I
prototipi sono:
-
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
ID} e l'\textit{effective group ID} del processo corrente ai valori
specificati da \var{rgid} e \var{egid}.
-Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento:
-l'unico errore possibile è \macro{EPERM}.
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \macro{EPERM}.}
\end{functions}
I processi non privilegiati possono settare i \textit{real id} soltanto ai
Queste due funzioni sono una 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}
ID} del processo corrente ai valori specificati rispettivamente da
\var{rgid}, \var{egid} e \var{sgid}.
-Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento:
-l'unico errore possibile è \macro{EPERM}.
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \macro{EPERM}.}
\end{functions}
I processi non privilegiati possono cambiare uno qualunque degli
Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
supportate dalla maggior parte degli unix) e usate per cambiare gli
\textit{effective id}; i loro prototipi sono:
-
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
\funcdecl{int setegid(gid\_t gid)} setta l'\textit{effective group ID} del
processo corrente a \var{gid}.
-Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento:
-l'unico errore possibile è \macro{EPERM}.
+\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
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 setfsgid(gid\_t fsgid)} setta l'\textit{filesystem group ID} del
processo corrente a \var{fsgid}.
-Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento:
-l'unico errore possibile è \macro{EPERM}.
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \macro{EPERM}.}
\end{functions}
Queste funzioni hanno successo solo se il processo chiamante ha i privilegi di
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 nella 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
processi.
Nel caso dei segnali invece la situazione è molto più delicata, in quanto lo
-stesso processo può essere interrotto in qualunque momento, e le operazioni di
-un eventuale \textit{signal handler} saranno compiute nello stesso spazio di
-indirizzi. Per questo anche solo il solo accesso o l'assegnazione di una
-variabile possono non essere più operazioni atomiche (torneremo su questi
-aspetti in \secref{sec:sign_xxx}).
+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
+solo il solo accesso o l'assegnazione di una variabile possono non essere più
+operazioni atomiche (torneremo su questi aspetti in \secref{sec:sign_xxx}).
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ò
Un caso particolare di \textit{race condition} sono poi i cosiddetti
\textit{deadlock}; l'esempio tipico è quello di un flag di ``occupazione'' che
viene rilasciato da un evento asincrono fra il controllo (in cui viene trovato
-occupato) e la successiva messa in attesa, attesa che a questo punto diventerà
+occupato) e la successiva messa in attesa, che a questo punto diventerà
perpetua (da cui il nome di \textit{deadlock}) in quanto l'evento di sblocco
-di questa è stato perso.
+del flag è stato perso fra il controllo e la messa in attesa.
\subsection{Le funzioni rientranti}