+\end{errlist}}
+\end{funcproto}
+
+La funzione restituisce il valore, secondo quanto elencato in
+tab.~\ref{tab:proc_sched_policy}, della politica di \textit{scheduling} per il
+processo specificato dall'argomento \param{pid}, se questo è nullo viene
+restituito il valore relativo al processo chiamante.
+
+L'ultima funzione di sistema che permette di leggere le informazioni relative
+ai processi real-time è \funcd{sched\_rr\_get\_interval}, che permette di
+ottenere la lunghezza della \textit{time-slice} usata dalla politica
+\textit{round robin}; il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sched.h}
+\fdecl{int sched\_rr\_get\_interval(pid\_t pid, struct timespec *tp)}
+\fdesc{Legge la durata della \textit{time-slice} per lo \textit{scheduling}
+ \textit{round robin}.}
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+caso \var{errno} assumerà uno dei valori:
+\begin{errlist}
+\item[\errcode{EINVAL}] l'argomento \param{pid} non è valido.
+\item[\errcode{ENOSYS}] la \textit{system call} non è presente (solo per
+ kernel arcaici).
+\item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+\end{errlist}
+ed inoltre anche \errval{EFAULT} nel suo significato generico.}
+\end{funcproto}
+
+La funzione restituisce nell'argomento \param{tp} come una struttura
+\struct{timespec}, (la cui definizione si può trovare in
+fig.~\ref{fig:sys_timeval_struct}) il valore dell'intervallo di tempo usato
+per la politica \textit{round robin} dal processo indicato da \ids{PID}. Il
+valore dipende dalla versione del kernel, a lungo infatti questo intervallo di
+tempo era prefissato e non modificabile ad un valore di 150 millisecondi,
+restituito indipendentemente dal \ids{PID} indicato.
+
+Con kernel recenti però è possibile ottenere una variazione della
+\textit{time-slice}, modificando il valore di \textit{nice} del processo
+(anche se questo non incide assolutamente sulla priorità statica) che come
+accennato in precedenza modifica il valore assegnato alla \textit{time-slice}
+di un processo ordinario, che però viene usato anche dai processi
+\textit{real-time}.
+
+Come accennato ogni processo può rilasciare volontariamente la CPU in modo da
+consentire agli altri processi di essere eseguiti; la funzione di sistema che
+consente di fare tutto questo è \funcd{sched\_yield}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sched.h}
+\fdecl{int sched\_yield(void)}
+\fdesc{Rilascia volontariamente l'esecuzione.}
+}
+{La funzione ritorna $0$ in caso di successo e teoricamente $-1$ per un
+ errore, ma su Linux ha sempre successo.}
+\end{funcproto}
+
+
+Questa funzione ha un utilizzo effettivo soltanto quando si usa lo
+\textit{scheduling} \textit{real-time}, e serve a far sì che il processo
+corrente rilasci la CPU, in modo da essere rimesso in coda alla lista dei
+processi con la stessa priorità per permettere ad un altro di essere eseguito;
+se però il processo è l'unico ad essere presente sulla coda l'esecuzione non
+sarà interrotta. In genere usano questa funzione i processi con politica
+\const{SCHED\_FIFO}, per permettere l'esecuzione degli altri processi con pari
+priorità quando la sezione più urgente è finita.
+
+La funzione può essere utilizzata anche con processi che usano lo
+\textit{scheduling} ordinario, ma in questo caso il comportamento non è ben
+definito, e dipende dall'implementazione. Fino al kernel 2.6.23 questo
+comportava che i processi venissero messi in fondo alla coda di quelli attivi,
+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
+ ripristinare un comportamento analogo al precedente scrivendo il valore 1
+ nel file \sysctlfile{kernel/sched\_compat\_yield}.}
+
+L'uso delle funzione nella programmazione ordinaria può essere utile e
+migliorare le prestazioni generali del sistema quando si è appena rilasciata
+una risorsa contesa con altri processi, e si vuole dare agli altri una
+possibilità di approfittarne mettendoli in esecuzione, ma chiamarla senza
+necessità, specie se questo avviene ripetutamente all'interno di un qualche
+ciclo, può avere invece un forte impatto negativo per la generazione di
+\itindex{contest~switch} \textit{contest switch} inutili.
+
+
+\subsection{Il controllo dello \textit{scheduler} per i sistemi
+ multiprocessore}
+\label{sec:proc_sched_multiprocess}
+
+Con il supporto dei sistemi multiprocessore sono state introdotte delle
+funzioni che permettono di controllare in maniera più dettagliata la scelta di
+quale processore utilizzare per eseguire un certo programma. Uno dei problemi
+che si pongono nei sistemi multiprocessore è infatti quello del cosiddetto
+\index{effetto~ping-pong} \textsl{effetto ping-pong}. Può accadere cioè che lo
+\textit{scheduler}, quando riavvia un processo precedentemente interrotto
+scegliendo il primo processore disponibile, lo faccia eseguire da un
+processore diverso rispetto a quello su cui era stato eseguito in
+precedenza. Se il processo passa da un processore all'altro in questo modo,
+cosa che avveniva abbastanza di frequente con i kernel della seria 2.4.x, si
+ha l'\textsl{effetto ping-pong}.
+
+Questo tipo di comportamento può generare dei seri problemi di prestazioni;
+infatti tutti i processori moderni utilizzano una memoria interna (la
+\textit{cache}) contenente i dati più usati, che permette di evitare di
+eseguire un accesso (molto più lento) alla memoria principale sulla scheda
+madre. Chiaramente un processo sarà favorito se i suoi dati sono nella cache
+del processore, ma è ovvio che questo può essere vero solo per un processore
+alla volta, perché in presenza di più copie degli stessi dati su più
+processori, non si potrebbe determinare quale di questi ha la versione dei
+dati aggiornata rispetto alla memoria principale.
+
+Questo comporta che quando un processore inserisce un dato nella sua cache,
+tutti gli altri processori che hanno lo stesso dato devono invalidarlo, e
+questa operazione è molto costosa in termini di prestazioni. Il problema
+diventa serio quando si verifica l'\textsl{effetto ping-pong}, in tal caso
+infatti un processo \textsl{rimbalza} continuamente da un processore all'altro
+e si ha una continua invalidazione della cache, che non diventa mai
+disponibile.
+
+\itindbeg{CPU~affinity}
+
+Per ovviare a questo tipo di problemi è nato il concetto di \textsl{affinità
+ di processore} (o \textit{CPU affinity}); la possibilità cioè di far sì che
+un processo possa essere assegnato per l'esecuzione sempre allo stesso
+processore. Lo \textit{scheduler} dei kernel della serie 2.4.x aveva una
+scarsa \textit{CPU affinity}, e \index{effetto~ping-pong} l'effetto ping-pong
+era comune; con il nuovo \textit{scheduler} dei kernel della 2.6.x questo
+problema è stato risolto ed esso cerca di mantenere il più possibile ciascun
+processo sullo stesso processore.
+
+In certi casi però resta l'esigenza di poter essere sicuri che un processo sia
+sempre eseguito dallo stesso processore,\footnote{quella che viene detta
+ \textit{hard CPU affinity}, in contrasto con quella fornita dallo
+ \textit{scheduler}, detta \textit{soft CPU affinity}, che di norma indica
+ solo una preferenza, non un requisito assoluto.} e per poter risolvere
+questo tipo di problematiche nei nuovi kernel\footnote{le due \textit{system
+ call} per la gestione della \textit{CPU affinity} sono state introdotte
+ nel kernel 2.5.8, e le corrispondenti funzioni di sistema nella
+ \textsl{glibc} 2.3.} è stata introdotta l'opportuna infrastruttura ed una
+nuova \textit{system call} che permette di impostare su quali processori far
+eseguire un determinato processo attraverso una \textsl{maschera di
+ affinità}. La corrispondente funzione di sistema è
+\funcd{sched\_setaffinity} ed il suo prototipo è:
+
+\index{insieme~di~processori|(}
+
+\begin{funcproto}{
+\fhead{sched.h}
+\fdecl{int sched\_setaffinity(pid\_t pid, size\_t setsize,
+ cpu\_set\_t *mask)}
+\fdesc{Imposta la maschera di affinità di un processo.}
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+caso \var{errno} assumerà uno dei valori:
+\begin{errlist}
+\item[\errcode{EINVAL}] il valore di \param{mask} contiene riferimenti a
+ processori non esistenti nel sistema o a cui non è consentito l'accesso.
+\item[\errcode{EPERM}] il processo non ha i privilegi sufficienti per
+ eseguire l'operazione.
+\item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+\end{errlist}
+ed inoltre anche \errval{EFAULT} nel suo significato generico.}
+\end{funcproto}
+
+Questa funzione e la corrispondente \func{sched\_getaffinity} hanno una storia
+abbastanza complessa, la sottostante \textit{system call} infatti prevede
+l'uso di due soli argomenti (per il pid e l'indicazione della maschera dei
+processori), che corrispondono al fatto che l'implementazione effettiva usa
+una semplice maschera binaria. Quando le funzioni vennero incluse nella
+\acr{glibc} assunsero invece un prototipo simile a quello mostrato però con il
+secondo argomento di tipo \ctyp{unsigned int}. A complicare la cosa si
+aggiunge il fatto che nella versione 2.3.3 della \acr{glibc} detto argomento
+venne stato eliminato, per poi essere ripristinato nella versione 2.3.4 nella
+forma attuale.\footnote{pertanto se la vostra pagina di manuale non è
+ aggiornata, o usate quella particolare versione della \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 \headfile{sched.h}.}
+
+La funzione imposta, con l'uso del valore contenuto all'indirizzo
+\param{mask}, l'insieme dei processori sui quali deve essere eseguito il
+processo identificato tramite il valore passato in \param{pid}. Come in
+precedenza il valore nullo di \param{pid} indica il processo corrente. Per
+poter utilizzare questa funzione sono richiesti i privilegi di amministratore
+(è necessaria la capacità \const{CAP\_SYS\_NICE}) altrimenti essa fallirà con
+un errore di \errcode{EPERM}. Una volta impostata una maschera di affinità,
+questa viene ereditata attraverso una \func{fork}, in questo modo diventa
+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
+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
+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
+(\textit{Non-Uniform Memory Access}).
+
+Infine se un gruppo di processi accede alle stesse risorse condivise (ad
+esempio una applicazione con più \itindex{thread} \textit{thread}) può avere
+senso usare lo stesso processore in modo da sfruttare meglio l'uso della sua
+cache; questo ovviamente riduce i benefici di un sistema multiprocessore
+nell'esecuzione contemporanea dei \itindex{thread} \textit{thread}, ma in
+certi casi (quando i \itindex{thread} \textit{thread} sono inerentemente
+serializzati nell'accesso ad una risorsa) possono esserci sufficienti vantaggi
+nell'evitare la perdita della cache da rendere conveniente l'uso dell'affinità
+di processore.
+
+Dato che il numero di processori può variare a seconda delle architetture, per
+semplificare l'uso dell'argomento \param{mask} la \acr{glibc} ha introdotto un
+apposito dato di tipo, \type{cpu\_set\_t},\footnote{questa è una estensione
+ specifica della \acr{glibc}, da attivare definendo la macro
+ \macro{\_GNU\_SOURCE}, non esiste infatti una standardizzazione per questo
+ tipo di interfaccia e POSIX al momento non prevede nulla al riguardo.} che
+permette di identificare un insieme di processori. Il dato è normalmente una
+maschera binaria: nei casi più comuni potrebbe bastare un intero a 32 bit, in
+cui ogni bit corrisponde ad un processore, ma oggi esistono architetture in
+cui questo numero può non essere sufficiente, e per questo è stato creato
+questo \index{tipo!opaco} 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 \code{sizeof(cpu\_set\_t)}.
+
+L'interfaccia di gestione degli insiemi di processori, oltre alla definizione
+del tipo \type{cpu\_set\_t}, prevede una serie di macro di preprocessore per
+la manipolazione degli stessi. Quelle di base, che consentono rispettivamente
+di svuotare un insieme, di aggiungere o togliere un processore o di verificare
+se esso è già presente in un insieme, sono le seguenti:
+
+{\centering
+\vspace{3pt}
+\begin{funcbox}{
+\fhead{sched.h}
+\fdecl{void \macro{CPU\_ZERO}(cpu\_set\_t *set)}
+\fdesc{Inizializza un insieme di processori vuoto \param{set}.}
+\fdecl{void \macro{CPU\_SET}(int cpu, cpu\_set\_t *set)}
+\fdesc{Inserisce il processore \param{cpu} nell'insieme di processori \param{set}.}
+\fdecl{void \macro{CPU\_CLR}(int cpu, cpu\_set\_t *set)}
+\fdesc{Rimuove il processore \param{cpu} nell'insieme di processori \param{set}.}
+\fdecl{int \macro{CPU\_ISSET}(int cpu, cpu\_set\_t *set)}
+\fdesc{Controlla se il processore \param{cpu} è nell'insieme di processori \param{set}.}
+}
+\end{funcbox}}
+
+Queste macro che sono ispirate dalle analoghe usate per gli insiemi di
+\textit{file descriptor} (vedi sez.~\ref{sec:file_select}) e sono state
+introdotte con la versione 2.3.3 della \acr{glibc}. Tutte richiedono che si
+specifichi il numero di una CPU nell'argomento \param{cpu}, ed un insieme su
+cui operare. L'unica che ritorna un risultato è \macro{CPU\_ISSET}, che
+restituisce un intero da usare come valore logico (zero se la CPU non è
+presente, diverso da zero se è presente).
+
+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
+\itindex{side~effects} \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
+ caso indicato in cui si passa una funzione ad una macro che usa l'argomento
+ al suo interno più volte, o si scrivono espressioni come \code{a=a++} in cui
+ non è chiaro se prima avvenga l'incremento e poi l'assegnazione, ed il cui
+ risultato dipende dall'implementazione del compilatore.}
+
+Le CPU sono numerate da zero (che indica la prima disponibile) fino ad
+un numero massimo che dipende dalla architettura hardware. La costante
+\const{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:
+
+{\centering
+\vspace{3pt}
+\begin{funcbox}{
+\fhead{sched.h}
+\fdecl{int \macro{CPU\_COUNT}(cpu\_set\_t *set)}
+\fdesc{Conta il numero di processori presenti nell'insieme \param{set}.}
+}
+\end{funcbox}}
+
+A partire dalla versione 2.7 della \acr{glibc} sono state introdotte altre
+macro che consentono ulteriori manipolazioni, in particolare si possono
+compiere delle operazioni logiche sugli insiemi di processori con:
+
+{\centering
+\vspace{3pt}
+\begin{funcbox}{
+\fhead{sched.h}
+\fdecl{void \macro{CPU\_AND}(cpu\_set\_t *destset, cpu\_set\_t *srcset1, cpu\_set\_t *srcset2)}
+\fdesc{Esegue l'AND logico di due insiemi di processori.}
+\fdecl{void \macro{CPU\_OR}(cpu\_set\_t *destset, cpu\_set\_t *srcset1, cpu\_set\_t *srcset2)}
+\fdesc{Esegue l'OR logico di due insiemi di processori.}
+\fdecl{void \macro{CPU\_XOR}(cpu\_set\_t *destset, cpu\_set\_t *srcset1, cpu\_set\_t *srcset2)}
+\fdesc{Esegue lo XOR logico di due insiemi di processori.}
+\fdecl{int \macro{CPU\_EQUAL}(cpu\_set\_t *set1, cpu\_set\_t *set2)}
+\fdesc{Verifica se due insiemi di processori sono uguali.}
+}
+\end{funcbox}}
+
+Le prime tre macro richiedono due insiemi di partenza, \param{srcset1}
+e \param{srcset2} e forniscono in un terzo insieme \param{destset} (che può
+essere anche lo stesso di uno dei precedenti) il risultato della rispettiva
+operazione logica sui contenuti degli stessi. In sostanza con \macro{CPU\_AND}
+si otterrà come risultato l'insieme che contiene le CPU presenti in entrambi
+gli insiemi di partenza, con \macro{CPU\_OR} l'insieme che contiene le CPU
+presenti in uno qualunque dei due insiemi di partenza, e con \macro{CPU\_XOR}
+l'insieme che contiene le CPU presenti presenti in uno solo dei due insiemi di
+partenza. Infine \macro{CPU\_EQUAL} confronta due insiemi ed è l'unica che
+restituisce un intero, da usare come valore logico che indica se sono
+identici o meno.
+
+Inoltre, sempre a partire dalla versione 2.7 della \acr{glibc}, è stata
+introdotta la possibilità di una allocazione dinamica degli insiemi di
+processori, per poterli avere di dimensioni corrispondenti al numero di CPU
+effettivamente in gioco, senza dover fare riferimento necessariamente alla
+precedente dimensione preimpostata di 1024. Per questo motivo sono state
+definite tre ulteriori macro, che consentono rispettivamente di allocare,
+disallocare ed ottenere la dimensione in byte di un insieme di processori:
+
+{\centering
+\vspace{3pt}
+\begin{funcbox}{
+\fhead{sched.h}
+\fdecl{cpu\_set\_t * \macro{CPU\_ALLOC}(num\_cpus)}
+\fdesc{Alloca dinamicamente un insieme di processori di dimensione voluta.}
+\fdecl{void \macro{CPU\_FREE}(cpu\_set\_t *set)}
+\fdesc{Disalloca un insieme di processori allocato dinamicamente.}
+\fdecl{size\_t \macro{CPU\_ALLOC\_SIZE}(num\_cpus)}
+\fdesc{Ritorna la dimensione di un insieme di processori allocato dinamicamente.}
+}
+\end{funcbox}}
+
+La prima macro, \macro{CPU\_ALLOC}, restituisce il puntatore ad un insieme di
+processori in grado di contenere almeno \param{num\_cpus} che viene allocato
+dinamicamente. Ogni insieme così allocato dovrà essere disallocato con
+\macro{CPU\_FREE} passandogli un puntatore ottenuto da una precedente
+\macro{CPU\_ALLOC}. La terza macro, \macro{CPU\_ALLOC\_SIZE}, consente di
+ottenere la dimensione in byte di un insieme allocato dinamicamente che
+contenga \param{num\_cpus} processori.
+
+Dato che le dimensioni effettive possono essere diverse le macro di gestione e
+manipolazione che abbiamo trattato in precedenza non si applicano agli insiemi
+allocati dinamicamente, per i quali dovranno sono state definite altrettante
+macro equivalenti contraddistinte dal suffisso \texttt{\_S}, che effettuano le
+stesse operazioni, ma richiedono in più un argomento
+aggiuntivo \param{setsize} che deve essere assegnato al valore ottenuto con
+\macro{CPU\_ALLOC\_SIZE}. Questo stesso valore deve essere usato per l'omonimo
+argomento delle funzioni \func{sched\_setaffinity} o \func{sched\_getaffinity}
+quando si vuole usare per l'argomento che indica la maschera di affinità un
+insieme di processori allocato dinamicamente.
+
+\index{insieme~di~processori|)}
+
+A meno di non aver utilizzato \func{sched\_setaffinity}, in condizioni
+ordinarie la maschera di affinità di un processo è preimpostata dal sistema in
+modo che esso possa essere eseguito su qualunque processore. Se ne può
+comunque ottenere il valore corrente usando la funzione di sistema
+\funcd{sched\_getaffinity}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sched.h}
+\fdecl{int sched\_getaffinity (pid\_t pid, size\_t setsize,
+ cpu\_set\_t *mask)}
+\fdesc{Legge la maschera di affinità di un processo.}
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+caso \var{errno} assumerà uno dei valori:
+\begin{errlist}
+\item[\errcode{EINVAL}] \param{setsize} è più piccolo delle dimensioni
+ della maschera di affinità usata dal kernel.
+\item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+\end{errlist}
+ed inoltre anche \errval{EFAULT} nel suo significato generico.}
+\end{funcproto}
+
+La funzione restituirà all'indirizzo specificato da \param{mask} il valore
+della maschera di affinità del processo indicato dall'argomento \param{pid}
+(al solito un valore nullo indica il processo corrente) così da poterla
+riutilizzare per una successiva reimpostazione.
+
+È chiaro che queste funzioni per la gestione dell'affinità hanno significato
+soltanto su un sistema multiprocessore, esse possono comunque essere
+utilizzate anche in un sistema con un processore singolo, nel qual caso però
+non avranno alcun risultato effettivo.
+
+\itindend{scheduler}
+\itindend{CPU~affinity}
+
+
+\subsection{Le priorità per le operazioni di I/O}
+\label{sec:io_priority}
+
+A lungo l'unica priorità usata per i processi è stata quella relativa
+all'assegnazione dell'uso del processore. Ma il processore non è l'unica
+risorsa che i processi devono contendersi, un'altra, altrettanto importante
+per le prestazioni, è quella dell'accesso a disco. Per questo motivo nello
+sviluppo del kernel sono stati introdotti diversi \textit{I/O scheduler} in
+grado di distribuire in maniera opportuna questa risorsa ai vari processi.
+
+Fino al kernel 2.6.17 era possibile soltanto differenziare le politiche
+generali di gestione, scegliendo di usare un diverso \textit{I/O scheduler}. A
+partire da questa versione, con l'introduzione dello \textit{scheduler} CFQ
+(\textit{Completely Fair Queuing}) è divenuto possibile, qualora si usi questo
+\textit{scheduler}, impostare anche delle diverse priorità di accesso per i
+singoli processi.\footnote{al momento (kernel 2.6.31), le priorità di I/O sono
+ disponibili soltanto per questo \textit{scheduler}.}
+
+La scelta di uno \textit{scheduler} di I/O si può fare in maniera generica per
+tutto il sistema all'avvio del kernel con il parametro di avvio
+\texttt{elevator},\footnote{per la trattazione dei parametri di avvio del
+ kernel si rimanda al solito alla sez.~5.3 di \cite{AGL}.} cui assegnare il
+nome dello \textit{scheduler}, ma se ne può anche indicare uno specifico per
+l'accesso al singolo disco scrivendo nel file
+\texttt{/sys/block/\textit{<dev>}/queue/scheduler} (dove
+\texttt{\textit{<dev>}} è il nome del dispositivo associato al disco).
+
+Gli \textit{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 \textit{scheduler} CFQ.} che supporta le priorità. Per i dettagli
+sulle caratteristiche specifiche degli altri \textit{scheduler}, la cui
+discussione attiene a problematiche di ambito sistemistico, si consulti la
+documentazione nella directory \texttt{Documentation/block/} dei sorgenti del
+kernel.
+
+Una volta che si sia impostato lo \textit{scheduler} CFQ ci sono due
+specifiche \textit{system call}, specifiche di Linux, che consentono di
+leggere ed impostare le priorità di I/O.\footnote{se usate in corrispondenza
+ ad uno \textit{scheduler} diverso il loro utilizzo non avrà alcun effetto.}
+Dato che non esiste una interfaccia diretta nella \acr{glibc} per queste due
+funzioni\footnote{almeno al momento della scrittura di questa sezione, con la
+ versione 2.11 della \acr{glibc}.} occorrerà invocarle tramite la funzione
+\func{syscall} (come illustrato in sez.~\ref{sec:proc_syscall}). Le due
+\textit{system call} sono \funcd{ioprio\_get} ed \funcd{ioprio\_set}; i
+rispettivi prototipi sono: