\begin{figure}[htb]
\centering
- \includegraphics[width=11cm]{img/task_struct}
+ \includegraphics[width=12cm]{img/task_struct}
\caption{Schema semplificato dell'architettura delle strutture usate dal
kernel nella gestione dei processi.}
\label{fig:proc_task_struct}
senza specificare attese (come si può notare in (\texttt{\small 17--19}) i
valori predefiniti specificano di non attendere), otterremo come output sul
terminale:
-\footnotesize
-\begin{verbatim}
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
[piccardi@selidor sources]$ export LD_LIBRARY_PATH=./; ./forktest 3
Process 1963: forking 3 child
Spawned 1 child, pid 1964
Child 3, parent 1963, exiting
Spawned 3 child, pid 1966
Go to next child
-\end{verbatim} %$
-\normalsize
+\end{Verbatim}
+%$
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
quello dell'interazione dei vari processi con i file; per illustrarlo meglio
proviamo a redirigere su un file l'output del nostro programma di test, quello
che otterremo è:
-\footnotesize
-\begin{verbatim}
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
[piccardi@selidor sources]$ ./forktest 3 > output
[piccardi@selidor sources]$ cat output
Process 1967: forking 3 child
Go to next child
Spawned 3 child, pid 1970
Go to next child
-\end{verbatim}
-\normalsize
+\end{Verbatim}
che come si vede è completamente diverso da quanto ottenevamo sul terminale.
Il comportamento delle varie funzioni di interfaccia con i file è analizzato
le variabili, la posizione corrente sul file è condivisa fra il padre e tutti
i processi figli.
-Quello che succede è che quando lo standard output del padre viene rediretto,
-lo stesso avviene anche per tutti i figli; la funzione \func{fork} infatti ha
-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 \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.
+Quello che succede è che quando lo standard output del padre viene rediretto
+come si è fatto nell'esempio, lo stesso avviene anche per tutti i figli; la
+funzione \func{fork} infatti ha la caratteristica di duplicare nei processi
+figli tutti i file descriptor aperti nel processo 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
+\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 \itindex{file~table} \textit{file table}, e tutti gli altri processi,
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
-scrivono sullo stesso file (un caso tipico è la shell quando lancia un
-programma, il cui output va sullo standard output).
-
-In questo modo, anche se l'output viene rediretto, il padre potrà sempre
-continuare a scrivere in coda a quanto scritto dal figlio in maniera
-automatica; se così non fosse ottenere questo comportamento sarebbe
-estremamente complesso necessitando di una qualche forma di comunicazione fra
-i due processi per far riprendere al padre la scrittura al punto giusto.
+scrivono sullo stesso file; un caso tipico è la shell quando lancia un
+programma, il cui output va sullo standard output. In questo modo, anche se
+l'output viene rediretto, il padre potrà sempre continuare a scrivere in coda
+a quanto scritto dal figlio in maniera automatica; se così non fosse ottenere
+questo comportamento sarebbe estremamente complesso necessitando di una
+qualche forma di comunicazione fra i due processi per far riprendere al padre
+la scrittura al punto giusto.
In generale comunque non è buona norma far scrivere più processi sullo stesso
file senza una qualche forma di sincronizzazione in quanto, come visto anche
con il nostro esempio, le varie scritture risulteranno mescolate fra loro in
una sequenza impredicibile. Per questo le modalità con cui in genere si usano
i file dopo una \func{fork} sono sostanzialmente due:
-\begin{enumerate*}
+\begin{enumerate}
\item Il processo padre aspetta la conclusione del figlio. In questo caso non
è necessaria nessuna azione riguardo ai file, in quanto la sincronizzazione
della posizione corrente dopo eventuali operazioni di lettura e scrittura
\item L'esecuzione di padre e figlio procede indipendentemente. In questo caso
ciascuno dei due processi deve chiudere i file che non gli servono una volta
che la \func{fork} è stata eseguita, per evitare ogni forma di interferenza.
-\end{enumerate*}
+\end{enumerate}
Oltre ai file aperti i processi figli ereditano dal padre una serie di altre
proprietà; la lista dettagliata delle proprietà che padre e figlio hanno in
comunque una serie di operazioni: chiude tutti i file aperti, rilascia la
memoria che stava usando, e così via; l'elenco completo delle operazioni
eseguite alla chiusura di un processo è il seguente:
-\begin{itemize*}
+\begin{itemize}
\item tutti i file descriptor sono chiusi;
\item viene memorizzato lo stato di terminazione del processo;
\item ad ogni processo figlio viene assegnato un nuovo padre (in genere
group} ciascun membro del gruppo viene bloccato, e poi gli vengono
inviati in successione i segnali \const{SIGHUP} e \const{SIGCONT}
(vedi ancora sez.~\ref{sec:sess_ctrl_term}).
-\end{itemize*}
+\end{itemize}
Oltre queste operazioni è però necessario poter disporre di un meccanismo
ulteriore che consenta di sapere come la terminazione è avvenuta: dato che in
cui riportare il suo stato di terminazione. Come verifica di questo
comportamento possiamo eseguire il nostro programma \cmd{forktest} imponendo a
ciascun processo figlio due secondi di attesa prima di uscire, il risultato è:
-\footnotesize
-\begin{verbatim}
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
[piccardi@selidor sources]$ ./forktest -c2 3
Process 1972: forking 3 child
Spawned 1 child, pid 1973
[piccardi@selidor sources]$ Child 3, parent 1, exiting
Child 2, parent 1, exiting
Child 1, parent 1, exiting
-\end{verbatim}
-\normalsize
+\end{Verbatim}
come si può notare in questo caso il processo padre si conclude prima dei
figli, tornando alla shell, che stampa il prompt sul terminale: circa due
secondi dopo viene stampato a video anche l'output dei tre figli che
sez.~\ref{sec:sess_job_control}), indicando al processo padre di aspettare 10
secondi prima di uscire; in questo caso, usando \cmd{ps} sullo stesso
terminale (prima dello scadere dei 10 secondi) otterremo:
-
-\footnotesize
-\begin{verbatim}
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
[piccardi@selidor sources]$ ps T
PID TTY STAT TIME COMMAND
419 pts/0 S 0:00 bash
570 pts/0 Z 0:00 [forktest <defunct>]
571 pts/0 Z 0:00 [forktest <defunct>]
572 pts/0 R 0:00 ps T
-\end{verbatim} %$
-\normalsize e come si vede, dato che non si è fatto nulla per riceverne lo
+\end{Verbatim}
+%$
+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 \index{zombie} \textit{zombie} e l'indicazione che
sono stati terminati.
senza che nessun figlio sia terminato. Pertanto per verificare il motivo del
ritorno della funzione occorre analizzare le informazioni che essa
restituisce; queste, al contrario delle precedenti \func{wait} e
-\func{waitpid}, sono ritornate nella struttura di tipo \struct{siginfo\_t}
-(vedi fig.~\ref{fig:sig_siginfo_t}) all'indirizzo puntato dall'argomento
-\param{infop}.
-
-Tratteremo nei dettagli questa struttura ed il significato dei suoi vari campi
-in sez.~\ref{sec:sig_sigaction}, per quanto ci interessa qui basta dire che al
-ritorno di \func{waitid} verranno avvalorati i seguenti campi:
+\func{waitpid} che usavano un semplice valore numerico, sono ritornate in una
+struttura di tipo \struct{siginfo\_t} (vedi fig.~\ref{fig:sig_siginfo_t})
+all'indirizzo puntato dall'argomento \param{infop}.
+
+Tratteremo nei dettagli la struttura \struct{siginfo\_t} ed il significato dei
+suoi vari campi in sez.~\ref{sec:sig_sigaction}, per quanto ci interessa qui
+basta dire che al ritorno di \func{waitid} verranno avvalorati i seguenti
+campi:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\var{si\_pid}] con il \acr{pid} del figlio.
\item[\var{si\_uid}] con l'user-ID reale (vedi sez.~\ref{sec:proc_perms}) del
Infine Linux, seguendo un'estensione di BSD, supporta altre due funzioni per
la lettura dello stato di terminazione di un processo, analoghe alle
precedenti ma che prevedono un ulteriore argomento attraverso il quale il
-kernel può restituire al padre informazioni sulle risorse usate dal processo
-terminato e dai vari figli. Le due funzioni sono \funcd{wait3} e
-\funcd{wait4}, che diventano accessibili definendo la macro
-\macro{\_USE\_BSD}; i loro prototipi sono:
+kernel può restituire al padre informazioni sulle risorse (vedi
+sez.~\ref{sec:sys_res_limits}) usate dal processo terminato e dai vari figli.
+Le due funzioni sono \funcd{wait3} e \funcd{wait4}, che diventano accessibili
+definendo la macro \macro{\_USE\_BSD}; i loro prototipi sono:
\begin{functions}
\headdecl{sys/times.h} \headdecl{sys/types.h} \headdecl{sys/wait.h}
\headdecl{sys/resource.h}
Oltre a mantenere lo stesso \acr{pid}, il nuovo programma fatto partire da
\func{exec} assume anche una serie di altre proprietà del processo chiamante;
la lista completa è la seguente:
-\begin{itemize*}
+\begin{itemize}
\item il \textit{process id} (\acr{pid}) ed il \textit{parent process id}
(\acr{ppid});
\item l'\textsl{user-ID reale}, il \textit{group-ID reale} ed i
\item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
\var{tms\_cutime}, \var{tms\_ustime} (vedi sez.~\ref{sec:sys_cpu_times}).
-\end{itemize*}
+\end{itemize}
Inoltre i segnali che sono stati impostati per essere ignorati nel processo
chiamante mantengono la stessa impostazione pure nel nuovo programma, tutti
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 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 sez.~\ref{sec:file_dir_read}) che effettua da sola
-l'impostazione del flag di \itindex{close-on-exec} \textit{close-on-exec}
-sulle directory che apre, in maniera trasparente all'utente.
+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 sez.~\ref{sec:file_dir_read}) che effettua
+da sola 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}
-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
-dettagli vedi sez.~\ref{sec:proc_perms}).
+restano gli stessi all'esecuzione di \func{exec}; normalmente vale lo stesso
+anche 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 di cui viene chiesta
+l'esecuzione ha 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 dettagli di questo comportamento si veda
+sez.~\ref{sec:proc_perms}).
Se il file da eseguire è in formato \emph{a.out} e necessita di librerie
condivise, viene lanciato il \textit{linker} dinamico \cmd{/lib/ld.so} prima
del programma per caricare le librerie necessarie ed effettuare il link
-dell'eseguibile. Se il programma è in formato ELF per caricare le librerie
-dinamiche viene usato l'interprete indicato nel segmento \const{PT\_INTERP},
-in genere questo è \sysfile{/lib/ld-linux.so.1} per programmi collegati con le
-\acr{libc5}, e \sysfile{/lib/ld-linux.so.2} per programmi collegati con le
-\acr{glibc}.
+dell'eseguibile.\footnote{il formato è ormai in completo disuso, per cui è
+ molto probabile che non il relativo supporto non sia disponibile.} Se il
+programma è in formato ELF per caricare le librerie dinamiche viene usato
+l'interprete indicato nel segmento \const{PT\_INTERP} pervisto dal formato
+stesso, in genere questo è \sysfile{/lib/ld-linux.so.1} per programmi
+collegati con le \acr{libc5}, e \sysfile{/lib/ld-linux.so.2} per programmi
+collegati con le \acr{glibc}.
Infine nel caso il file sia uno script esso deve iniziare con una linea nella
forma \cmd{\#!/path/to/interpreter [argomenti]} dove l'interprete indicato
\func{capget} e \func{capset}, sono soggette ad essere modificate con il
cambiamento del kernel (in particolare i tipi di dati delle strutture) ed
anche se finora l'interfaccia è risultata stabile, non c'è nessuna
-assicurazione che questa venga mantenuta. Pertanto se si vogliono scrivere
-programmi portabili che possano essere eseguiti su qualunque versione del
-kernel è opportuno utilizzare le interfacce di alto livello.
+assicurazione che questa venga mantenuta.\footnote{anzi, visto lo scarso
+ utilizzo di questa funzionalità ci sono state varie discussioni fra gli
+ sviluppatori del kernel relative all'eliminarla o al modificarla
+ radicalmente.} Pertanto se si vogliono scrivere programmi portabili che
+possano essere eseguiti su qualunque versione del kernel è opportuno
+utilizzare le interfacce di alto livello.
\begin{figure}[!htb]
\footnotesize
non c'è memoria sufficiente ad allocare i dati) viene restituito \macro{NULL}
ed \var{errno} viene impostata a \errval{ENOMEM}. La memoria necessaria a
mantenere i dati viene automaticamente allocata da \func{cap\_init}, ma dovrà
-essere disallocata esplicitamente quando non più necessaria utilizzando la
-funzione \funcd{cap\_free}, il cui prototipo è:
+essere disallocata esplicitamente quando non è più necessaria utilizzando, per
+questo l'interfaccia fornisce una apposita funzione, \funcd{cap\_free}, il cui
+prototipo è:
\begin{functions}
\headdecl{sys/capability.h}
della libreria sia per un \textit{capability state}, nel qual caso l'argomento
dovrà essere un dato di tipo \type{cap\_t}, che per una descrizione testuale
dello stesso,\footnote{cioè quanto ottenuto tramite la funzione
- \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere di tipo
-\texttt{char *}. L'argomento \param{obj\_d} deve corrispondere ad un oggetto
-ottenuto tramite altre funzioni della libreria, altrimenti la funzione fallirà
-con un errore di \errval{EINVAL}.
+ \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere un dato di
+tipo \texttt{char *}. Per questo l'argomento \param{obj\_d} è dichiarato come
+\texttt{void *} e deve sempre corrispondere ad un puntatore ottenuto tramite
+le altre funzioni della libreria, altrimenti la funzione fallirà con un errore
+di \errval{EINVAL}.
Infine si può creare una copia di un \textit{capability state} ottenuto in
precedenza tramite la funzione \funcd{cap\_dup}, il cui prototipo è:
copia, che conterrà gli stessi valori delle \textit{capabilities} presenti
nell'originale. La memoria necessaria viene allocata automaticamente dalla
funzione. Una volta effettuata la copia i due \textit{capability state}
-potranno essere modificati in maniera completamente indipendente.
+potranno essere modificati in maniera completamente
+indipendente.\footnote{alla fine delle operazioni si ricordi però di
+ disallocare anche la copia, oltre all'originale. }
-Una seconda classe di funzioni di servizio sono quelle per la gestione dei
-dati contenuti all'interno di un \textit{capability state}; la prima di esse è
-\funcd{cap\_clear}, il cui prototipo è:
+Una seconda classe di funzioni di servizio previste dall'interfaccia sono
+quelle per la gestione dei dati contenuti all'interno di un \textit{capability
+ state}; la prima di queste è \funcd{cap\_clear}, il cui prototipo è:
\begin{functions}
\headdecl{sys/capability.h}
\type{cap\_value\_t} deve indicare una sola capacità.\footnote{nel file di
header citato nella nota precedente il tipo \type{cap\_value\_t} è definito
come \ctyp{int}, ma i valori validi sono soltanto quelli di
- tab.~\ref{tab:proc_capabilities}.} Infine lo stato di una capacità è
-descritto ad una variabile di tipo \type{cap\_flag\_value\_t}, che a sua volta
-può assumere soltanto uno\footnote{anche questo è un tipo enumerato.} dei
-valori di tab.~\ref{tab:cap_value_type}.
+ tab.~\ref{tab:proc_capabilities}.}
+
+Infine lo stato di una capacità è descritto ad una variabile di tipo
+\type{cap\_flag\_value\_t}, che a sua volta può assumere soltanto
+uno\footnote{anche questo è un tipo enumerato.} dei valori di
+tab.~\ref{tab:cap_value_type}.
\begin{table}[htb]
\centering
stato di una capacità alla volta.
La funzione \func{cap\_set\_flag} può invece impostare in una sola chiamata
-più capacità, anche se solo all'interno dello stesso insieme; per questo essa
-prende un vettore di valori di tipo \type{cap\_value\_t} nell'argomento
-\param{caps}, la cui dimensione è specificata dall'argomento \param{ncap}. Il
-tipo di impostazione da eseguire (cancellazione o impostazione) viene indicato
-dall'argomento \param{value}.
+più \textit{capabilities}, anche se solo all'interno dello stesso insieme. Per
+questo motivo essa prende un vettore di valori di tipo \type{cap\_value\_t}
+nell'argomento \param{caps}, la cui dimensione viene specificata dall'argomento
+\param{ncap}. Il tipo di impostazione da eseguire (cancellazione o
+impostazione) viene indicato dall'argomento \param{value}.
Per la visualizzazione dello stato delle \textit{capabilities} l'interfaccia
prevede una funzione apposita, \funcd{cap\_to\_text}, il cui prototipo è:
come argomento, e, qualora l'argomento \param{length\_p} sia diverso da
\val{NULL}, restituisce nella variabile intera da questo puntata la lunghezza
della stringa. La stringa restituita viene allocata automaticamente dalla
-funzione e deve essere liberata con \func{cap\_free}.
+funzione e pertanto dovrà essere liberata con \func{cap\_free}.
-Fin quei abbiamo trattato delle funzioni di manipolazione dei
-\textit{capabilities state}; quando si vuole eseguire la lettura delle
-\textit{capabilities} del processo corrente si deve usare la funzione
-\funcd{cap\_get\_proc}, il cui prototipo è:
+Fin quei abbiamo trattato solo le funzioni di servizio relative alla
+manipolazione dei \textit{capabilities state}; l'interfaccia di gestione
+prevede però anche le funzioni per la gestione delle \textit{capabilities}
+stesse. La prima di queste è \funcd{cap\_get\_proc} che consente la lettura
+delle \textit{capabilities} del processo corrente, il suo prototipo è:
\begin{functions}
\headdecl{sys/capability.h}
assumere i valori \errval{EINVAL}, \errval{EPERM} o \errval{ENOMEM}. }
\end{functions}
-La funzione legge il valore delle \textit{capabilities} del processo corrente
-e restituisce il puntatore ad un \textit{capabilities state} contenente il
-risultato, che provvede ad allocare autonomamente, e che occorrerà liberare
-con \func{cap\_free} quando non sarà più utilizzato.
+La funzione legge il valore delle \textit{capabilities} associate al processo
+da cui viene invocata, restituendo il risultato tramite il puntatore ad un
+\textit{capabilities state} contenente tutti i dati che provvede ad allocare
+autonomamente e che di nuovo occorrerà liberare con \func{cap\_free} quando
+non sarà più utilizzato.
Se invece si vogliono leggere le \textit{capabilities} di un processo
specifico occorre usare la funzione \funcd{capgetp}, il cui
\errval{EPERM} o \errval{ENOMEM}.
}
\end{functions}
+%TODO controllare e correggere i codici di errore!!!
La funzione legge il valore delle \textit{capabilities} del processo indicato
-con l'argomento \param{pid}, salvando il risultato nel \textit{capabilities
- state} all'indirizzo \param{cap\_d} che deve essere stato creato in
-precedenza. Qualora il processo non esista si avrà un errore di
-\errval{ESRCH}. Gli stessi valori possono essere letti direttamente nel
-filesystem \textit{proc}, nei file \texttt{/proc/<pid>/status}; ad esempio per
-\texttt{init} si otterrà qualcosa del tipo:
+con l'argomento \param{pid}, e restituisce il risultato nel
+\textit{capabilities state} posto all'indirizzo indicato con l'argomento
+\param{cap\_d}; a differenza della precedente in questo caso il
+\textit{capability state} deve essere stato creato in precedenza. Qualora il
+processo indicato non esista si avrà un errore di \errval{ESRCH}. Gli stessi
+valori possono essere letti direttamente nel filesystem \textit{proc}, nei
+file \texttt{/proc/<pid>/status}; ad esempio per \texttt{init} si otterrà
+qualcosa del tipo:
\begin{Verbatim}
...
CapInh: 0000000000000000
CapPrm: 00000000fffffeff
CapEff: 00000000fffffeff
+...
\end{Verbatim}
Infine per impostare le \textit{capabilities} del processo corrente (non
{int nice(int inc)}
Aumenta il valore di \var{nice} per il processo corrente.
- \bodydesc{La funzione ritorna zero in caso di successo e -1 in caso di
- errore, nel qual caso \var{errno} può assumere i valori:
+ \bodydesc{La funzione ritorna zero o il nuovo valore di \var{nice} in caso
+ di successo e -1 in caso di errore, nel qual caso \var{errno} può assumere
+ i valori:
\begin{errlist}
\item[\errcode{EPERM}] un processo senza i privilegi di amministratore ha
specificato un valore di \param{inc} negativo.
l'amministratore può specificare valori negativi che permettono di aumentare
la priorità di un processo.
-In SUSv2 la funzione ritorna il nuovo valore di \var{nice}; Linux non segue
-questa convenzione, e per leggere il nuovo valore occorre invece usare la
-funzione \funcd{getpriority}, derivata da BSD, il cui prototipo è:
+Gli standard SUSv2 e POSIX.1 prevedono che la funzione ritorni il nuovo valore
+di \var{nice} del processo; tuttavia la system call di Linux non segue questa
+convenzione e restituisce sempre 0 in caso di successo, questo perchè $-1$ è
+un valore di \var{nice} legittimo e questo comporta una confusione con una
+eventuale condizione di errore.
+
+Fino alle \acr{glibc} 2.2.4 la funzione di libreria riportava direttamente il
+valore ottenuto dalla system call, violando lo standard, per cui per ottenere
+il nuovo valore occorreva una successiva chiamata alla funzione
+\func{getpriority}. A partire dalla \acr{glibc} 2.2.4 \func{nice} è stata
+reimplementata come funzione di libreria, e restituisce il valore di
+\var{nice} come richiesto dallo standard.\footnote{questo viene fatto
+ chiamando al suo interno \func{getpriority}, ed è questo il motivo delle due
+ possibilità per i valori di ritorno citati nella descrizione del prototipo.}
+In questo caso l'unico modo per rilevare in maniera affidabile una condizione
+di errore è quello di azzerare \var{errno} prima della chiamata della funzione
+e verificarne il valore quando \func{nice} restituisce $-1$.
+
+
+Per leggere il valore di nice di un processo occorre usare la funzione
+\funcd{getpriority}, derivata da BSD; il suo prototipo è:
\begin{prototype}{sys/resource.h}
{int getpriority(int which, int who)}
\end{table}
La funzione restituisce la priorità più alta (cioè il valore più basso) fra
-quelle dei processi specificati; dato che -1 è un valore possibile, per poter
-rilevare una condizione di errore è necessario cancellare sempre \var{errno}
-prima della chiamata alla funzione, per verificare che essa resti uguale a
-zero.
+quelle dei processi specificati; di nuovo, dato che $-1$ è un valore
+possibile, per poter rilevare una condizione di errore è necessario cancellare
+sempre \var{errno} prima della chiamata alla funzione per verificare che essa
+resti uguale a zero.
-Analoga a \func{getpriority} la funzione \funcd{setpriority} permette di
+Analoga a \func{getpriority} è la funzione \funcd{setpriority} che permette di
impostare la priorità di uno o più processi; il suo prototipo è:
\begin{prototype}{sys/resource.h}
{int setpriority(int which, int who, int prio)}
l'opportuna infrastruttura ed una nuova system call che permette di impostare
su quali processori far eseguire un determinato processo attraverso una
\textsl{maschera di affinità}. La corrispondente funzione di libreria è
-\funcd{sched\_setaffinity} ed il suo prototipo\footnote{di questa funzione (e
- della corrispondente \func{sched\_setaffinity}) esistono versioni diverse
- per gli argomenti successivi a \param{pid}: la prima (quella riportata nella
- pagina di manuale) prevedeva due ulteriori argomenti di tipo
- \texttt{unsigned int len} e \texttt{unsigned long *mask}, poi l'argomento
- \texttt{len} è stato eliminato, successivamente si è introdotta la versione
- riportata con però un secondo argomento di tipo \texttt{size\_t cpusetsize}
- (anche questa citata nella pagina di manuale); la versione citata è quella
- riportata nel manuale delle \textsl{glibc} e corrispondente alla definizione
- presente in \file{sched.h}.} è:
+\funcd{sched\_setaffinity} ed il suo prototipo è:
\begin{prototype}{sched.h}
- {int sched\_setaffinity (pid\_t pid, const cpu\_set\_t *cpuset)}
+ {int sched\_setaffinity (pid\_t pid, unsigned int cpusetsize, const
+ cpu\_set\_t *cpuset)}
Imposta la maschera di affinità del processo \param{pid}.
\bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
ed inoltre anche \errval{EFAULT}.}
\end{prototype}
+
+Questa funzione e la corrispondente \func{sched\_setaffinity} hanno una storia
+abbastanza complessa, la system call prevede l'uso di due ulteriori argomenti
+di tipo \texttt{unsigned int len} e \texttt{unsigned long *mask}, che
+corrispondono al fatto che la implementazione effettiva usa una semplice
+maschera binaria. Quando le funzioni vennero incluse nelle \acr{glibc}
+assunsero invece il prototipo appena mostrato. A complicare la cosa si
+aggiunge il fatto che nella versione 2.3.3 delle \acr{glibc} l'argomento
+\param{cpusetsize} è stato eliminato, per poi essere ripristinato nella
+versione 2.3.4.\footnote{pertanto se la vostra pagina di manuale non è
+ aggiornata, o usate quella particolare versione delle \acr{glibc}, potrete
+ trovare indicazioni diverse, il prototipo illustrato è quello riportato
+ nella versione corrente (maggio 2008) delle pagine di manuale e
+ corrispondente alla definizione presente in \file{sched.h}.}
+
La funzione imposta, con l'uso del valore contenuto all'indirizzo
\param{cpuset}, l'insieme dei processori sui quali deve essere eseguito il
processo identificato tramite il valore passato in \param{pid}. Come in
valore per un processo specifico usando la funzione
\funcd{sched\_getaffinity}, il suo prototipo è:
\begin{prototype}{sched.h}
- {int sched\_getaffinity (pid\_t pid, const cpu\_set\_t *cpuset)}
+ {int sched\_getaffinity (pid\_t pid, unsigned int cpusetsize,
+ const cpu\_set\_t *cpuset)}
Legge la maschera di affinità del processo \param{pid}.
\bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,