Completato (salvo revisioni) lo scheduling real-time
[gapil.git] / prochand.tex
index 21c683b9acaa593a2c8bc65696fe4b8e3bd849f7..474b75946572a30331b95a8180fb9277c6470d57 100644 (file)
@@ -1216,7 +1216,7 @@ la lista completa 
   \secref{sec:file_umask}) ed i \textit{lock} sui file (vedi
   \secref{sec:file_locking}).
 \item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
-  \secref{sec:sig_sigpending}).
+  \secref{sec:sig_sigmask}).
 \item i limiti sulle risorse (vedi \secref{sec:sys_limits}).
 \item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
   \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}).
@@ -2113,60 +2113,223 @@ virtuale (vedi \secref{sec:proc_mem_lock}), il primo non 
 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.
+In ogni caso 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 altro processo potrà essere eseguito, ed esso sarà mantenuto in
+esecuzione permanentemente assorbendo tutta la CPU e senza 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
+eseguito per primo quello con priorità assoluta più alta. Quando ci sono più
+processi con la stessa priorità assoluta questi vegono tenuti in una coda
+tocca al kernel decidere quale deve essere eseguito. 
+
+
+
+Il meccanismo con cui vengono gestiti questi processi dipende dalla politica
+di scheduling che si è scelto; lo standard ne prevede due:
+\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
+\item[\textit{FIFO}] il processo viene eseguito fintanto che non cede
+  volontariamente la CPU, si blocca, finisce o viene interrotto da un processo
+  a priorità più alta.
+\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}
+\end{basedescript}
 
-La funzione per settare politica di scheduling ed i relativi parametri è
-\func{sched\_setscheduler}; il suo prototipo è:
+La funzione per settare le politiche di scheduling (sia real-time che
+ordinarie) 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.
+    \begin{errlist}
+    \item[\macro{ESRCH}] il processo \param{pid} non esiste.
+    \item[\macro{EINVAL}] il valore di \param{policy} non esiste o il relativo
+      valore di \param{p} non è valido.
+    \item[\macro{EPERM}] il processo non ha i privilegi per attivare la
+      politica richiesta (vale solo per \macro{SCHED\_FIFO} e
+      \macro{SCHED\_RR}).
   \end{errlist}}
 \end{prototype}
 
+La funzione esegue il settaggio per il processo specificato; un valore nullo
+di \param{pid} esegue il settaggio per il processo corrente, solo un processo
+con i privilegi di amministratore può settare delle priorità assolute diverse
+da zero. La politica di scheduling è specificata dall'argomento \param{policy}
+i cui possibili valori sono riportati in \tabref{tab:proc_sched_policy}; un
+valore negativo per \param{policy} mantiene la politica di scheduling
+corrente.
 
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|c|l|}
+    \hline
+    \textbf{Policy}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \macro{SCHED\_FIFO} & Scheduling real-time con politica \textit{FIFO} \\
+    \macro{SCHED\_RR}   & Scheduling real-time con politica \textit{Round
+    Robin} \\
+    \macro{SCHED\_OTHER}& Scheduling ordinario\\
+    \hline
+  \end{tabular}
+  \caption{Valori dell'argomento \param{policy}  per la funzione
+    \func{sched\_setscheduler}. }
+  \label{tab:proc_sched_policy}
+\end{table}
 
+Il valore della priorità è passato attraverso la struttura \var{sched\_param}
+(riportata in \figref{fig:sig_sched_param}), il cui solo campo attualmente
+definito è \var{sched\_priority}, che nel caso delle priorità assolute deve
+essere specificato nell'intervallo fra 1 e 99 (il valore zero è legale, ma
+indica i processi normali). Lo standard POSIX.1b prevede comunque che questi
+due valori possano essere ottenuti per ciascuna politica di scheduling dalle
+funzioni \func{sched\_get\_priority\_max} e \func{sched\_get\_priority\_min},
+i cui prototipi sono:
+\begin{functions}
+  \headdecl{sched.h}
+  
+  \funcdecl{int sched\_get\_priority\_max(int policy)} Legge il valore
+  massimo della priorità statica per la politica di scheduling \param{policy}.
 
+  
+  \funcdecl{int sched\_get\_priority\_min(int policy)} Legge il valore minimo
+  della priorità statica per la politica di scheduling \param{policy}.
+  
+  \bodydesc{La funzioni ritornano il valore della priorità in caso di successo
+    e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\macro{EINVAL}] il valore di \param{policy} è invalido.
+  \end{errlist}}
+\end{functions}
 
 
+I processi con politica di scheduling \macro{SCHED\_OTHER} devono specificare
+un valore nullo (altrimenti si avrà un errore \macro{EINVAL}), questo valore
+infatti non ha niente a che vedere con la priorità dinamica determinata dal
+valore di \var{nice}, che deve essere settato con le funzioni viste in
+precedenza.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct sched_param {
+    int sched_priority;
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{sched\_param}.} 
+  \label{fig:sig_sched_param}
+\end{figure}
 
+Il kernel mantiene i processi con la stessa priorità assoluta in una lista, ed
+esegue sempre il primo della lista, mentre un nuovo processo che torna in
+stato \textit{runnable} viene sempre inserito in coda alla lista. Se la
+politica scelta è \macro{SCHED\_FIFO} quando il processo viene eseguito 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.
+
+La priorità assoluta può essere riletta indietro dalla funzione
+\func{sched\_getscheduler}, il cui prototipo è:
+\begin{prototype}{sched.h}
+{int sched\_getscheduler(pid\_t pid)}
+  Legge la politica di scheduling per il processo \param{pid}.
+  
+  \bodydesc{La funzione ritorna la politica di scheduling in caso di successo
+    e -1 in caso di errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\macro{ESRCH}] il processo \param{pid} non esiste.
+    \item[\macro{EINVAL}] il valore di \param{pid} è negativo.
+  \end{errlist}}
+\end{prototype}
+
+La funzione restituisce il valore (secondo la quanto elencato in
+\tabref{tab:proc_sched_policy}) della politica di scheduling per il processo
+specificato; se \param{pid} è nullo viene restituito quello del processo
+chiamante.
+
+Se si intende operare solo sulla priorità assoluta di un processo si possono
+usare le funzioni \func{sched\_setparam} e \func{sched\_getparam}, i cui
+prototipi sono:
+  
+\begin{functions}
+  \headdecl{sched.h}
+
+  \funcdecl{int sched\_setparam(pid\_t pid, const struct sched\_param *p)}
+  Setta la priorità assoluta del processo \param{pid}.
+
+
+  \funcdecl{int sched\_getparam(pid\_t pid, struct sched\_param *p)}
+  Legge la priorità assoluta del 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}] il processo \param{pid} non esiste.
+    \item[\macro{EINVAL}] il valore di \param{pid} è negativo.
+  \end{errlist}}
+\end{functions}
+
+L'uso di \func{sched\_setparam} che è del tutto equivalente a
+\func{sched\_setscheduler} con \param{priority} uguale a -1. Come per
+\func{sched\_setscheduler} specificando 0 come valore di \param{pid} si opera
+sul processo corrente. La disponibilità di entrambe le funzioni può essere
+verificata controllando la macro \macro{\_POSIX\_PRIORITY\_SCHEDULING} che è
+definita nell'header \macro{sched.h}.
+
+L'ultima funzione che permette di leggere le informazioni relative ai processi
+real-time è \func{sched\_rr\_get\_interval}, che permette di ottenere la
+lunghezza della \textit{time slice} usata dalla politica \textit{round robin};
+il suo protototipo è:
+\begin{prototype}{sched.h}
+  {int sched\_rr\_get\_interval(pid\_t pid, struct timespec *tp)} Legge in
+  \param{tp} la durata della \textit{time slice} per il processo \param{pid}.
+  
+  \bodydesc{La funzione ritorna 0in caso di successo e -1 in caso di errore,
+    nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\macro{ESRCH}] il processo \param{pid} non esiste.
+    \item[\macro{ENOSYS}] la system call non è stata implementata.
+  \end{errlist}}
+\end{prototype}
+
+La funzione restituisce il valore dell'intervallo di tempo usato per la
+politica \textit{round robin} in una struttura \var{timespec}, (la cui
+definizione si può trovare in \secref{fig:sig_timespec_def}).
+
+
+Come accennato ogni processo che usa lo scheduling real-time può rilasciare
+volontariamente la CPU; questo viene fatto attraverso la funzione
+\func{sched\_yield}, il cui prototipo è:
+\begin{prototype}{sched.h}
+  {int sched\_yield(void)} 
+  
+  Rilascia volontariamente l'esecuzione.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+    nel qual caso \var{errno} viene settata opportunamente.}
+\end{prototype}
 
+La funzione fa si che il processo rilasci la CPU, in modo da essere rimesso in
+coda alla lista dei processi da eseguire, e permettere l'esecuzione di un
+altro processo; se però il processo è l'unico ad essere presente sulla coda
+l'esecuzione non sarà interrotta. In genere usano questa funzione i processi
+in modalità \textit{fifo}, per permettere l'esecuzioni degli altri processi
+con pari priorità quando la sezione più urgente è finita.
 
 
 \section{Problematiche di programmazione multitasking}