From 7abda42da0ed18f06b0ad260e49671a68c886a16 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Wed, 29 Jul 2009 14:02:42 +0000 Subject: [PATCH] Finite priorita` di I/O. --- filedir.tex | 8 +- prochand.tex | 225 ++++++++++++++++++++++++++------------------------- 2 files changed, 119 insertions(+), 114 deletions(-) diff --git a/filedir.tex b/filedir.tex index f139117..40602cb 100644 --- a/filedir.tex +++ b/filedir.tex @@ -3023,7 +3023,6 @@ capacit vengono mantenute le stesse capacità del processo padre. - % TODO verificare per process capability bounding set, vedi: % http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b7391de67da515c91f48aa371de77cb6cc5c07e @@ -4058,12 +4057,14 @@ file descriptor, da specificare con il loro primo argomento. Anche in questo caso l'argomento \param{name} deve essere specificato con le modalità già illustrate in precedenza per le altre funzioni relative agli attributi estesi. - \itindend{Extended~Attributes} + \subsection{Le \textit{Access Control List}} \label{sec:file_ACL} +% la documentazione di sistema è nei pacchetti libacl1-dev e acl +% vedi anche http://www.suse.de/~agruen/acl/linux-acls/online/ \itindbeg{Access~Control~List} @@ -4836,9 +4837,6 @@ ad un altra con \funcd{acl\_copy\_entry} o eliminare una voce da una ACL con \itindend{Access~Control~List} -% la documentazione di sistema è nei pacchetti libacl1-dev e acl -% vedi anche http://www.suse.de/~agruen/acl/linux-acls/online/ - \subsection{La funzione \func{chroot}} diff --git a/prochand.tex b/prochand.tex index d649018..9164c66 100644 --- a/prochand.tex +++ b/prochand.tex @@ -146,15 +146,14 @@ fig.~\ref{fig:proc_task_struct}. % TODO la task_struct è cambiata per qualche dettaglio vedi anche % http://www.ibm.com/developerworks/linux/library/l-linux-process-management/ +% TODO completare la parte su quando viene chiamato lo scheduler. 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 + di altre occasioni.} (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},\footnote{fino al kernel 2.4 il valore usuale di questa costante era 100, per tutte le architetture eccetto l'alpha, per la quale era 1000, nel 2.6 è stato portato a 1000 su tutte le architetture; occorre fare @@ -171,7 +170,6 @@ valore da parte del processore che può essere messo in stato di sospensione anche per lunghi periodi di tempo.} - 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 @@ -2998,7 +2996,7 @@ disco scrivendo nel file \texttt{/sys/block/\textit{dev}/queue/scheduler} scheduler disponibili sono mostrati dal contenuto dello stesso file che riporta fra parentesi quadre quello attivo, il default in tutti i kernel recenti è proprio il \texttt{cfq},\footnote{nome con cui si indica appunto lo - scheduler \textit{Completely Fair Queuing}.} che supporta le priorità; per i + scheduler \textit{Completely Fair Queuing}.} che supporta le priorità. Per i dettagli sulle caratteristiche specifiche degli altri scheduler, la cui discussione attiene a problematiche di ambito sistemistico, si consulti la documentazione nella directory \texttt{Documentation/block/} dei sorgenti del @@ -3008,31 +3006,37 @@ Una volta che si sia impostato lo scheduler CFQ ci sono due specifiche system call, specifiche di Linux, che consentono di leggere ed impostare le priorità di I/O.\footnote{se usate in corrispondenza ad uno scheduler diverso il loro utilizzo non avrà alcun effetto.} Dato che non esiste una interfaccia -diretta nelle librerie del C per queste due funzioni occorrerà invocarle -tramite la funzione \func{syscall} (come illustrato in -sez.~\ref{sec:intro_syscall}). La prima delle due è \funcd{ioprio\_get}, che -consente di leggere la priorità; il suo prototipo è: -\begin{prototype}{linux/ioprio.h} - {int ioprio\_get(int which, int who)} - Legge la priorità di I/O. +diretta nelle \acr{glibc} per queste due funzioni occorrerà invocarle tramite +la funzione \func{syscall} (come illustrato in +sez.~\ref{sec:intro_syscall}). Le due funzioni sono \funcd{ioprio\_get} ed +\funcd{ioprio\_set}; i rispettivi prototipi sono: +\begin{functions} + \headdecl{linux/ioprio.h} + \funcdecl{int ioprio\_get(int which, int who)} + \funcdecl{int ioprio\_set(int which, int who, int ioprio)} + + Rileva o imposta la priorità di I/O di un processo. - \bodydesc{La funzione ritorna un valore positivo in caso di successo e $-1$ - in caso di errore, nel qual caso \var{errno} può assumere i valori: + \bodydesc{Le funzioni ritornano rispettivamente un intero positivo + (indicante la priorità) o 0 in caso di successo e $-1$ in caso di errore, + nel qual caso \var{errno} può assumere i valori: \begin{errlist} \item[\errcode{ESRCH}] non esiste il processo indicato. \item[\errcode{EINVAL}] i valori di \param{which} e \param{who} non sono validi. + \item[\errcode{EPERM}] non si hanno i privilegi per eseguire + l'impostazione (solo per \func{ioprio\_set}). \end{errlist} } -\end{prototype} +\end{functions} -La funzione legge la priorità di I/O sulla base dell'indicazione dei due -argomenti \param{which} e \param{who} che hanno lo stesso significato già -visto per gli analoghi argomenti di \func{getpriority} e \func{setpriority}; -in questo caso vengono però per \param{which} sono state definite delle -costanti apposite, illustrate in tab.~\ref{tab:ioprio_args}. A seconda dei -valori è così possibile leggere delle priorità per il singolo processo, per i +Le funzioni leggono o impostano la priorità di I/O sulla base dell'indicazione +dei due argomenti \param{which} e \param{who} che hanno lo stesso significato +già visto per gli omonimi argomenti di \func{getpriority} e +\func{setpriority}. Anche in questo caso si deve specificare il valore +di \param{which} tramite le opportune costanti riportate in +tab.~\ref{tab:ioprio_args} che consentono di indicare un singolo processo, i processi di un \textit{process group} (tratteremo questo argomento in -sez.~\ref{sec:sess_proc_group}) o per tutti o processi di un utente. +sez.~\ref{sec:sess_proc_group}) o tutti o processi di un utente. \begin{table}[htb] \centering @@ -3054,84 +3058,23 @@ sez.~\ref{sec:sess_proc_group}) o per tutti o processi di un utente. \label{tab:ioprio_args} \end{table} -Gli stessi valori possono essere utilizzati anche quando si vuole eseguire -l'impostazione di una priorità di I/O; in tal caso si deve usare la funzione -\funcd{ioprio\_set}, il cui prototipo è: -\begin{prototype}{linux/ioprio.h} - {int ioprio\_set(int which, int who, int ioprio)} - - Imposta la priorità di I/O. - - \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} può assumere i valori: - \begin{errlist} - \item[\errcode{EPERM}] non si hanno i privilegi per eseguire - l'impostazione. - \end{errlist} - oltre a \errcode{EINVAL} e \errcode{ESRCH} con lo stesso significato di - \func{ioprio\_get}. } -\end{prototype} - - -La funzione in caso di successo restituisce un intero positivo che esprime il -valore della priorità di I/O, questo è composto di due parti, una che esprime -la cosiddetta \textsl{classe} di scheduling, l'altro che esprime la priorità -all'interno della classe stessa. Le classi previste dallo scheduler CFQ sono -tre, identificate da altrettanti costanti, riportate in -tab.~\ref{tab:IOsched_class}. - -\begin{table}[htb] - \centering - \footnotesize - \begin{tabular}[c]{|l|l|} - \hline - \textbf{Classe} & \textbf{Significato} \\ - \hline - \hline - \const{IOPRIO\_CLASS\_RT} & Scheduling di I/O \textit{real time}.\\ - \const{IOPRIO\_CLASS\_BE} & Scheduling di I/O ordinario.\\ - \const{IOPRIO\_CLASS\_IDLE}& Scheduling di I/O di priorità minima.\\ - \hline - \end{tabular} - \caption{Costanti che identificano le classi di scheduling di I/O.} - \label{tab:IOsched_class} -\end{table} - -La tre classi ricalcano i concetti presenti anche nello scheduler della CPU; -la classe di priorità più bassa è \const{IOPRIO\_CLASS\_IDLE}, i processi in -questa classe riescono ad accedere a disco soltanto quando nessun altro -processo richiede l'accesso; occorre pertanto usarla con molta attenzione, -perché un processo in questa classe può venire completamente bloccato quando -ci sono altri processi di priorità più alta che stanno accedendo al -disco; in questa classe non esistono valori di priorità, tutti i processi -hanno la stessa priorità, che è la minima possibile. - -La classe per le priorità ordinarie è \const{IOPRIO\_CLASS\_BE} (il nome sta -per \textit{best-effort}) che è quella usata di default per tutti processi; in -questo caso esistono delle priorità all'interno della classe che corrispondono -all'assegnazione ad un processo di una maggiore banda passante nell'accesso a -disco rispetto agli altri senza però che questo possa bloccare indefinitamente -l'accesso agli altri; con un concetto simile a quello dei valori di -\textit{nice} per le priorità di processore. In questo caso esistono però -soltanto otto diverse priorità, indicate da un valore numerico fra 0 e -7,\footnote{come per \textit{nice} anche in questo caso un valore più basso - indica una priorità maggiore.} che sono assegnate ai singoli processi in -maniera automatica a partire dal loro valore di \textit{nice}.\footnote{come - riportato nella documentazione il valore della priorità viene calcolato con - la formula: $\mathtt{prio}=(\mathtt{nice}+20)/5$.} - -Infine la classe di priorità \textit{real-time} \const{IOPRIO\_CLASS\_RT} -ricalca le analoghe priorità di processore: un processo in questa classe ha -sempre la precedenza nell'accesso a disco rispetto a tutti i processi di -priorità inferiore, e pertanto è in grado di bloccare completamente gli -altri. Anche in questo caso ci sono 8 priorità diverse con un valore numerico -fra 0 e 7, con una priorità più elevata per valori inferiori. - -Per manipolare il valori delle priorità di I/O sono state approntate delle -opportune macro, in grado di estrarre i valori di priorità e la classe dai -valori restituiti da \func{ioprio\_get} e di creare da questi un opportuno -valore da passare a \func{ioprio\_set}, che si sono riportate in -tab.~\ref{tab:IOsched_class_macro}. +In caso di successo \func{ioprio\_get} restituisce un intero positivo che +esprime il valore della priorità di I/O, questo valore è una maschera binaria +composta da due parti, una che esprime la \textsl{classe} di scheduling di I/O +del processo, l'altra che esprime, quando la classe di scheduling lo prevede, +la priorità del processo all'interno della classe stessa. Questo stesso +formato viene utilizzato per indicare il valore della priorità da impostare +con l'argomento \param{ioprio} di \func{ioprio\_set}. + +Per la gestione dei valori che esprimono le priorità di I/O sono state +definite delle opportune macro di preprocessore, riportate in +tab.~\ref{tab:IOsched_class_macro}. I valori delle priorità si ottengono o si +impostano usando queste macro. Le prime due si usano con il valore restituito +da \func{ioprio\_get} e per ottenere rispettivamente la classe di +scheduling\footnote{restituita dalla macro con i valori di + tab.~\ref{tab:IOsched_class}.} e l'eventuale valore della priorità. La terza +macro viene invece usata per creare un valore di priorità da usare come +argomento di \func{ioprio\_set} per eseguire una impostazione. \begin{table}[htb] \centering @@ -3142,12 +3085,12 @@ tab.~\ref{tab:IOsched_class_macro}. \hline \hline \macro{IOPRIO\_PRIO\_CLASS}\texttt{(\textit{value})} - & dato il valore di un priorità come - restituito da \func{ioprio\_get} ottiene il + & dato il valore di una priorità come + restituito da \func{ioprio\_get} estrae il valore della classe.\\ \macro{IOPRIO\_PRIO\_DATA}\texttt{(\textit{value})} - & dato il valore di un priorità come - restituito da \func{ioprio\_get} ottiene il + & dato il valore di una priorità come + restituito da \func{ioprio\_get} estrae il valore della priorità.\\ \macro{IOPRIO\_PRIO\_VALUE}\texttt{(\textit{class},\textit{prio})} & dato un valore di priorità ed una classe @@ -3159,10 +3102,74 @@ tab.~\ref{tab:IOsched_class_macro}. \label{tab:IOsched_class_macro} \end{table} +Le classi di scheduling previste dallo scheduler CFQ sono tre, e ricalcano tre +diverse modalità di distribuzione delle risorse analoghe a quelle già adottate +anche nel funzionamento dello scheduler del processore. Ciascuna di esse è +identificata tramite una opportuna costante, secondo quanto riportato in +tab.~\ref{tab:IOsched_class}. + +La classe di priorità più bassa è \const{IOPRIO\_CLASS\_IDLE}; i processi in +questa classe riescono ad accedere a disco soltanto quando nessun altro +processo richiede l'accesso. Occorre pertanto usarla con molta attenzione, +perché un processo in questa classe può venire completamente bloccato quando +ci sono altri processi in una qualunque delle altre due classi che stanno +accedendo al disco. Quando si usa questa classe non ha senso indicare un +valore di priorità, dato che in questo caso non esiste nessuna gerarchia e la +priorità è identica, la minima possibile, per tutti i processi. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Classe} & \textbf{Significato} \\ + \hline + \hline + \const{IOPRIO\_CLASS\_RT} & Scheduling di I/O \textit{real time}.\\ + \const{IOPRIO\_CLASS\_BE} & Scheduling di I/O ordinario.\\ + \const{IOPRIO\_CLASS\_IDLE}& Scheduling di I/O di priorità minima.\\ + \hline + \end{tabular} + \caption{Costanti che identificano le classi di scheduling di I/O.} + \label{tab:IOsched_class} +\end{table} +La seconda classe di priorità di I/O è \const{IOPRIO\_CLASS\_BE} (il nome sta +per \textit{best-effort}) che è quella usata ordinariamente da tutti +processi. In questo caso esistono priorità diverse che consentono di +assegnazione di una maggiore banda passante nell'accesso a disco ad un +processo rispetto agli altri, con meccanismo simile a quello dei valori di +\textit{nice} in cui si evita che un processo a priorità più alta possa +bloccare indefinitamente quelli a priorità più bassa. In questo caso però le +diverse priorità sono soltanto otto, indicate da un valore numerico fra 0 e 7 +e come per \textit{nice} anche in questo caso un valore più basso indica una +priorità maggiore. + + +Infine la classe di priorità di I/O \textit{real-time} +\const{IOPRIO\_CLASS\_RT} ricalca le omonime priorità di processore: un +processo in questa classe ha sempre la precedenza nell'accesso a disco +rispetto a tutti i processi delle altre classi e di un processo nella stessa +classe ma con priorità inferiore, ed è pertanto in grado di bloccare +completamente tutti gli altri. Anche in questo caso ci sono 8 priorità diverse +con un valore numerico fra 0 e 7, con una priorità più elevata per valori più +bassi. + +In generale nel funzionamento ordinario la priorità di I/O di un processo +viene impostata in maniera automatica nella classe \const{IOPRIO\_CLASS\_BE} +con un valore ottenuto a partire dal corrispondente valore di \textit{nice} +tramite la formula: $\mathtt{\mathit{prio}}=(\mathtt{\mathit{nice}}+20)/5$. Un +utente ordinario può modificare con \func{ioprio\_set} soltanto le priorità +dei processi che gli appartengono,\footnote{per la modifica delle priorità di + altri processi occorrono privilegi amministrativi, ed in particolare la + capacità \const{CAP\_SYS\_NICE} (vedi sez.~\ref{sec:proc_capabilities}).} +cioè quelli il cui user-ID reale corrisponde all'user-ID reale o effettivo del +chiamante. Data la possibilità di ottenere un blocco totale dello stesso, solo +l'amministratore\footnote{o un processo con la capacità + \const{CAP\_SYS\_ADMIN} (vedi sez.~\ref{sec:proc_capabilities}).} può +impostare un processo ad una priorità di I/O nella classe +\const{IOPRIO\_CLASS\_RT} o \const{IOPRIO\_CLASS\_IDLE}. -%TODO trattare le priorità di I/O -% vedi man ioprio_set e Documentation/block/ioprio.txt %TODO trattare le funzionalità per il NUMA % vedi man numa e le pagine di manuale relative @@ -3378,9 +3385,9 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso % LocalWords: next cat for COMMAND pts bash defunct TRAPPED DUMPED Killable PR % LocalWords: SIGKILL static RLIMIT preemption PREEMPT VOLUNTARY IDLE RTPRIO % LocalWords: Completely Fair compat Uniform CFQ Queuing elevator dev cfq RT +% LocalWords: Documentation block syscall ioprio IPRIO CLASS class best effort %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: -% LocalWords: Documentation block syscall ioprio IPRIO CLASS -- 2.30.2