%% prochand.tex
%%
-%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
%% license is included in the section entitled "GNU Free Documentation
%% License".
%%
+
\chapter{La gestione dei processi}
\label{cha:process_handling}
\label{fig:proc_task_struct}
\end{figure}
-Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \textit{scheduler}
-\itindex{scheduler} che decide quale processo mettere in esecuzione; esso
-viene eseguito ad ogni system call ed ad ogni interrupt,\footnote{più in una
- serie di altre occasioni.}
-% TODO completare questa parte.
+Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \itindex{scheduler}
+\textit{scheduler} che decide quale processo mettere in esecuzione; esso viene
+eseguito ad ogni system call ed ad ogni interrupt,\footnote{più in una serie
+ di altre occasioni.}
+% TODO completare questa parte su quando viene chiamato lo scheduler.
(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 \const{HZ}, definita
% TODO verificare gli ultimi cambiamenti del 2.6
% Si ha cioè un interrupt dal timer ogni centesimo di secondo.
-Ogni volta che viene eseguito, lo \textit{scheduler} \itindex{scheduler}
+Ogni volta che viene eseguito, lo \itindex{scheduler} \textit{scheduler}
effettua il calcolo delle priorità dei vari processi attivi (torneremo su
questo in sez.~\ref{sec:proc_priority}) e stabilisce quale di essi debba
essere posto in esecuzione fino alla successiva invocazione.
candidato per generare ulteriori indicatori associati al processo di cui
diventa possibile garantire l'unicità: ad esempio in alcune implementazioni la
funzione \func{tempnam} (si veda sez.~\ref{sec:file_temp_file}) usa il
-\acr{pid} per generare un \itindex{pathname}\textit{pathname} univoco, che non
-potrà essere replicato da un altro processo che usi la stessa funzione.
+\acr{pid} per generare un \itindex{pathname} \textit{pathname} univoco, che
+non potrà essere replicato da un altro processo che usi la stessa funzione.
Tutti i processi figli dello stesso processo padre sono detti
\textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di
Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che
il processo figlio continuano ad essere eseguiti normalmente a partire
dall'istruzione successiva alla \func{fork}; il processo figlio è però una
-copia del padre, e riceve una copia dei segmenti di testo, \itindex{stack}
-stack e dati (vedi sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo
-stesso codice del padre. Si tenga presente però che la memoria è copiata, non
-condivisa, pertanto padre e figlio vedono variabili diverse.
-
-Per quanto riguarda la gestione della memoria, in generale
-il\index{segmento!testo} segmento di testo, che è identico per i due processi,
-è condiviso e tenuto in read-only per il padre e per i figli. Per gli altri
-segmenti Linux utilizza la tecnica del \textit{copy on write}
-\itindex{copy~on~write}; questa tecnica comporta che una pagina di memoria
-viene effettivamente copiata per il nuovo processo solo quando ci viene
-effettuata sopra una scrittura (e si ha quindi una reale differenza fra padre
-e figlio). In questo modo si rende molto più efficiente il meccanismo della
-creazione di un nuovo processo, non essendo più necessaria la copia di tutto
-lo spazio degli indirizzi virtuali del padre, ma solo delle pagine di memoria
-che sono state modificate, e solo al momento della modifica stessa.
+copia del padre, e riceve una copia dei \index{segmento!testo} segmenti di
+testo, \itindex{stack} stack e \index{segmento!dati} dati (vedi
+sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del
+padre. Si tenga presente però che la memoria è copiata, non condivisa,
+pertanto padre e figlio vedono variabili diverse.
+
+Per quanto riguarda la gestione della memoria, in generale il
+\index{segmento!testo} segmento di testo, che è identico per i due processi, è
+condiviso e tenuto in read-only per il padre e per i figli. Per gli altri
+segmenti Linux utilizza la tecnica del \itindex{copy~on~write} \textit{copy on
+ write}; questa tecnica comporta che una pagina di memoria viene
+effettivamente copiata per il nuovo processo solo quando ci viene effettuata
+sopra una scrittura (e si ha quindi una reale differenza fra padre e figlio).
+In questo modo si rende molto più efficiente il meccanismo della creazione di
+un nuovo processo, non essendo più necessaria la copia di tutto lo spazio
+degli indirizzi virtuali del padre, ma solo delle pagine di memoria che sono
+state modificate, e solo al momento della modifica stessa.
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
Esaminiamo questo risultato: una prima conclusione che si può trarre è che non
si può dire quale processo fra il padre ed il figlio venga eseguito per
primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
- scheduler\itindex{scheduler} di Ingo Molnar che esegue sempre per primo il
- figlio; per mantenere la portabilità è opportuno non fare comunque
+ \itindex{scheduler} \textit{scheduler} di Ingo Molnar che esegue sempre per
+ primo il figlio; per mantenere la portabilità è opportuno non fare comunque
affidamento su questo comportamento.} dopo la chiamata a \func{fork};
dall'esempio si può notare infatti come nei primi due cicli sia stato eseguito
per primo il padre (con la stampa del \acr{pid} del nuovo processo) per poi
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}
-\itindex{race~condition} (vedi sez.~\ref{sec:proc_race_cond}).
+rischio di incorrere nelle cosiddette \itindex{race~condition} \textit{race
+ condition} (vedi sez.~\ref{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
la caratteristica di duplicare nei figli tutti i file descriptor aperti nel
padre (allo stesso modo in cui lo fa la funzione \func{dup}, trattata in
sez.~\ref{sec:file_dup}), il che comporta che padre e figli condividono le
-stesse voci della \textit{file table} (per la spiegazione di questi termini si
-veda sez.~\ref{sec:file_sharing}) fra cui c'è anche la posizione corrente nel
-file.
+stesse voci della \itindex{file~table} \textit{file table} (per la spiegazione
+di questi termini si veda sez.~\ref{sec:file_sharing}) fra cui c'è anche la
+posizione corrente nel file.
In questo modo se un processo scrive sul file aggiornerà la posizione corrente
-sulla \textit{file table}, e tutti gli altri processi, che vedono la stessa
-\textit{file table}, vedranno il nuovo valore. In questo modo si evita, in
-casi come quello appena mostrato in cui diversi processi scrivono sullo stesso
-file, che l'output successivo di un processo vada a sovrapporsi a quello dei
-precedenti: l'output potrà risultare mescolato, ma non ci saranno parti
-perdute per via di una sovrascrittura.
+sulla \itindex{file~table} \textit{file table}, e tutti gli altri processi,
+che vedono la stessa \itindex{file~table} \textit{file table}, vedranno il
+nuovo valore. In questo modo si evita, in casi come quello appena mostrato in
+cui diversi processi scrivono sullo stesso file, che l'output successivo di un
+processo vada a sovrapporsi a quello dei precedenti: l'output potrà risultare
+mescolato, ma non ci saranno parti perdute per via di una sovrascrittura.
Questo tipo di comportamento è essenziale in tutti quei casi in cui il padre
crea un figlio e attende la sua conclusione per proseguire, ed entrambi
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}\itindex{close-on-exec} impostati (vedi
- sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl});
+\item i file aperti e gli eventuali flag di \itindex{close-on-exec}
+ \textit{close-on-exec} impostati (vedi sez.~\ref{sec:proc_exec} e
+ sez.~\ref{sec:file_fcntl});
\item gli identificatori per il controllo di accesso: l'\textsl{user-ID
reale}, il \textsl{group-ID reale}, l'\textsl{user-ID effettivo}, il
\textsl{group-ID effettivo} ed i \textit{group-ID supplementari} (vedi
sez.~\ref{sec:proc_access_id});
-\item gli identificatori per il controllo di sessione: il \textit{process
- group-ID} e il \textit{session id} ed il terminale di controllo (vedi
- sez.~\ref{sec:sess_proc_group});
+\item gli identificatori per il controllo di sessione: il
+ \itindex{process~group} \textit{process group-ID} e il \textit{session id}
+ ed il terminale di controllo (vedi sez.~\ref{sec:sess_proc_group});
\item la directory di lavoro e la directory radice (vedi
sez.~\ref{sec:file_work_dir} e sez.~\ref{sec:file_chroot});
-\item la maschera dei permessi di creazione (vedi sez.~\ref{sec:file_umask});
+\item la maschera dei permessi di creazione (vedi
+ sez.~\ref{sec:file_perm_management});
\item la maschera dei segnali bloccati (vedi sez.~\ref{sec:sig_sigmask}) e le
azioni installate (vedi sez.~\ref{sec:sig_gen_beha});
\item i segmenti di memoria condivisa agganciati al processo (vedi
\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} \itindex{copy~on~write} la
+Dato che Linux supporta il \itindex{copy~on~write} \textit{copy on write} la
perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
funzione (che resta un caso speciale della system call \func{\_\_clone}) è
deprecato; per questo eviteremo di trattarla ulteriormente.
dal processo (vedi sez.~\ref{sec:sys_unix_time}) e lo stato di terminazione,
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 chiamati \textit{zombie}\index{zombie}, essi
+ancora ricevuto dal padre sono chiamati \index{zombie} \textit{zombie}, essi
restano presenti nella tabella dei processi ed in genere possono essere
identificati dall'output di \cmd{ps} per la presenza di una \texttt{Z} nella
colonna che ne indica lo stato (vedi tab.~\ref{tab:proc_proc_states}). Quando
\end{verbatim} %$
\normalsize e come si vede, dato che non si è fatto nulla per riceverne lo
stato di terminazione, i tre processi figli sono ancora presenti pur essendosi
-conclusi, con lo stato di zombie \index{zombie} e l'indicazione che sono stati
-terminati.
-
-La possibilità di avere degli zombie \index{zombie} deve essere tenuta sempre
-presente quando si scrive un programma che deve essere mantenuto in esecuzione
-a lungo e creare molti figli. In questo caso si deve sempre avere cura di far
-leggere l'eventuale stato di uscita di tutti i figli (in genere questo si fa
-attraverso un apposito \textit{signal handler}, che chiama la funzione
-\func{wait}, vedi sez.~\ref{sec:sig_sigchld} e sez.~\ref{sec:proc_wait}).
-Questa operazione è necessaria perché anche se gli \textit{zombie}
-\index{zombie} non consumano risorse di memoria o processore, occupano
-comunque una voce nella tabella dei processi, che a lungo andare potrebbe
-esaurirsi.
+conclusi, con lo stato di \index{zombie} \textit{zombie} e l'indicazione che
+sono stati terminati.
+
+La possibilità di avere degli \index{zombie} \textit{zombie} deve essere
+tenuta sempre presente quando si scrive un programma che deve essere mantenuto
+in esecuzione a lungo e creare molti figli. In questo caso si deve sempre
+avere cura di far leggere l'eventuale stato di uscita di tutti i figli (in
+genere questo si fa attraverso un apposito \textit{signal handler}, che chiama
+la funzione \func{wait}, vedi sez.~\ref{sec:sig_sigchld} e
+sez.~\ref{sec:proc_wait}). Questa operazione è necessaria perché anche se gli
+\index{zombie} \textit{zombie} non consumano risorse di memoria o processore,
+occupano comunque una voce nella tabella dei processi, che a lungo andare
+potrebbe esaurirsi.
Si noti che quando un processo adottato da \cmd{init} termina, esso non
-diviene uno \textit{zombie}\index{zombie}; questo perché una delle funzioni di
-\cmd{init} è appunto quella di chiamare la funzione \func{wait} per i processi
-cui fa da padre, completandone la terminazione. Questo è quanto avviene anche
-quando, come nel caso del precedente esempio con \cmd{forktest}, il padre
-termina con dei figli in stato di zombie\index{zombie}: alla sua terminazione
-infatti tutti i suoi figli (compresi gli zombie\index{zombie}) verranno
-adottati da \cmd{init}, il quale provvederà a completarne la terminazione.
-
-Si tenga presente infine che siccome gli zombie\index{zombie} sono processi
-già usciti, non c'è modo di eliminarli con il comando \cmd{kill}; l'unica
-possibilità di cancellarli dalla tabella dei processi è quella di terminare il
-processo che li ha generati, in modo che \cmd{init} possa adottarli e
-provvedere a concluderne la terminazione.
+diviene uno \index{zombie} \textit{zombie}; questo perché una delle funzioni
+di \cmd{init} è appunto quella di chiamare la funzione \func{wait} per i
+processi cui fa da padre, completandone la terminazione. Questo è quanto
+avviene anche quando, come nel caso del precedente esempio con \cmd{forktest},
+il padre termina con dei figli in stato di \index{zombie} \textit{zombie}:
+alla sua terminazione infatti tutti i suoi figli (compresi gli \index{zombie}
+\textit{zombie}) verranno adottati da \cmd{init}, il quale provvederà a
+completarne la terminazione.
+
+Si tenga presente infine che siccome gli \index{zombie} \textit{zombie} sono
+processi già usciti, non c'è modo di eliminarli con il comando \cmd{kill};
+l'unica possibilità di cancellarli dalla tabella dei processi è quella di
+terminare il processo che li ha generati, in modo che \cmd{init} possa
+adottarli e provvedere a concluderne la terminazione.
\subsection{Le funzioni \func{wait} e \func{waitpid}}
principale attende le richieste che vengono poi soddisfatte da una serie di
processi figli. Si è già sottolineato al paragrafo precedente come in questo
caso diventi necessario gestire esplicitamente la conclusione dei figli onde
-evitare di riempire di \textit{zombie}\index{zombie} la tabella dei processi;
+evitare di riempire di \index{zombie} \textit{zombie} la tabella dei processi;
le funzioni deputate a questo compito sono sostanzialmente due, \funcd{wait} e
\func{waitpid}. La prima, il cui prototipo è:
\begin{functions}
In genere in un programma non si vuole essere forzati ad attendere la
conclusione di un processo per proseguire, specie se tutto questo serve solo
-per leggerne lo stato di chiusura (ed evitare la presenza di
-\textit{zombie}\index{zombie}), per questo la modalità più usata per chiamare
-queste funzioni è quella di utilizzarle all'interno di un \textit{signal
- handler} (vedremo un esempio di come gestire \const{SIGCHLD} con i segnali
-in sez.~\ref{sec:sig_example}). In questo caso infatti, dato che il segnale è
+per leggerne lo stato di chiusura (ed evitare la presenza di \index{zombie}
+\textit{zombie}), per questo la modalità più usata per chiamare queste
+funzioni è quella di utilizzarle all'interno di un \textit{signal handler}
+(vedremo un esempio di come gestire \const{SIGCHLD} con i segnali in
+sez.~\ref{sec:sig_example}). In questo caso infatti, dato che il segnale è
generato dalla terminazione di un figlio, avremo la certezza che la chiamata a
\func{wait} non si bloccherà.
valutata solo se \val{WIFSIGNALED} ha restituito
un valore non nullo.\\
\macro{WCOREDUMP(s)} & Vera se il processo terminato ha generato un
- file di \itindex{core~dump}\textit{core
+ file di \itindex{core~dump} \textit{core
dump}. Può essere valutata solo se
\val{WIFSIGNALED} ha restituito un valore non
nullo.\footnotemark \\
bit (in genere 8) sono riservati per memorizzare lo stato di uscita, e altri
per indicare il segnale che ha causato la terminazione (in caso di
conclusione anomala), uno per indicare se è stato generato un
-\itindex{core~dump}\textit{core dump}, ecc.\footnote{le definizioni esatte
+\itindex{core~dump} \textit{core dump}, ecc.\footnote{le definizioni esatte
si possono trovare in \file{<bits/waitstatus.h>} ma questo file non deve
mai essere usato direttamente, esso viene incluso attraverso
\file{<sys/wait.h>}.}
processo chiama una di queste funzioni esso viene completamente sostituito dal
nuovo programma; il \acr{pid} del processo non cambia, dato che non viene
creato un nuovo processo, la funzione semplicemente rimpiazza lo
-\itindex{stack} stack, lo \itindex{heap} heap, i dati ed il testo del processo
+\itindex{stack} \textit{stack}, lo \itindex{heap} \textit{heap}, i
+\index{segmento!dati} dati ed il \index{segmento!testo} testo del processo
corrente con un nuovo programma letto da disco.
Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata
Le altre quattro funzioni si limitano invece a cercare di eseguire il file
indicato dall'argomento \param{path}, che viene interpretato come il
-\itindex{pathname}\textit{pathname} del programma.
+\itindex{pathname} \textit{pathname} del programma.
\begin{figure}[htb]
\centering
\item la directory radice e la directory di lavoro corrente (vedi
sez.~\ref{sec:file_work_dir});
\item la maschera di creazione dei file (\var{umask}, vedi
- sez.~\ref{sec:file_umask}) ed i \textit{lock} sui file (vedi
+ sez.~\ref{sec:file_perm_management}) ed i \textit{lock} sui file (vedi
sez.~\ref{sec:file_locking});
\item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
sez.~\ref{sec:sig_sigmask});
sez.~\ref{sec:sig_gen_beha}).
La gestione dei file aperti dipende dal valore che ha il flag di
-\textit{close-on-exec}\itindex{close-on-exec} (vedi anche
+\itindex{close-on-exec} \textit{close-on-exec} (vedi anche
sez.~\ref{sec:file_fcntl}) per ciascun 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
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 sez.~\ref{sec:file_dir_read}) che effettua da sola
-l'impostazione del flag di \textit{close-on-exec}\itindex{close-on-exec} sulle
-directory che apre, in maniera trasparente all'utente.
+l'impostazione del flag di \itindex{close-on-exec} \textit{close-on-exec}
+sulle directory che apre, in maniera trasparente all'utente.
Abbiamo detto che l'\textsl{user-ID reale} ed il \textsl{group-ID reale}
restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per
l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} (il significato
di questi identificatori è trattato in sez.~\ref{sec:proc_access_id}), tranne
-quando il file che si va ad eseguire abbia o il \itindex{suid~bit}\acr{suid}
+quando il file che si va ad eseguire abbia o il \itindex{suid~bit} \acr{suid}
bit o lo \itindex{sgid~bit} \acr{sgid} bit impostato, in questo caso
l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} vengono
impostati rispettivamente all'utente o al gruppo cui il file appartiene (per i
realtà già esistono estensioni di questo modello base, che lo rendono più
flessibile e controllabile, come le \itindex{capabilities}
\textit{capabilities} illustrate in sez.~\ref{sec:proc_capabilities}, le ACL
- per i file o il \textit{Mandatory Access Control}
- \itindex{Mandatory~Access~Control~(MAC)} di SELinux; inoltre basandosi sul
- lavoro effettuato con SELinux, a partire dal kernel 2.5.x, è iniziato lo
- sviluppo di una infrastruttura di sicurezza, il \textit{Linux Security
- Modules}, o LSM, in grado di fornire diversi agganci a livello del kernel
- per modularizzare tutti i possibili controlli di accesso.} di sicurezza di
-un sistema unix-like è fondato sui concetti di utente e gruppo, e sulla
-separazione fra l'amministratore (\textsl{root}, detto spesso anche
-\textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli
-utenti, per i quali invece vengono effettuati i vari controlli di accesso.
+ per i file o il \itindex{Mandatory~Access~Control~(MAC)} \textit{Mandatory
+ Access Control} di SELinux; inoltre basandosi sul lavoro effettuato con
+ SELinux, a partire dal kernel 2.5.x, è iniziato lo sviluppo di una
+ infrastruttura di sicurezza, il \textit{Linux Security Modules}, o LSM, in
+ grado di fornire diversi agganci a livello del kernel per modularizzare
+ tutti i possibili controlli di accesso.} di sicurezza di un sistema
+unix-like è fondato sui concetti di utente e gruppo, e sulla separazione fra
+l'amministratore (\textsl{root}, detto spesso anche \textit{superuser}) che
+non è sottoposto a restrizioni, ed il resto degli utenti, per i quali invece
+vengono effettuati i vari controlli di accesso.
Abbiamo già accennato come il sistema associ ad ogni utente e gruppo due
identificatori univoci, lo user-ID ed il group-ID; questi servono al kernel per
sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i
bit \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid} impostati
(il significato di questi bit è affrontato in dettaglio in
-sez.~\ref{sec:file_suid_sgid}). In questo caso essi saranno impostati
+sez.~\ref{sec:file_special_perm}). 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).
padre, e vengono impostati dalla funzione \func{exec} all'avvio del processo,
come copie dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo}
dopo che questi sono stati impostati tenendo conto di eventuali
-\itindex{suid~bit}\acr{suid} o \itindex{sgid~bit} \acr{sgid}. Essi quindi
+\itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid}. Essi quindi
consentono di tenere traccia di quale fossero utente e gruppo effettivi
all'inizio dell'esecuzione di un nuovo programma.
Come accennato l'uso principale di queste funzioni è quello di poter
consentire ad un programma con i bit \itindex{suid~bit} \acr{suid} o
-\itindex{sgid~bit} \acr{sgid} impostati (vedi sez.~\ref{sec:file_suid_sgid})
+\itindex{sgid~bit} \acr{sgid} impostati (vedi sez.~\ref{sec:file_special_perm})
di riportare l'\textsl{user-ID effettivo} a quello dell'utente che ha lanciato
il programma, effettuare il lavoro che non necessita di privilegi aggiuntivi,
ed eventualmente tornare indietro.
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
-\itindex{value~result~argument}\textit{value result argument}). Si noti che
+\itindex{value~result~argument} \textit{value result argument}). Si noti che
queste funzioni sono le uniche in grado di leggere gli identificatori del
gruppo \textit{saved}.
%
\const{CAP\_CHOWN} & la capacità di cambiare proprietario e gruppo
proprietario di un file (vedi
- sez.~\ref{sec:file_chown}).\\
+ sez.~\ref{sec:file_ownership_management}).\\
\const{CAP\_DAC\_OVERRIDE}& la capacità di evitare il controllo dei
permessi di lettura, scrittura ed esecuzione dei
file, (vedi sez.~\ref{sec:file_access_control})
precedenti \const{CAP\_DAC\_OVERRIDE} e
\const{CAP\_DAC\_READ\_SEARCH}. Queste
comprendono i cambiamenti dei permessi e dei
- tempi del file (vedi sez.~\ref{sec:file_chmod} e
- sez.~\ref{sec:file_utime}), le impostazioni degli
- attributi estesi (con il comando \cmd{chattr}) e
- delle ACL, poter ignorare lo
+ tempi del file (vedi
+ sez.~\ref{sec:file_perm_management} e
+ sez.~\ref{sec:file_file_times}), le impostazioni
+ degli attributi estesi (con il comando
+ \cmd{chattr}) e delle ACL, poter ignorare lo
\itindex{sticky~bit} \textit{sticky bit} nella
cancellazione dei file (vedi
- sez.~\ref{sec:file_sticky}), la possibilità di
- impostare il flag di \const{O\_NOATIME} con
+ sez.~\ref{sec:file_special_perm}), la possibilità
+ di impostare il flag di \const{O\_NOATIME} con
\func{open} e \func{fcntl} (vedi
sez.~\ref{sec:file_open} e
sez.~\ref{sec:file_fcntl}).\\
un processo senza questa capacità e la capacità
di impostare il bit \acr{sgid} su un file anche
quando questo è relativo ad un gruppo cui non si
- appartiene (vedi sez.~\ref{sec:file_chmod}).\\
+ appartiene (vedi
+ sez.~\ref{sec:file_perm_management}).\\
\const{CAP\_KILL} & la capacità di mandare segnali a qualunque
processo (vedi sez.~\ref{sec:sig_kill_raise}).\\
\const{CAP\_SETGID} & la capacità di manipolare i group ID dei
processi, sia il principale che i supplementari,
(vedi sez.~\ref{sec:proc_setgroups} che quelli
- trasmessi tramite i \index{socket} socket
- \textit{unix domain} (vedi
- sez.~\ref{sec:unix_socket}).\\
+ trasmessi tramite i socket \textit{unix domain}
+ (vedi sez.~\ref{sec:unix_socket}).\\
\const{CAP\_SETUID} & la capacità di manipolare gli user ID del
processo (con \func{setuid}, \func{setreuid},
\func{setresuid}, \func{setfsuid}) e di
trasmettere un valore arbitrario
dell'\textsl{uid} nel passaggio delle
- credenziali coi socket unix domain (vedi
+ credenziali coi socket \textit{unix domain} (vedi
sez.~\ref{sec:unix_socket}).\\
%
% Linux specific capabilities
\itindend{capabilities}
-
-
+% TODO vedi http://lwn.net/Articles/198557/ e
+% http://www.madore.org/~david/linux/newcaps/
+% TODO documentare prctl ...
+
\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}\itindex{scheduler} assegna la CPU ai vari processi
+lo \itindex{scheduler} \textit{scheduler} assegna la CPU ai vari processi
attivi. In particolare prenderemo in esame i vari meccanismi con cui viene
gestita l'assegnazione del tempo di CPU, ed illustreremo le varie funzioni di
gestione.
\label{sec:proc_sched}
\itindbeg{scheduler}
+
La scelta di un meccanismo che sia in grado di distribuire in maniera efficace
il tempo di CPU per l'esecuzione dei processi è sempre una questione delicata,
ed oggetto di numerose ricerche; in generale essa dipende in maniera
cui non esiste un meccanismo che sia valido per tutti gli usi.
La caratteristica specifica di un sistema multitasking come Linux è quella del
-cosiddetto \itindex{prehemptive~multitasking}\textit{prehemptive
+cosiddetto \itindex{prehemptive~multitasking} \textit{prehemptive
multitasking}: questo significa che al contrario di altri sistemi (che usano
-invece il cosiddetto \itindex{cooperative~multitasking}\textit{cooperative
+invece il cosiddetto \itindex{cooperative~multitasking} \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
sez.~\ref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione
Adeos gestiti dalle code del nano-kernel), in modo da poterli controllare
direttamente qualora ci sia la necessità di avere un processo con priorità
più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un
-\textit{page fault}\itindex{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 sez.~\ref{sec:proc_mem_lock}), il primo
-non è superabile e può comportare ritardi non prevedibili riguardo ai tempi di
-esecuzione di qualunque processo.
+\itindex{page~fault} \textit{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
+sez.~\ref{sec:proc_mem_lock}), il primo non è superabile e può comportare
+ritardi non prevedibili riguardo ai tempi di esecuzione di qualunque processo.
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
funzioni che permettono di controllare in maniera più dettagliata la scelta di
quale processore utilizzare per eseguire un certo programma. Uno dei problemi
che si pongono nei sistemi multiprocessore è infatti quello
-dell'\textsl{effetto ping-pong}.\index{effetto~ping-pong} Può accadere cioè
+\index{effetto~ping-pong} dell'\textsl{effetto ping-pong}. Può accadere cioè
che lo scheduler, quando riavvia un processo precedentemente interrotto,
scegliendo il primo processore disponibile lo faccia eseguire da un processore
diverso rispetto a quello su cui era stato eseguito in precedenza. Se il
disponibile.
\itindbeg{CPU~affinity}
+
Per ovviare a questo tipo di problemi è nato il concetto di \textsl{affinità
di processore} (o \textit{CPU affinity}); la
possibilità cioè di far sì che un processo possa essere assegnato per
soltanto su un sistema multiprocessore, esse possono comunque essere
utilizzate anche in un sistema con un processore singolo, nel qual caso però
non avranno alcun risultato effettivo.
+
\itindend{scheduler}
\itindend{CPU~affinity}
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}\itindex{race~condition} (vedi sez.~\ref{sec:proc_race_cond})
-derivanti da operazioni interrotte in una fase in cui non erano ancora state
-completate.
+accorti nei confronti delle possibili \itindex{race~condition} \textit{race
+ condition} (vedi sez.~\ref{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
\label{sec:proc_race_cond}
\itindbeg{race~condition}
+
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
condivisa. In questi casi, se non si dispone della possibilità di eseguire
atomicamente le operazioni necessarie, occorre che quelle parti di codice in
cui si compiono le operazioni sulle risorse condivise (le cosiddette
-\textsl{sezioni critiche}\index{sezione~critica}) del programma, siano
+\index{sezione~critica} \textsl{sezioni critiche}) del programma, siano
opportunamente protette da meccanismi di sincronizzazione (torneremo su queste
problematiche di questo tipo in cap.~\ref{cha:IPC}).
varie funzioni di libreria, che sono identificate aggiungendo il suffisso
\code{\_r} al nome della versione normale.
-
-%%% Local Variables:
-%%% mode: latex
-%%% TeX-master: "gapil"
-%%% End:
-
% LocalWords: multitasking like VMS child process identifier pid sez shell fig
% LocalWords: parent kernel init pstree keventd kswapd table struct linux call
% LocalWords: nell'header scheduler system interrupt timer HZ asm Hertz clock
% LocalWords: get ncap caps CapInh CapPrm fffffeff CapEff getcap STAT dall'I
% LocalWords: inc PRIO SUSv PRGR prio SysV SunOS Ultrix sched timespec len sig
% LocalWords: cpusetsize cpuset atomic
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: