all'\ids{UID} reale o all'\ids{UID} salvato, ottenendo un errore di
\errcode{EPERM} negli altri casi.
-E' importante notare che la funzione può fallire con \errval{EAGAIN} anche
-quando viene invocata da un processo con privilegi di amministratore per
-cambiare il proprio l'\ids{UID} reale, sia per una temporanea indisponibilità
-di risorse del kernel, sia perché l'utente di cui si vuole assumere
-l'\ids{UID} andrebbe a superare un eventuale limite sul numero di processi (il
-limite \const{RLIMIT\_NPROC}, che tratteremo in
-sez.~\ref{sec:sys_resource_limit}),\footnote{non affronteremo qui l'altro caso
- di errore, che può avvenire solo quando si esegue la funzione all'interno di
- un diverso \textit{user namespace}, argomento su cui torneremo in
- sez.~\ref{sec:process_namespaces}.} pertanto occorre sempre verificare lo
-stato di uscita della funzione.
+E' importante notare che la funzione può fallire, con
+\errval{EAGAIN},\footnote{non affronteremo qui l'altro caso di errore, che può
+ avvenire solo quando si esegue la funzione all'interno di un diverso
+ \textit{user namespace}, argomento su cui torneremo in
+ sez.~\ref{sec:process_namespaces} ma la considerazione di controllare sempre
+ lo stato di uscita si applica allo stesso modo.} anche quando viene invocata
+da un processo con privilegi di amministratore per cambiare il proprio
+l'\ids{UID} reale, sia per una temporanea indisponibilità di risorse del
+kernel, sia perché l'utente di cui si vuole assumere l'\ids{UID} andrebbe a
+superare un eventuale limite sul numero di processi (il limite
+\const{RLIMIT\_NPROC}, che tratteremo in sez.~\ref{sec:sys_resource_limit}),
+pertanto occorre sempre verificare lo stato di uscita della funzione.
Non controllare questo tipo di errori perché si presume che la funzione abbia
sempre successo quando si hanno i privilegi di amministratore può avere
\fdesc{Imposta il \ids{GID} effettivo del processo corrente.}
}
{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual
-caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}.
+ caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}
+ tranne \errval{EAGAIN}.
}
\end{funcproto}
\fdesc{Imposta il \ids{GID} reale, effettivo e salvato del processo corrente.}
}
{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual
-caso \var{errno} può assumere solo il valore \errcode{EPERM}.
+caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}.
}
\end{funcproto}
\func{setresuid} imposta l'\ids{UID} reale, l'\ids{UID} effettivo e
l'\ids{UID} salvato del processo corrente ai valori specificati
rispettivamente dagli argomenti \param{ruid}, \param{euid} e \param{suid}. I
-processi non privilegiati possono cambiare uno qualunque degli\ids{UID} solo
+processi non privilegiati possono cambiare uno qualunque degli \ids{UID} solo
ad un valore corrispondente o all'\ids{UID} reale, o a quello effettivo o a
quello salvato, l'amministratore può specificare i valori che vuole. Un valore
di $-1$ per un qualunque argomento lascia inalterato l'identificatore
\fdecl{int setfsgid(gid\_t fsgid)}
\fdesc{Legge il \ids{GID} di filesystem del processo corrente.}
}
-{Le funzioni restituiscono il nuovo valore dell'identificativo in caso di
- successo e quello corrente per un errore, in questo caso non viene però
- impostato nessun codice di errore in \var{errno}.}
+
+{Le funzioni restituiscono sia in caso di successo che di errore il valore
+ corrente dell'identificativo, e in caso di errore non viene impostato nessun
+ codice in \var{errno}.}
\end{funcproto}
Le due funzioni sono analoghe ed usano il valore passato come argomento per
altri utenti, se il valore specificato coincide con uno dei di quelli del
gruppo \textit{real}, \textit{effective} o \textit{saved}.
+Il problema di queste funzioni è che non restituiscono un codice di errore e
+non c'è modo di sapere (con una singola chiamata) di sapere se hanno avuto
+successo o meno, per verificarlo occorre eseguire una chiamata aggiuntiva
+passando come argomento $-1$ (un valore impossibile per un identificativo),
+così fallendo si può di ottenere il valore corrente e verificare se è
+cambiato.
\subsection{Le funzioni per la gestione dei gruppi associati a un processo}
\label{sec:proc_setgroups}
vettore \param{list} che deve essere di dimensione pari a \param{size}. Non è
specificato se la funzione inserisca o meno nella lista il \ids{GID} effettivo
del processo. Se si specifica un valore di \param{size} uguale a $0$ allora
-l'argomento \param{list} non viene modificato, ma si ottiene il numero di
-gruppi supplementari.
+l'argomento \param{list} non viene modificato, ma si ottiene dal valore di
+ritorno il numero di gruppi supplementari.
Una seconda funzione, \funcd{getgrouplist}, può invece essere usata per
ottenere tutti i gruppi a cui appartiene utente identificato per nome; il suo
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
+processo; in Linux un processo può trovarsi in uno degli stati riportati in
tab.~\ref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato
\textit{runnable} concorrono per l'esecuzione. Questo vuol dire che, qualunque
sia la sua priorità, un processo non potrà mai essere messo in esecuzione
\hline
\hline
\textit{runnable}& \texttt{R} & Il processo è in esecuzione o è pronto ad
- essere eseguito (cioè è in attesa che gli
+ essere eseguito (in attesa che gli
venga assegnata la CPU).\\
\textit{sleep} & \texttt{S} & Il processo è in attesa di un
risposta dal sistema, ma può essere
preoccupare nella programmazione. Come accennato in Linux i processi ordinari
hanno tutti una priorità assoluta nulla; quello che determina quale, fra tutti
i processi in attesa di esecuzione, sarà eseguito per primo, è la cosiddetta
-\textsl{priorità dinamica},\footnote{quella che viene mostrata nella colonna
- \texttt{PR} del comando \texttt{top}.} che è chiamata così proprio perché
-varia nel corso dell'esecuzione di un processo.
+\textsl{priorità dinamica}, quella che viene mostrata nella colonna
+\texttt{PR} del comando \texttt{top}, che è chiamata così proprio perché varia
+nel corso dell'esecuzione di un processo.
Il meccanismo usato da Linux è in realtà piuttosto complesso,\footnote{e
dipende strettamente dalla versione di kernel; in particolare a partire
processo mettere in esecuzione avviene con un algoritmo molto più
complicato, che tiene conto anche della \textsl{interattività} del processo,
utilizzando diversi fattori, questa è una brutale semplificazione per
- rendere l'idea del funzionamento, per una trattazione più dettagliata, anche
- se non aggiornatissima, dei meccanismi di funzionamento dello
- \textit{scheduler} si legga il quarto capitolo di \cite{LinKernDev}.} Lo
-\textit{scheduler} infatti mette sempre in esecuzione, fra tutti i processi in
-stato \textit{runnable}, quello che ha il valore di priorità dinamica più
-basso.\footnote{con le priorità dinamiche il significato del valore numerico
- ad esse associato è infatti invertito, un valore più basso significa una
- priorità maggiore.} Il fatto che questo valore venga diminuito quando un
-processo non viene posto in esecuzione pur essendo pronto, significa che la
-priorità dei processi che non ottengono l'uso del processore viene
-progressivamente incrementata, così che anche questi alla fine hanno la
-possibilità di essere eseguiti.
+ rendere l'idea del funzionamento, per una trattazione più dettagliata dei
+ meccanismi di funzionamento dello \textit{scheduler}, anche se non
+ aggiornatissima, si legga il quarto capitolo di \cite{LinKernDev}.}
+
+Lo \textit{scheduler} infatti mette sempre in esecuzione, fra tutti i processi
+in stato \textit{runnable}, quello che ha il valore di priorità dinamica più
+basso; con le priorità dinamiche il significato del valore numerico ad esse
+associato è infatti invertito, un valore più basso significa una priorità
+maggiore. Il fatto che questo valore venga diminuito quando un processo non
+viene posto in esecuzione pur essendo pronto, significa che la priorità dei
+processi che non ottengono l'uso del processore viene progressivamente
+incrementata, così che anche questi alla fine hanno la possibilità di essere
+eseguiti.
Sia la dimensione della \textit{time-slice} che il valore di partenza della
priorità dinamica sono determinate dalla cosiddetta \textit{nice} (o
\end{errlist}}
\end{funcproto}
-La funzione permette, a seconda di quanto specificato
-nell'argomento \param{which}, di leggere il valore di \textit{nice} di un
-processo, di un gruppo di processi (vedi sez.~\ref{sec:sess_proc_group}) o di
-un utente indicato dall'argomento \param{who}. Nelle vecchie versioni può
-essere necessario includere anche \headfiled{sys/time.h}, questo non è più
-necessario con versioni recenti delle librerie, ma è comunque utile per
-portabilità.
+La funzione permette, a seconda di quanto specificato nell'argomento
+\param{which}, di leggere il valore di \textit{nice} o di un processo, o di un
+gruppo di processi (vedi sez.~\ref{sec:sess_proc_group}) o di un utente,
+indicati con l'argomento \param{who}. Nelle vecchie versioni può essere
+necessario includere anche \headfiled{sys/time.h}, questo non è più necessario
+con versioni recenti delle librerie, ma è comunque utile per portabilità.
I valori possibili per \param{which}, ed il tipo di valore che occorre usare
-in corrispondenza per \param{who} solo elencati nella legenda di
+in corrispondenza per \param{who}, solo elencati nella legenda di
tab.~\ref{tab:proc_getpriority} insieme ai relativi significati. Usare un
valore nullo per \param{who} indica, a seconda della corrispondente
-indicazione usata per \param{which} il processo, il gruppo di processi o
+indicazione usata per \param{which}, il processo, il gruppo di processi o
l'utente correnti.
\begin{table}[htb]
In caso di una indicazione che faccia riferimento a più processi, la funzione
restituisce la priorità più alta (cioè il valore più basso) fra quelle dei
-processi corrispondenti. Come per \func{nice} $-1$ è un valore possibile
+processi corrispondenti. Come per \func{nice}, $-1$ è un possibile valore
corretto, per cui di nuovo per poter rilevare una condizione di errore è
necessario cancellare sempre \var{errno} prima della chiamata alla funzione e
quando si ottiene un valore di ritorno uguale a $-1$ per verificare che essa
specchietto di tab.~\ref{tab:proc_getpriority}.
In questo caso come valore di \param{prio} deve essere specificato il valore
-di \textit{nice} da assegnare, e non un incremento (positivo o negativo) come
-nel caso di \func{nice}, nell'intervallo fra \const{PRIO\_MIN} ($-20$) e
-\const{PRIO\_MAX} ($19$). La funzione restituisce il valore di \textit{nice}
+di \textit{nice} da assegnare nell'intervallo fra \const{PRIO\_MIN} ($-20$) e
+\const{PRIO\_MAX} ($19$), e non un incremento (positivo o negativo) come nel
+caso di \func{nice}. La funzione restituisce il valore di \textit{nice}
assegnato in caso di successo e $-1$ in caso di errore, e come per \func{nice}
anche in questo caso per rilevare un errore occorre sempre porre a zero
\var{errno} prima della chiamata della funzione, essendo $-1$ un valore di
dello \textit{scheduler} di Linux, ed in particolare a partire dal kernel
2.6.23 l'uso di diversi valori di \textit{nice} ha un impatto molto più forte
nella distribuzione della CPU ai processi. Infatti se viene comunque calcolata
-una priorità dinamica per i processi che non ricevono la CPU così che anche
+una priorità dinamica per i processi che non ricevono la CPU, così che anche
essi possano essere messi in esecuzione, un alto valore di \textit{nice}
corrisponde comunque ad una \textit{time-slice} molto piccola che non cresce
comunque, per cui un processo a bassa priorità avrà davvero scarse possibilità
di essere eseguito in presenza di processi attivi a priorità più alta.
-
\subsection{Il meccanismo di \textit{scheduling real-time}}
\label{sec:proc_real_time}
Come spiegato in sez.~\ref{sec:proc_sched} lo standard POSIX.1b ha introdotto
-le priorità assolute per permettere la gestione di processi real-time. In
-realtà nel caso di Linux non si tratta di un vero \textit{hard real-time}, in
-quanto in presenza di eventuali interrupt il kernel interrompe l'esecuzione di
-un processo qualsiasi sia la sua priorità,\footnote{questo a meno che non si
- siano installate le patch di RTLinux, RTAI o Adeos, con i quali è possibile
- ottenere un sistema effettivamente \textit{hard real-time}. In tal caso
- infatti gli interrupt vengono intercettati dall'interfaccia
- \textit{real-time} (o nel caso di 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} 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.
+le priorità assolute per permettere la gestione di processi
+\textit{real-time}. In realtà nel caso di Linux non si tratta di un vero
+\textit{hard real-time}, in quanto in presenza di eventuali interrupt il
+kernel interrompe l'esecuzione di un processo, qualsiasi sia la sua
+priorità,\footnote{questo a meno che non si siano installate le patch di
+ RTLinux, RTAI o Adeos, con i quali è possibile ottenere un sistema
+ effettivamente \textit{hard real-time}. In tal caso infatti gli interrupt
+ vengono intercettati dall'interfaccia \textit{real-time} (o nel caso di
+ 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} 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.
Nonostante questo, ed in particolare con una serie di miglioramenti che sono
stati introdotti nello sviluppo del kernel,\footnote{in particolare a partire
caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EINVAL}] il valore di \param{policy} non esiste o il
- relativo valore di \param{p} non è valido per la politica scelta.
+ valore di \param{p} non è valido per la politica scelta.
\item[\errcode{EPERM}] il processo non ha i privilegi per attivare la
politica richiesta.
\item[\errcode{ESRCH}] il processo \param{pid} non esiste.
- \end{errlist}}
+ \end{errlist}}
\end{funcproto}
La funzione esegue l'impostazione per il processo specificato dall'argomento
-\param{pid}, un valore nullo di questo argomento esegue l'impostazione per il
+\param{pid}; un valore nullo di questo argomento esegue l'impostazione per il
processo corrente. La politica di \textit{scheduling} è specificata
dall'argomento \param{policy} i cui possibili valori sono riportati in
tab.~\ref{tab:proc_sched_policy}; la parte alta della tabella indica le
% TODO Aggiungere SCHED_DEADLINE, sulla nuova politica di scheduling aggiunta
% con il kernel 3.14, vedi anche Documentation/scheduler/sched-deadline.txt e
% http://lwn.net/Articles/575497/
+% vedi anche man 7 sched, man sched_setattr
Con le versioni più recenti del kernel sono state introdotte anche delle
varianti sulla politica di \textit{scheduling} tradizionale per alcuni carichi
processi interattivi, dato che essi sono per la maggior parte del tempo in
attesa di dati in ingresso da parte dell'utente.} La si usa pertanto, come
indica il nome, per processi che usano molta CPU (come programmi di calcolo)
-che in questo modo sono leggermente sfavoriti rispetto ai processi interattivi
-che devono rispondere a dei dati in ingresso, pur non perdendo il loro valore
-di \textit{nice}.
+che in questo modo, pur non perdendo il loro valore di \textit{nice}, sono
+leggermente sfavoriti rispetto ai processi interattivi che devono rispondere a
+dei dati in ingresso.
La politica \const{SCHED\_IDLE} invece è una politica dedicata ai processi che
si desidera siano eseguiti con la più bassa priorità possibile, ancora più
intervallo fra un massimo ed un minimo che nel caso di Linux sono
rispettivamente 1 e 99.
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{0.5\textwidth}
\includestruct{listati/sched_param.c}
\end{errlist}}
\end{funcproto}
-Le funzioni ritornano rispettivamente i due valori della massima e minima
-priorità statica possano essere ottenuti per una delle politiche di
-\textit{scheduling} \textit{real-time} indicata dall'argomento \param{policy}.
+Le funzioni ritornano rispettivamente il valore massimo e minimo usabile per
+la priorità statica di una delle politiche di \textit{scheduling}
+\textit{real-time} indicata dall'argomento \param{policy}.
Si tenga presente che quando si imposta una politica di \textit{scheduling}
real-time per un processo o se ne cambia la priorità statica questo 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.
+sarà in coda alla lista); l'esecuzione viene ripresa subito solo nel caso che
+esso sia stato interrotto da un processo a priorità più alta.
Solo un processo con i privilegi di amministratore\footnote{più precisamente
con la capacità \const{CAP\_SYS\_NICE}, vedi
con la possibilità di essere rimessi in esecuzione entro breve tempo, con
l'introduzione del \textit{Completely Fair Scheduler} questo comportamento è
cambiato ed un processo che chiama la funzione viene inserito nella lista dei
-processi inattivo, con un tempo molto maggiore.\footnote{è comunque possibile
+processi inattivi, con un tempo molto maggiore.\footnote{è comunque possibile
ripristinare un comportamento analogo al precedente scrivendo il valore 1
nel file \sysctlfiled{kernel/sched\_compat\_yield}.}
possibile legare automaticamente un gruppo di processi ad un singolo
processore.
-Nell'uso comune, almeno con i kernel successivi alla serie 2.6.x, l'uso di
+Nell'uso comune, almeno con i kernel successivi alla serie 2.6.x, utilizzare
questa funzione non è necessario, in quanto è lo \textit{scheduler} stesso che
provvede a mantenere al meglio l'affinità di processore. Esistono però
esigenze particolari, ad esempio quando un processo (o un gruppo di processi)
è utilizzato per un compito importante (ad esempio per applicazioni
\textit{real-time} o la cui risposta è critica) e si vuole la massima
-velocità, e con questa interfaccia diventa possibile selezionare gruppi di
+velocità; con questa interfaccia diventa possibile selezionare gruppi di
processori utilizzabili in maniera esclusiva. Lo stesso dicasi quando
l'accesso a certe risorse (memoria o periferiche) può avere un costo diverso a
seconda del processore, come avviene nelle architetture NUMA
cui questo numero può non essere sufficiente, e per questo è stato creato
questo tipo opaco e una interfaccia di gestione che permette di usare a basso
livello un tipo di dato qualunque rendendosi indipendenti dal numero di bit e
-dalla loro disposizione. Per questo le funzioni richiedono anche che oltre
-all'insieme di processori si indichi anche la dimensione dello stesso con
-l'argomento \param{setsize}, per il quale, se non si usa l'allocazione
-dinamica che vedremo a breve, ed è in genere sufficiente passare il valore
+dalla loro disposizione. Per questo le funzioni di libreria richiedono che
+oltre all'insieme di processori si indichi anche la dimensione dello stesso
+con l'argomento \param{setsize}, per il quale, se non si usa l'allocazione
+dinamica che vedremo a breve, è in genere sufficiente passare il valore
\code{sizeof(cpu\_set\_t)}.
L'interfaccia di gestione degli insiemi di processori, oltre alla definizione
Si tenga presente che trattandosi di macro l'argomento \param{cpu} può essere
valutato più volte. Questo significa ad esempio che non si può usare al suo
posto una funzione o un'altra macro, altrimenti queste verrebbero eseguite più
-volte, l'argomento cioè non deve avere \textsl{effetti collaterali} (in gergo
+volte; l'argomento cioè non deve avere \textsl{effetti collaterali} (in gergo
\textit{side effects}).\footnote{nel linguaggio C si
parla appunto di \textit{side effects} quando si usano istruzioni la cui
valutazione comporta effetti al di fuori dell'istruzione stessa, come il
\itindend{side~effects}
-Le CPU sono numerate da zero (che indica la prima disponibile) fino ad
-un numero massimo che dipende dalla architettura hardware. La costante
+Le CPU sono numerate da zero (che indica la prima disponibile) fino ad un
+numero massimo che dipende dall'architettura hardware. La costante
\constd{CPU\_SETSIZE} indica il numero massimo di processori che possono far
parte di un insieme (al momento vale sempre 1024), e costituisce un limite
-massimo al valore dell'argomento \param{cpu}.
-Dalla versione 2.6 della \acr{glibc} alle precedenti macro è stata aggiunta,
-per contare il numero di processori in un insieme, l'ulteriore:
+massimo al valore dell'argomento \param{cpu}. Dalla versione 2.6 della
+\acr{glibc} alle precedenti macro è stata aggiunta, per contare il numero di
+processori in un insieme, l'ulteriore:
{\centering
\vspace{3pt}