X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=21c683b9acaa593a2c8bc65696fe4b8e3bd849f7;hp=d4b7de25d080ae3667520c12cce3e7ef3947ded4;hb=b5f480c523e18a6f1fad62ee66c784e598c65bba;hpb=ce9e7bc52908e92783f1b88faf090e93b06fd320 diff --git a/prochand.tex b/prochand.tex index d4b7de2..21c683b 100644 --- a/prochand.tex +++ b/prochand.tex @@ -211,7 +211,7 @@ Come accennato nell'introduzione, ogni processo viene identificato dal sistema da un numero identificativo unico, il \textit{process id} o \acr{pid}; quest'ultimo è un tipo di dato standard, il \type{pid\_t} che in genere è un intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato è -\type{int}). +\ctyp{int}). Il \acr{pid} viene assegnato in forma progressiva ogni volta che un nuovo processo viene creato, fino ad un limite che, essendo il \acr{pid} un numero @@ -606,7 +606,7 @@ comune dopo l'esecuzione di una \func{fork} \item la directory di lavoro e la directory radice (vedi \secref{sec:file_work_dir} e \secref{sec:file_chroot}). \item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}). -\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigpending}) e le +\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigmask}) e le azioni installate (vedi \secref{sec:sig_gen_beha}). \item i segmenti di memoria condivisa agganciati al processo (vedi \secref{sec:ipc_xxx}). @@ -996,7 +996,7 @@ Lo standard POSIX.1 definisce una serie di macro di preprocessore da usare per analizzare lo stato di uscita. Esse sono definite sempre in \file{} ed elencate in \tabref{tab:proc_status_macro} (si tenga presente che queste macro prendono come parametro la variabile di tipo -\type{int} puntata da \var{status}). +\ctyp{int} puntata da \var{status}). Si tenga conto che nel caso di conclusione anomala il valore restituito da \macro{WTERMSIG} può essere confrontato con le costanti definite in @@ -1982,15 +1982,15 @@ valore di \var{counter} del processo corrente viene diminuito, questo assicura che anche i processi con priorità più bassa verranno messi in esecuzione. La priorità di un processo è così controllata attraverso il valore di -\var{nice}, che stabilisce la durata della \textit{time-slice}; un valore più -lungo infatti assicura una maggiore attribuzione di CPU. L'origine di questo -parametro sta nel fatto che in genere esso viene generalmente usato come per -diminuire la priorità di un processo, come termine di cortesia (da cui il -nome) nei confronti degli altri. +\var{nice}, che stabilisce la durata della \textit{time-slice}; per il +meccanismo appena descritto infatti un valore più lungo infatti assicura una +maggiore attribuzione di CPU. L'origine del nome di questo parametro sta nel +fatto che in genere esso viene generalmente usato per diminuire la priorità di +un processo, come misura di cortesia nei confronti degli altri. I processi infatti vengono creati dal sistema con lo stesso valore di -\var{nice} (nullo) e nessuno è privilegiato; il valore può essere modificato -solo attraverso la funzione \func{nice}, il cui prototipo è: +\var{nice} (nullo) e nessuno è privilegiato rispetto agli altri; il valore può +essere modificato solo attraverso la funzione \func{nice}, il cui prototipo è: \begin{prototype}{unistd.h} {int nice(int inc)} Aumenta il valore di \var{nice} per il processo corrente. @@ -1998,55 +1998,172 @@ solo attraverso la funzione \func{nice}, il cui prototipo \bodydesc{La funzione ritorna zero in caso di successo e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori: \begin{errlist} - \item[\macro{EPERM}] un utente normale ha specificato un valore di - \param{inc} negativo. + \item[\macro{EPERM}] un processo senza i privilegi di amministratore ha + specificato un valore di \param{inc} negativo. \end{errlist}} \end{prototype} L'argomento \param{inc} indica l'incremento del valore di \var{nice}: quest'ultimo può assumere valori compresi fra \macro{PRIO\_MIN} e -\macro{PRIO\_MAX} (che nel caso di Linux sono $-19$ e $20$) , ma per +\macro{PRIO\_MAX} (che nel caso di Linux sono $-19$ e $20$), ma per \param{inc} si può specificare un valore qualunque, positivo o negativo, ed il sistema provvederà a troncare il risultato nell'intervallo consentito. Valori positivi comportano maggiore \textit{cortesia} e cioè una diminuzione della -priorità. Solo l'amministratore può specificare valori negativi che permettono -di aumentare la priorità di un processo. - +priorità, ogni utente può solo innalzare il valore di un suo processo. Solo +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, per leggere il nuovo valore di occorre invece usare la +questa convenzione, e per leggere il nuovo valore occorre invece usare la funzione \func{getpriority}, derivata da BSD, il cui prototipo è: \begin{prototype}{sys/resource.h} {int getpriority(int which, int who)} - Restituisce la priorità per l'insieme dei processi specificati. +Restituisce il valore di \var{nice} per l'insieme dei processi specificati. \bodydesc{La funzione ritorna la priorità in caso di successo e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori: \begin{errlist} \item[\macro{ESRCH}] non c'è nessun processo che corrisponda ai valori di \param{which} e \param{who}. - \item[\macro{ESRCH}] il valore di \param{which} non è valido. + \item[\macro{EINVAL}] il valore di \param{which} non è valido. \end{errlist}} \end{prototype} +\noindent (in vecchie versioni può essere necessario includere anche +\file{}, questo non è più necessario con versioni recenti delle +librerie, ma è comunque utile per portabilità). +La funzione permette di leggere la priorità di un processo, di un gruppo di +processi (vedi \secref{sec:sess_proc_group}) o di un utente, a seconda del +valore di \param{which}, secondo la legenda di \tabref{tab:proc_getpriority}, +specificando un corrispondente valore per \param{who}; un valore nullo di +quest'ultimo indica il processo, il gruppo di processi o l'utente correnti. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|c|c|l|} + \hline + \param{which} & \param{who} & \textbf{Significato} \\ + \hline + \hline + \macro{PRIO\_PROCESS} & \type{pid\_t} & processo \\ + \macro{PRIO\_PRGR} & \type{pid\_t} & process group \\ + \macro{PRIO\_USER} & \type{uid\_t} & utente \\ + \hline + \end{tabular} + \caption{Legenda del valore dell'argomento \param{which} e del tipo + dell'argomento \param{who} delle funzioni \func{getpriority} e + \func{setpriority} per le tre possibili scelte.} + \label{tab:proc_getpriority} +\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. + +Analoga a \func{getpriority} la funzione \func{setpriority} permette di +settare la priorità di uno o più processi; il suo prototipo è: +\begin{prototype}{sys/resource.h} +{int setpriority(int which, int who, int prio)} + Setta la priorità per l'insieme dei processi specificati. + + \bodydesc{La funzione ritorna la priorità in caso di successo e -1 in caso di + errore, nel qual caso \var{errno} può assumere i valori: + \begin{errlist} + \item[\macro{ESRCH}] non c'è nessun processo che corrisponda ai valori di + \param{which} e \param{who}. + \item[\macro{EINVAL}] il valore di \param{which} non è valido. + \item[\macro{EPERM}] un processo senza i privilegi di amministratore ha + specificato un valore di \param{inc} negativo. + \item[\macro{EACCESS}] un processo senza i privilegi di amministratore ha + cercato di modificare la priorità di un processo di un altro utente. + \end{errlist}} +\end{prototype} + +La funzione setta la priorità al valore specificato da \param{prio} per tutti +i processi indicati dagli argomenti \param{which} e \param{who}. La gestione +dei permessi dipende dalle varie implementazioni; in Linux, secondo le +specifiche dello standard SUSv3, e come avviene per tutti i sistemi che +derivano da SYSV, è richiesto che il real o l'effective user id del processo +chiamante corrispondano al real user id (e solo quello) del processo di cui si +vuole cambiare la prorità; per i sistemi derivati da BSD invece (SunOS, +Ultrix, *BSD) la corrispondenza può essere anche con l'effective user id. \subsection{Il meccanismo di \textit{scheduling real-time}} \label{sec:proc_real_time} -Per settare le +Come spiegato in \secref{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 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 o RTAI, con i quali è possibile + ottenere un sistema effettivamente hard real-time. In tal caso infatti gli + interrupt vengono intercettati dall'interfaccia real-time, e gestiti + direttamente qualora ci sia la necessità di avere un processo con priorità + più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un +page fault si possono avere ritardi non previsti. Se l'ultimo problema può +essere aggirato attraverso l'uso delle funzioni di controllo della memoria +virtuale (vedi \secref{sec:proc_mem_lock}), il primo non è superabile e può +comportare ritardi non prevedibili riguardo ai tempi di esecuzione di +qualunque processo. + +L'interfaccia POSIX.1b comunque permette di assicurare ai processi che ne +hanno necessità una priorità assoluta superiore a quella dei normali processi. +In ogni caso occorre usare questo meccanismo con molta attenzione: se si dà ad +un processo una priorità assoluta e questo finisce in un loop infinito, dato +che fintanto che non esegue dell'I/O o viene messo in attesa nessun altro +processo potrà essere eseguito, esso resterà esecuzione assorbendo tutto il +tempo di esecuzione della CPU e non si avrà nessuna possibilità di riottenere +l'accesso al sistema. Per questo motivo è sempre opportuno, quando si lavora +con processi che usano priorità assolute, tenere attiva una shell cui si sia +assegnata la massima priorità assoluta, in modo da poter essere comunque in +grado di rientrare nel sistema. + +Quando c'è un processo con priorità assoluta lo scheduler lo metterà in +esecuzione prima di ogni processo normale. In caso di più processi sarà +eseguito per primo quello con priorità assoluta più alta. Quando ci sono due +processi con la stessa priorità assoluta tocca al kernel decidere quale dei +due deve essere eseguito. Questo viene fatto secondo la politica di scheduling +che ciascuno di questi processi ha; lo standard ne prevede due: +\begin{description} +\item[\textit{Round robin}] ciascun processo viene eseguito a turno per un + certo periodo di tempo (una \textit{time slice}). Solo i processi con la + stessa priorità ed in stato \textit{runnable} entrano nel circolo. +\item[\textit{FIFO}] il processo che ha atteso di più ha la precedenza e viene + eseguito fintanto che non cede volontariamente la CPU, si blocca, finisce o + viene interrotto da un processo a priorità più alta. +\end{description} + +La funzione per settare politica di scheduling ed i relativi parametri è +\func{sched\_setscheduler}; il suo prototipo è: +\begin{prototype}{sched.h} +{int sched\_setscheduler(pid\_t pid, int policy, const struct sched\_param *p)} + Setta priorità e politica di scheduling per il processo \param{pid}. + + \bodydesc{La funzione ritorna la priorità in caso di successo e -1 in caso di + errore, nel qual caso \var{errno} può assumere i valori: + \begin{errlist} + \item[\macro{ESRCH}] non c'è nessun processo che corrisponda ai valori di + \param{which} e \param{who}. + \item[\macro{EINVAL}] il valore di \param{which} non è valido. + \item[\macro{EPERM}] un processo senza i privilegi di amministratore ha + specificato un valore di \param{inc} negativo. + \item[\macro{EACCESS}] un processo senza i privilegi di amministratore ha + cercato di modificare la priorità di un processo di un altro utente. + \end{errlist}} +\end{prototype} + + + -\footnote{a meno che non si siano installate le patch di RTLinux o RTAI, con i - quali è possibile ottenere un sistema effettivamente hard real-time.} -in realtà non si tratta di un vero hard real-time, in quanto - la presenza di eventuali interrupt o di page fault può sempre interrompere - l'esecuzione di un processo, a meno di non installare le estensioni di - RTLinux o RTAI, il normale kernel non è real-time. @@ -2104,11 +2221,11 @@ operazioni atomiche (torneremo su questi aspetti in 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ò assumere che, in ogni piattaforma su cui è implementato Linux, il tipo -\type{int}, gli altri interi di dimensione inferiore ed i puntatori sono +\ctyp{int}, gli altri interi di dimensione inferiore ed i puntatori sono atomici. Non è affatto detto che lo stesso valga per interi di dimensioni maggiori (in cui l'accesso può comportare più istruzioni in assembler) o per le strutture. In tutti questi casi è anche opportuno marcare come -\type{volatile} le variabili che possono essere interessate ad accesso +\ctyp{volatile} le variabili che possono essere interessate ad accesso condiviso, onde evitare problemi con le ottimizzazioni del codice.