file viene \textsl{mappata} direttamente nello spazio degli indirizzi del
programma. Tutte le operazioni di lettura e scrittura su variabili contenute
in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto
-del file attraverso il sistema della memoria virtuale \index{memoria~virtuale}
-che in maniera analoga a quanto avviene per le pagine che vengono salvate e
-rilette nella swap, si incaricherà di sincronizzare il contenuto di quel
-segmento di memoria con quello del file mappato su di esso. Per questo motivo
-si può parlare tanto di \textsl{file mappato in memoria}, quanto di
-\textsl{memoria mappata su file}.
+del file attraverso il sistema della memoria virtuale illustrato in
+sez.~\ref{sec:proc_mem_gen} che in maniera analoga a quanto avviene per le
+pagine che vengono salvate e rilette nella \textit{swap}, si incaricherà di
+sincronizzare il contenuto di quel segmento di memoria con quello del file
+mappato su di esso. Per questo motivo si può parlare tanto di \textsl{file
+ mappato in memoria}, quanto di \textsl{memoria mappata su file}.
L'uso del \textit{memory-mapping} comporta una notevole semplificazione delle
operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer
solo per le parti effettivamente usate, il tutto in maniera completamente
trasparente al processo; l'accesso alle pagine non ancora caricate avverrà
allo stesso modo con cui vengono caricate in memoria le pagine che sono state
-salvate sullo swap.
+salvate sullo \textit{swap}.
Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un file
vengono salvate automaticamente, così come le pagine dei programmi vengono
-scritte sulla swap; questo consente di accedere ai file su dimensioni il cui
-solo limite è quello dello spazio di indirizzi disponibile, e non della
+scritte sulla \textit{swap}; questo consente di accedere ai file su dimensioni
+il cui solo limite è quello dello spazio di indirizzi disponibile, e non della
memoria su cui possono esserne lette delle porzioni.
L'interfaccia POSIX implementata da Linux prevede varie funzioni di sistema
con gli indirizzi crescenti verso il basso.\\
\const{MAP\_HUGETLB} & Esegue la mappatura usando le cosiddette
``\textit{huge pages}'' (dal 2.6.32).\\
- \const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine
+ \const{MAP\_LOCKED} & Se impostato impedisce lo \textit{swapping} delle pagine
mappate (dal 2.5.37).\\
\const{MAP\_NONBLOCK} & Esegue un \textit{prefaulting} più limitato che
non causa I/O (dal 2.5.46).\\
\const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva
- delle pagine di swap ad uso del meccanismo del
+ delle pagine di \textit{swap} ad uso del meccanismo del
\textit{copy on write} \itindex{copy~on~write}
per mantenere le modifiche fatte alla regione
mappata, in questo caso dopo una scrittura, se
privata cui solo il processo chiamante ha
accesso. Le modifiche sono mantenute attraverso
il meccanismo del \textit{copy on write} e
- salvate su swap in caso di necessità. Non è
+ salvate su \textit{swap} in caso di necessità. Non è
specificato se i cambiamenti sul file originale
vengano riportati sulla regione
mappata. Incompatibile con \const{MAP\_SHARED}.\\
La funzione richiede che venga letto in anticipo il contenuto del file
\param{fd} a partire dalla posizione \param{offset} e per un ammontare di
-\param{count} byte, in modo da portarlo in cache. La funzione usa la
-\index{memoria~virtuale} memoria virtuale ed il meccanismo della
-\index{paginazione} paginazione per cui la lettura viene eseguita in blocchi
-corrispondenti alle dimensioni delle pagine di memoria, ed i valori di
-\param{offset} e \param{count} vengono arrotondati di conseguenza.
+\param{count} byte, in modo da portarlo in cache. La funzione usa la memoria
+virtuale ed il meccanismo della paginazione per cui la lettura viene eseguita
+in blocchi corrispondenti alle dimensioni delle pagine di memoria, ed i valori
+di \param{offset} e \param{count} vengono arrotondati di conseguenza.
La funzione estende quello che è un comportamento normale del kernel che
quando si legge un file, aspettandosi che l'accesso prosegua, esegue sempre
\label{fig:intro_sys_struct}
\end{figure}
-Una parte del kernel, lo \itindex{scheduler} \textit{scheduler}, si occupa di
-stabilire, sulla base di un opportuno calcolo delle priorità e con una
-suddivisione appropriata del tempo di processore, quali fra i vari
-``\textsl{processi}'' presenti nel sistema deve essere eseguito, realizzando
-il cosiddetto \itindex{preemptive~multitasking} \textit{preemptive
+\itindbeg{scheduler}
+
+Una parte del kernel, lo \textit{scheduler}, si occupa di stabilire, sulla
+base di un opportuno calcolo delle priorità e con una suddivisione appropriata
+del tempo di processore, quali fra i vari ``\textsl{processi}'' presenti nel
+sistema deve essere eseguito, realizzando il cosiddetto
+\itindex{preemptive~multitasking} \textit{preemptive
multitasking}.\footnote{si chiama così quella gestione del
\textit{multitasking} in cui è il kernel a decidere a chi assegnare l'uso
della CPU, potendo interrompere l'esecuzione di un processo in qualunque
sez.~\ref{sec:intro_syscall}) che restituiranno il controllo al kernel per
eseguire le operazioni necessarie.
+\itindend{scheduler}
+
La memoria viene sempre gestita dal kernel attraverso il meccanismo della
\index{memoria~virtuale} \textsl{memoria virtuale}, che consente di assegnare
a ciascun processo uno spazio di indirizzi ``\textsl{virtuale}'' (vedi
la cui corrispondenza ad un nome espresso in caratteri è inserita nei due file
\conffile{/etc/passwd} e \conffile{/etc/group}.\footnote{in realtà negli
sistemi più moderni, come vedremo in sez.~\ref{sec:sys_user_group} queste
- informazioni possono essere mantenute, con l'uso del
- \itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch}, su varie
- tipologie di supporti, compresi server centralizzati come LDAP.} Questi
-identificativi sono l'\textit{user identifier}, detto in breve
-\textsl{user-ID}, ed indicato dall'acronimo \ids{UID}, e il \textit{group
- identifier}, detto in breve \textsl{group-ID}, ed identificato dall'acronimo
-\ids{GID}, torneremo in dettaglio su questo argomento in
+ informazioni possono essere mantenute, con l'uso del \textit{Name Service
+ Switch}, su varie tipologie di supporti, compresi server centralizzati
+ come LDAP.} Questi identificativi sono l'\textit{user identifier}, detto in
+breve \textsl{user-ID}, ed indicato dall'acronimo \ids{UID}, e il
+\textit{group identifier}, detto in breve \textsl{group-ID}, ed identificato
+dall'acronimo \ids{GID}, torneremo in dettaglio su questo argomento in
sez.~\ref{sec:proc_perms}. Il kernel conosce ed utilizza soltanto questi
valori numerici, i nomi ad essi associati sono interamente gestiti in
\textit{user space} con opportune funzioni di libreria, torneremo su questo
\end{figure}
Questa interfaccia resta la stessa anche quando, invece che a dei normali
-file, si accede alle periferiche coi citati \index{file!di~dispositivo} file
-di dispositivo, solo che in questo caso invece di usare il codice del
-filesystem che accede al disco, il \textit{Virtual File System} eseguirà
-direttamente il codice del kernel che permette di accedere alla periferica.
+file, si accede alle periferiche coi citati file di dispositivo, solo che in
+questo caso invece di usare il codice del filesystem che accede al disco, il
+\textit{Virtual File System} eseguirà direttamente il codice del kernel che
+permette di accedere alla periferica.
\itindend{Virtual~File~System}
Tutti gli ulteriori filesystem che possono essere disponibili su altri
dispositivi dovranno a loro volta essere inseriti nell'albero, montandoli su
altrettante directory del filesystem radice, su quelli che vengono chiamati
-\index{mount~point} \textit{mount point}. Questo comunque avverrà sempre in
-un secondo tempo, in genere a cura dei programmi eseguiti nella procedura di
-inizializzazione del sistema, grazie alle funzioni che tratteremo in
+\textit{mount point}. Questo comunque avverrà sempre in un secondo tempo, in
+genere a cura dei programmi eseguiti nella procedura di inizializzazione del
+sistema, grazie alle funzioni che tratteremo in
sez.~\ref{sec:filesystem_mounting}.
tutti gli altri oggetti previsti l'interfaccia del
\itindex{Virtual~File~System} VFS (su cui torneremo in
sez.~\ref{sec:file_file_types}), come le fifo, i collegamenti simbolici, i
-socket e gli stessi \index{file!di~dispositivo} file di dispositivo.
+socket e gli stessi file di dispositivo.
La convenzione usata nei sistemi unix-like per indicare i \textit{pathname}
dei file è quella di usare il carattere ``\texttt{/}'' come separatore fra i
\multicolumn{2}{|c|}{\textbf{Tipo di file}} & \textbf{Descrizione} \\
\hline
\hline
- \textit{regular file} & \textsl{file regolare} &
- Un file che contiene dei dati (l'accezione normale di file).\\
- \textit{directory} & \textsl{cartella o direttorio} &
- Un file che contiene una lista di nomi associati a degli
- \itindex{inode} \textit{inode} (vedi sez.~\ref{sec:file_vfs_work}).\\
- \textit{symbolic link} & \textsl{collegamento simbolico} &
- Un file che contiene un riferimento ad un altro file/directory.\\
- \textit{char device} & \textsl{dispositivo a caratteri} &
- Un file \textsl{speciale} che identifica una periferica ad accesso a
- caratteri.\\
- \textit{block device} & \textsl{dispositivo a blocchi} &
- Un file \textsl{speciale} che identifica una periferica ad accesso a
- blocchi.\\
- \textit{fifo} & ``\textsl{coda}'' &
- Un file \textsl{speciale} che identifica una linea di comunicazione
- unidirezionale (vedi sez.~\ref{sec:ipc_named_pipe}).\\
- \textit{socket} & ``\textsl{presa}''&
- Un file \textsl{speciale} che identifica una linea di comunicazione
- bidirezionale (vedi cap.~\ref{cha:socket_intro}).\\
+ \textit{regular file} & \textsl{file regolare} & Un file che contiene dei dati (l'accezione
+ normale di file).\\
+ \textit{directory} & \textsl{cartella o direttorio} & Un file che contiene una lista
+ di nomi associati a degli
+ \textit{inode} (vedi
+ sez.~\ref{sec:file_vfs_work}).\\
+ \textit{symbolic link} & \textsl{collegamento simbolico} & Un file che contiene un
+ riferimento ad un altro
+ file/directory.\\
+ \textit{char device} & \textsl{dispositivo a caratteri} & Un file \textsl{speciale}
+ che identifica una periferica
+ ad accesso a caratteri.\\
+ \textit{block device} & \textsl{dispositivo a blocchi} & Un file \textsl{speciale}
+ che identifica una periferica
+ ad accesso a blocchi.\\
+ \textit{fifo} & ``\textsl{coda}'' & Un file \textsl{speciale} che
+ identifica una linea di comunicazione
+ unidirezionale (vedi sez.~\ref{sec:ipc_named_pipe}).\\
+ \textit{socket} & ``\textsl{presa}''& Un file \textsl{speciale} che identifica una linea di
+ comunicazione bidirezionale (vedi
+ cap.~\ref{cha:socket_intro}).\\
\hline
\end{tabular}
\caption{Tipologia dei file definiti nel VFS}
Nelle versioni più recenti del kernel e delle librerie sono inoltre supportate
ulteriori funzionalità aggiunte dallo standard POSIX.1c per quanto riguarda i
-\itindex{thread} \textit{thread} (vedi cap.~\ref{cha:threads}), e dallo
-standard POSIX.1b per quanto riguarda i segnali e lo \itindex{scheduler}
-scheduling real-time (sez.~\ref{sec:sig_real_time} e
-sez.~\ref{sec:proc_real_time}), la misura del tempo, i meccanismi di
-intercomunicazione (sez.~\ref{sec:ipc_posix}) e l'I/O asincrono
-(sez.~\ref{sec:file_asyncronous_io}).
+\textit{thread} (vedi cap.~\ref{cha:threads}), e dallo standard POSIX.1b per
+quanto riguarda i segnali e lo scheduling real-time
+(sez.~\ref{sec:sig_real_time} e sez.~\ref{sec:proc_real_time}), la misura del
+tempo, i meccanismi di intercomunicazione (sez.~\ref{sec:ipc_posix}) e l'I/O
+asincrono (sez.~\ref{sec:file_asyncronous_io}).
Lo standard principale resta comunque POSIX.1, che continua ad evolversi; la
versione più nota, cui gran parte delle implementazioni fanno riferimento, e
operazioni richieste (nel campo \var{sops}, che è un puntatore ad una
struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper})
poi quest'ultimo viene messo stato di attesa e viene invocato lo
-\itindex{scheduler} \textit{scheduler} per passare all'esecuzione di un altro
-processo.
+\textit{scheduler} per passare all'esecuzione di un altro processo.
Se invece tutte le operazioni possono avere successo queste vengono eseguite
immediatamente, dopo di che il kernel esegue una scansione della coda di
\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
\item[\const{SHM\_LOCK}] Abilita il \itindex{memory~locking} \textit{memory
locking} sul segmento di memoria condivisa, impedendo che la memoria usata
- per il segmento venga salvata su disco dal meccanismo della
- \index{memoria~virtuale} memoria virtuale. Come illustrato in
- sez.~\ref{sec:proc_mem_lock} fino al kernel 2.6.9 solo l'amministratore
- poteva utilizzare questa capacità,\footnote{che richiedeva la
- \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal dal kernel
- 2.6.10 anche gli utenti normali possono farlo fino al limite massimo
- determinato da \const{RLIMIT\_MEMLOCK} (vedi
+ per il segmento venga salvata su disco dal meccanismo della memoria
+ virtuale. Come illustrato in sez.~\ref{sec:proc_mem_lock} fino al kernel
+ 2.6.9 solo l'amministratore poteva utilizzare questa capacità,\footnote{che
+ richiedeva la \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal
+ dal kernel 2.6.10 anche gli utenti normali possono farlo fino al limite
+ massimo determinato da \const{RLIMIT\_MEMLOCK} (vedi
sez.~\ref{sec:sys_resource_limit}).
\item[\const{SHM\_UNLOCK}] Disabilita il \itindex{memory~locking}
\textit{memory locking} sul segmento di memoria condivisa. Fino al kernel
in cui gli indirizzi vanno da zero ad un qualche valore massimo.\footnote{nel
caso di Linux fino al kernel 2.2 detto massimo era, per macchine a 32bit, di
2Gb. Con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite
- è stato esteso anche per macchine a 32 bit.}
-
-Come accennato nel cap.~\ref{cha:intro_unix} questo spazio di indirizzi è
-virtuale e non corrisponde all'effettiva posizione dei dati nella RAM del
-computer. In generale detto spazio non è neppure continuo, cioè non tutti gli
-indirizzi possibili sono utilizzabili, e quelli usabili non sono
-necessariamente adiacenti.
+ è stato esteso anche per macchine a 32 bit.} Come accennato nel
+cap.~\ref{cha:intro_unix} questo spazio di indirizzi è virtuale e non
+corrisponde all'effettiva posizione dei dati nella RAM del computer. In
+generale detto spazio non è neppure continuo, cioè non tutti gli indirizzi
+possibili sono utilizzabili, e quelli usabili non sono necessariamente
+adiacenti.
Per la gestione da parte del kernel la memoria viene divisa in pagine di
dimensione fissa. Inizialmente queste pagine erano di 4kb sulle macchine a 32
farà da supporto a tutte le pagine di memoria virtuale di tutti i processi che
hanno detta funzione nel loro codice.
+\index{paginazione|(}
+
La corrispondenza fra le pagine della memoria virtuale di un processo e quelle
della memoria fisica della macchina viene gestita in maniera trasparente dal
kernel.\footnote{in genere con l'ausilio dell'hardware di gestione della
fisica è solo una piccola frazione della memoria virtuale, è necessario un
meccanismo che permetta di trasferire le pagine che servono dal supporto su
cui si trovano in memoria, eliminando quelle che non servono. Questo
-meccanismo è detto \index{paginazione} \textsl{paginazione} (o
-\textit{paging}), ed è uno dei compiti principali del kernel.
+meccanismo è detto \textsl{paginazione} (o \textit{paging}), ed è uno dei
+compiti principali del kernel.
Quando un processo cerca di accedere ad una pagina che non è nella memoria
reale, avviene quello che viene chiamato un \itindex{page~fault} \textit{page
Normalmente questo è il prezzo da pagare per avere un multitasking reale, ed
in genere il sistema è molto efficiente in questo lavoro; quando però ci siano
esigenze specifiche di prestazioni è possibile usare delle funzioni che
-permettono di bloccare il meccanismo della \index{paginazione} paginazione e
-mantenere fisse delle pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}).
+permettono di bloccare il meccanismo della paginazione e mantenere fisse delle
+pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}).
+\index{paginazione|)}
\index{memoria~virtuale|)}
\subsection{La struttura della memoria di un processo}
dell'utilizzo corrente da parte dei vari processi.
Nell'uso comune un processo non deve preoccuparsi di tutto ciò, in quanto il
-meccanismo della \index{paginazione} paginazione riporta in RAM, ed in maniera
-trasparente, tutte le pagine che gli occorrono; esistono però esigenze
-particolari in cui non si vuole che questo meccanismo si attivi. In generale i
-motivi per cui si possono avere di queste necessità sono due:
+meccanismo della paginazione riporta in RAM, ed in maniera trasparente, tutte
+le pagine che gli occorrono; esistono però esigenze particolari in cui non si
+vuole che questo meccanismo si attivi. In generale i motivi per cui si possono
+avere di queste necessità sono due:
\begin{itemize*}
-\item \textsl{La velocità}. Il processo della \index{paginazione} paginazione
- è trasparente solo se il programma in esecuzione non è sensibile al tempo
- che occorre a riportare la pagina in memoria; per questo motivo processi
- critici che hanno esigenze di tempo reale o tolleranze critiche nelle
- risposte (ad esempio processi che trattano campionamenti sonori) possono non
- essere in grado di sopportare le variazioni della velocità di accesso dovuta
- alla paginazione.
+\item \textsl{La velocità}. Il processo della paginazione è trasparente solo
+ se il programma in esecuzione non è sensibile al tempo che occorre a
+ riportare la pagina in memoria; per questo motivo processi critici che hanno
+ esigenze di tempo reale o tolleranze critiche nelle risposte (ad esempio
+ processi che trattano campionamenti sonori) possono non essere in grado di
+ sopportare le variazioni della velocità di accesso dovuta alla paginazione.
In certi casi poi un programmatore può conoscere meglio dell'algoritmo di
allocazione delle pagine le esigenze specifiche del suo programma e decidere
\item \textsl{La sicurezza}. Se si hanno password o chiavi segrete in chiaro
in memoria queste possono essere portate su disco dal meccanismo della
- \index{paginazione} paginazione. Questo rende più lungo il periodo di tempo
- in cui detti segreti sono presenti in chiaro e più complessa la loro
- cancellazione: un processo infatti può cancellare la memoria su cui scrive
- le sue variabili, ma non può toccare lo spazio disco su cui una pagina di
- memoria può essere stata salvata. Per questo motivo di solito i programmi
- di crittografia richiedono il blocco di alcune pagine di memoria.
+ paginazione. Questo rende più lungo il periodo di tempo in cui detti segreti
+ sono presenti in chiaro e più complessa la loro cancellazione: un processo
+ infatti può cancellare la memoria su cui scrive le sue variabili, ma non può
+ toccare lo spazio disco su cui una pagina di memoria può essere stata
+ salvata. Per questo motivo di solito i programmi di crittografia richiedono
+ il blocco di alcune pagine di memoria.
\end{itemize*}
Per ottenere informazioni sulle modalità in cui un programma sta usando la
\itindbeg{memory~locking}
-Il meccanismo che previene la \index{paginazione} paginazione di parte della
-memoria virtuale di un processo è chiamato \textit{memory locking} (o
-\textsl{blocco della memoria}). Il blocco è sempre associato alle pagine della
-memoria virtuale del processo, e non al segmento reale di RAM su cui essa
-viene mantenuta. La regola è che se un segmento di RAM fa da supporto ad
-almeno una pagina bloccata allora esso viene escluso dal meccanismo della
-\index{paginazione} paginazione. I blocchi non si accumulano, se si blocca due
-volte la stessa pagina non è necessario sbloccarla due volte, una pagina o è
-bloccata oppure no.
+Il meccanismo che previene la paginazione di parte della memoria virtuale di
+un processo è chiamato \textit{memory locking} (o \textsl{blocco della
+ memoria}). Il blocco è sempre associato alle pagine della memoria virtuale
+del processo, e non al segmento reale di RAM su cui essa viene mantenuta. La
+regola è che se un segmento di RAM fa da supporto ad almeno una pagina
+bloccata allora esso viene escluso dal meccanismo della paginazione. I blocchi
+non si accumulano, se si blocca due volte la stessa pagina non è necessario
+sbloccarla due volte, una pagina o è bloccata oppure no.
Il \textit{memory lock} persiste fintanto che il processo che detiene la
memoria bloccata non la sblocca. Chiaramente la terminazione del processo
però diversi processi bloccano la stessa pagina questa resterà bloccata
fintanto che ci sarà almeno un processo che la blocca.
-Le funzioni di sistema per bloccare e sbloccare la \index{paginazione}
-paginazione di singole sezioni di memoria sono rispettivamente \funcd{mlock} e
-\funcd{munlock}; i loro prototipi sono:
+Le funzioni di sistema per bloccare e sbloccare la paginazione di singole
+sezioni di memoria sono rispettivamente \funcd{mlock} e \funcd{munlock}; i
+loro prototipi sono:
\begin{funcproto}{
\fhead{sys/mman.h}
% 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 in occasione di dell'invocazione di ogni \textit{system call} ed per
-ogni interrupt dall'hardware oltre che in una serie di altre occasioni, e può
-essere anche attivato esplicitamente. Il timer di sistema provvede comunque a
-che esso sia invocato periodicamente, generando un interrupt periodico secondo
-una frequenza predeterminata, specificata dalla costante \const{HZ} del kernel
-(torneremo su questo argomento in sez.~\ref{sec:sys_unix_time}), che assicura
-che lo \textit{scheduler} scheduler venga comunque eseguito ad intervalli
-regolari e possa prendere le sue decisioni.
+\itindbeg{scheduler}
+Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \textit{scheduler} che
+decide quale processo mettere in esecuzione; esso viene eseguito in occasione
+di dell'invocazione di ogni \textit{system call} ed per ogni interrupt
+dall'hardware oltre che in una serie di altre occasioni, e può essere anche
+attivato esplicitamente. Il timer di sistema provvede comunque a che esso sia
+invocato periodicamente, generando un interrupt periodico secondo una
+frequenza predeterminata, specificata dalla costante \const{HZ} del kernel
+(torneremo su questo argomento in sez.~\ref{sec:sys_unix_time}), che assicura
+che lo \textit{scheduler} venga comunque eseguito ad intervalli regolari e
+possa prendere le sue decisioni.
A partire dal kernel 2.6.21 è stato introdotto anche un meccanismo
completamente diverso, detto \textit{tickless}, in cui non c'è più una
sospensione anche per lunghi periodi di tempo.
Indipendentemente dalle motivazioni per cui questo avviene, 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 essere posto in
-esecuzione fino alla successiva invocazione.
+viene eseguito lo \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 essere posto in esecuzione fino alla successiva
+invocazione.
+\itindend{scheduler}
\subsection{Gli identificatori dei processi}
\label{sec:proc_pid}
e poi il padre.
In generale l'ordine di esecuzione dipenderà, oltre che dall'algoritmo di
-\itindex{scheduler} \textit{scheduling} usato dal kernel, dalla particolare
-situazione in cui si trova la macchina al momento della chiamata, risultando
-del tutto impredicibile. Eseguendo più volte il programma di prova e
-producendo un numero diverso di figli, si sono ottenute situazioni
-completamente diverse, compreso il caso in cui il processo padre ha eseguito
-più di una \func{fork} prima che uno dei figli venisse messo in esecuzione.
+\textit{scheduling} usato dal kernel, dalla particolare situazione in cui si
+trova la macchina al momento della chiamata, risultando del tutto
+impredicibile. Eseguendo più volte il programma di prova e producendo un
+numero diverso di figli, si sono ottenute situazioni completamente diverse,
+compreso il caso in cui il processo padre ha eseguito più di una \func{fork}
+prima che uno dei figli venisse messo in esecuzione.
Pertanto non si può fare nessuna assunzione sulla sequenza di esecuzione delle
istruzioni del codice fra padre e figli, né sull'ordine in cui questi potranno
rischio di incorrere nelle cosiddette \itindex{race~condition} \textit{race
condition} (vedi sez.~\ref{sec:proc_race_cond}).
-In realtà con l'introduzione dei kernel della serie 2.6 lo \itindex{scheduler}
-\textit{scheduler} è stato modificato per eseguire sempre per primo il
-figlio.\footnote{i risultati precedenti infatti sono stati ottenuti usando un
- kernel della serie 2.4.} Questa è una ottimizzazione adottata per evitare
-che il padre, effettuando per primo una operazione di scrittura in memoria,
-attivasse il meccanismo del \itindex{copy~on~write} \textit{copy on write},
-operazione inutile qualora il figlio venga creato solo per eseguire una
-\func{exec} su altro programma che scarta completamente lo spazio degli
-indirizzi e rende superflua la copia della memoria modificata dal
-padre. Eseguendo sempre per primo il figlio la \func{exec} verrebbe effettuata
-subito, con la certezza di utilizzare \itindex{copy~on~write} \textit{copy on
- write} solo quando necessario.
+In realtà con l'introduzione dei kernel della serie 2.6 lo \textit{scheduler}
+è stato modificato per eseguire sempre per primo il figlio.\footnote{i
+ risultati precedenti infatti sono stati ottenuti usando un kernel della
+ serie 2.4.} Questa è una ottimizzazione adottata per evitare che il padre,
+effettuando per primo una operazione di scrittura in memoria, attivasse il
+meccanismo del \itindex{copy~on~write} \textit{copy on write}, operazione
+inutile qualora il figlio venga creato solo per eseguire una \func{exec} su
+altro programma che scarta completamente lo spazio degli indirizzi e rende
+superflua la copia della memoria modificata dal padre. Eseguendo sempre per
+primo il figlio la \func{exec} verrebbe effettuata subito, con la certezza di
+utilizzare \itindex{copy~on~write} \textit{copy on write} solo quando
+necessario.
Con il kernel 2.6.32 però il comportamento è stato nuovamente cambiato,
stavolta facendo eseguire per primo sempre il padre. Si è realizzato infatti
\label{sec:proc_priority}
In questa sezione tratteremo più approfonditamente i meccanismi con il quale
-lo \itindex{scheduler} \textit{scheduler} assegna la CPU ai vari processi
-attivi. In particolare prenderemo in esame i vari meccanismi con cui viene
-gestita l'assegnazione del tempo di CPU, ed illustreremo le varie funzioni di
-gestione. Tratteremo infine anche le altre priorità dei processi (come quelle
-per l'accesso a disco) divenute disponibili con i kernel più recenti.
+lo \textit{scheduler} assegna la CPU ai vari processi attivi. In particolare
+prenderemo in esame i vari meccanismi con cui viene gestita l'assegnazione del
+tempo di CPU, ed illustreremo le varie funzioni di gestione. Tratteremo infine
+anche le altre priorità dei processi (come quelle per l'accesso a disco)
+divenute disponibili con i kernel più recenti.
\subsection{I meccanismi di \textit{scheduling}}
Il meccanismo usato da Linux è in realtà piuttosto complesso,\footnote{e
dipende strettamente dalla versione di kernel; in particolare a partire
- dalla serie 2.6.x lo scheduler è stato riscritto completamente, con molte
- modifiche susseguitesi per migliorarne le prestazioni, per un certo periodo
- ed è stata anche introdotta la possibilità di usare diversi algoritmi,
- selezionabili sia in fase di compilazione, che, nelle versioni più recenti,
- all'avvio (addirittura è stato ideato un sistema modulare che permette di
- cambiare lo scheduler a sistema attivo).} ma a grandi linee si può dire che
-ad ogni processo è assegnata una \textit{time-slice}, cioè un intervallo di
-tempo (letteralmente una fetta) per il quale, a meno di eventi esterni, esso
-viene eseguito senza essere interrotto. Inoltre la priorità dinamica viene
-calcolata dallo scheduler a partire da un valore iniziale che viene
-\textsl{diminuito} tutte le volte che un processo è in stato \textit{runnable}
-ma non viene posto in esecuzione.\footnote{in realtà il calcolo della priorità
- dinamica e la conseguente scelta di quale 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 scheduler si legga il quarto capitolo di
- \cite{LinKernDev}.} Lo 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
+ dalla serie 2.6.x lo \textit{scheduler} è stato riscritto completamente, con
+ molte modifiche susseguitesi per migliorarne le prestazioni, per un certo
+ periodo ed è stata anche introdotta la possibilità di usare diversi
+ algoritmi, selezionabili sia in fase di compilazione, che, nelle versioni
+ più recenti, all'avvio (addirittura è stato ideato un sistema modulare che
+ permette di cambiare lo \textit{scheduler} a sistema attivo).} ma a grandi
+linee si può dire che ad ogni processo è assegnata una \textit{time-slice},
+cioè un intervallo di tempo (letteralmente una fetta) per il quale, a meno di
+eventi esterni, esso viene eseguito senza essere interrotto. Inoltre la
+priorità dinamica viene calcolata dallo \textit{scheduler} a partire da un
+valore iniziale che viene \textsl{diminuito} tutte le volte che un processo è
+in stato \textit{runnable} ma non viene posto in esecuzione.\footnote{in
+ realtà il calcolo della priorità dinamica e la conseguente scelta di quale
+ 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.
Sia la dimensione della \textit{time-slice} che il valore di partenza della
che ciascun processo si porta dietro, essa viene ereditata dai processi
figli e mantenuta attraverso una \func{exec}; fino alla serie 2.4 essa era
mantenuta nell'omonimo campo \texttt{nice} della \texttt{task\_struct}, con
- la riscrittura dello scheduler eseguita nel 2.6 viene mantenuta nel campo
- \texttt{static\_prio} come per le priorità statiche.} L'origine del nome di
-questo parametro sta nel fatto che generalmente questo viene usato per
+ la riscrittura dello \textit{scheduler} eseguita nel 2.6 viene mantenuta nel
+ campo \texttt{static\_prio} come per le priorità statiche.} L'origine del
+nome di questo parametro sta nel fatto che generalmente questo viene usato per
\textsl{diminuire} la priorità di un processo, come misura di cortesia nei
confronti degli altri. I processi infatti vengono creati dal sistema con un
valore nullo e nessuno è privilegiato rispetto agli altri. Specificando un
La politica \const{SCHED\_BATCH} è una variante della politica ordinaria con
la sola differenza che i processi ad essa soggetti non ottengono, nel calcolo
-delle priorità dinamiche fatto dallo scheduler, il cosiddetto bonus di
-interattività che mira a favorire i processi che si svegliano dallo stato di
-\textit{sleep}.\footnote{cosa che accade con grande frequenza per i 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}.
+delle priorità dinamiche fatto dallo \textit{scheduler}, il cosiddetto bonus
+di interattività che mira a favorire i processi che si svegliano dallo stato
+di \textit{sleep}.\footnote{cosa che accade con grande frequenza per i
+ 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}.
La politica \const{SCHED\_IDLE} invece è una politica dedicata ai processi che
si desidera siano eseguiti con la più bassa priorità possibile, ancora più
processore.
Nell'uso comune, almeno con i kernel successivi alla serie 2.6.x, l'uso di
-questa funzione non è necessario, in quanto è lo 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
+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
utilizzate anche in un sistema con un processore singolo, nel qual caso però
non avranno alcun risultato effettivo.
-
\itindend{scheduler}
\itindend{CPU~affinity}
\textit{delivered}) quando viene eseguita l'azione per esso prevista, mentre
per tutto il tempo che passa fra la generazione del segnale e la sua consegna
esso è detto \textsl{pendente} (o \textit{pending}). In genere questa
-procedura viene effettuata dallo \itindex{scheduler} scheduler quando,
-riprendendo l'esecuzione del processo in questione, verifica la presenza del
-segnale nella \struct{task\_struct} e mette in esecuzione il gestore.
+procedura viene effettuata dallo \textit{scheduler} quando, riprendendo
+l'esecuzione del processo in questione, verifica la presenza del segnale nella
+\struct{task\_struct} e mette in esecuzione il gestore.
In questa semantica un processo ha la possibilità di bloccare la consegna dei
segnali, in questo caso, se l'azione per il suddetto segnale non è quella di
ignorarlo.
Normalmente l'invio al processo che deve ricevere il segnale è immediato ed
-avviene non appena questo viene rimesso in esecuzione dallo
-\itindex{scheduler} scheduler che esegue l'azione specificata. Questo a meno
-che il segnale in questione non sia stato bloccato prima della notifica, nel
-qual caso l'invio non avviene ed il segnale resta \textsl{pendente}
-indefinitamente.
+avviene non appena questo viene rimesso in esecuzione dallo \textit{scheduler}
+che esegue l'azione specificata. Questo a meno che il segnale in questione non
+sia stato bloccato prima della notifica, nel qual caso l'invio non avviene ed
+il segnale resta \textsl{pendente} indefinitamente.
Quando lo si sblocca un segnale \textsl{pendente} sarà subito notificato. Si
tenga presente però che tradizionalmente i segnali \textsl{pendenti} non si
arrotondato al multiplo successivo di 1/\const{HZ}.
Con i kernel della serie 2.4 in realtà era possibile ottenere anche pause più
-precise del centesimo di secondo usando politiche di \itindex{scheduler}
-scheduling \textit{real-time} come \const{SCHED\_FIFO} o \const{SCHED\_RR}; in
-tal caso infatti il calcolo sul numero di interruzioni del timer veniva
-evitato utilizzando direttamente un ciclo di attesa con cui si raggiungevano
-pause fino ai 2~ms con precisioni del $\mu$s. Questa estensione è stata
-rimossa con i kernel della serie 2.6, che consentono una risoluzione più alta
-del timer di sistema; inoltre a partire dal kernel 2.6.21, \func{nanosleep}
-può avvalersi del supporto dei timer ad alta risoluzione, ottenendo la massima
-precisione disponibile sull'hardware della propria macchina.
+precise del centesimo di secondo usando politiche di \textit{scheduling}
+\textit{real-time} come \const{SCHED\_FIFO} o \const{SCHED\_RR} (vedi
+sez.~\ref{sec:proc_real_time}); in tal caso infatti il calcolo sul numero di
+interruzioni del timer veniva evitato utilizzando direttamente un ciclo di
+attesa con cui si raggiungevano pause fino ai 2~ms con precisioni del
+$\mu$s. Questa estensione è stata rimossa con i kernel della serie 2.6, che
+consentono una risoluzione più alta del timer di sistema; inoltre a partire
+dal kernel 2.6.21, \func{nanosleep} può avvalersi del supporto dei timer ad
+alta risoluzione, ottenendo la massima precisione disponibile sull'hardware
+della propria macchina.
\subsection{Un esempio elementare}
servizi di risoluzione dei nomi illustrati in sez.~\ref{sec:sock_resolver}; in
generale infatti ci sono una serie di funzioni nella forma
\texttt{getXXXbyname} e \texttt{getXXXbyaddr} (dove \texttt{XXX} indica il
-servizio) per ciascuna delle informazioni di rete mantenute dal
-\itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch} che permettono
-rispettivamente di trovare una corrispondenza cercando per nome o per numero.
+servizio) per ciascuna delle informazioni di rete mantenute dal \textit{Name
+ Service Switch} che permettono rispettivamente di trovare una corrispondenza
+cercando per nome o per numero.
L'elenco di queste funzioni è riportato nelle colonne finali di
tab.~\ref{tab:name_resolution_functions}, dove le si sono suddivise rispetto
al tipo di informazione che forniscono (riportato in prima colonna). Nella
tabella si è anche riportato il file su cui vengono ordinariamente mantenute
queste informazioni, che però può essere sostituito da un qualunque supporto
-interno al \itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch}
-(anche se usualmente questo avviene solo per la risoluzione degli indirizzi).
-Ciascuna funzione fa riferimento ad una sua apposita struttura che contiene i
-relativi dati, riportata in terza colonna.
+interno al \textit{Name Service Switch} (anche se usualmente questo avviene
+solo per la risoluzione degli indirizzi). Ciascuna funzione fa riferimento ad
+una sua apposita struttura che contiene i relativi dati, riportata in terza
+colonna.
\begin{table}[!htb]
\centering
\hline
\end{tabular}
\caption{Funzioni di risoluzione dei nomi per i vari servizi del
- \itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch}.}
+ \textit{Name Service Switch} riguardanti la rete.}
\label{tab:name_resolution_functions}
\end{table}
Delle funzioni di tab.~\ref{tab:name_resolution_functions} abbiamo trattato
finora soltanto quelle relative alla risoluzione dei nomi, dato che sono le
più usate, e prevedono praticamente da sempre la necessità di rivolgersi ad
-una entità esterna; per le altre invece, estensioni fornite dal
-\itindex{Name~Service~Switch~(NSS)} NSS a parte, si fa sempre riferimento ai
-dati mantenuti nei rispettivi file.
+una entità esterna; per le altre invece, estensioni fornite dal \textit{Name
+ Service Switch} a parte, si fa sempre riferimento ai dati mantenuti nei
+rispettivi file.
Dopo la risoluzione dei nomi a dominio una delle ricerche più comuni è quella
sui nomi dei servizi di rete più comuni (cioè \texttt{http}, \texttt{smtp},
Il primo argomento è il nome del servizio per \func{getservbyname},
specificato tramite la stringa \param{name}, mentre \func{getservbyport}
richiede il numero di porta in \param{port}. Entrambe le funzioni eseguono una
-ricerca sul file \conffile{/etc/services}\footnote{il
- \itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch} astrae il
- concetto a qualunque supporto su cui si possano mantenere i suddetti dati.}
-ed estraggono i dati dalla prima riga che corrisponde agli argomenti
-specificati; se la risoluzione ha successo viene restituito un puntatore ad
-una apposita struttura \struct{servent} contenente tutti i risultati,
-altrimenti viene restituito un puntatore nullo. Si tenga presente che anche
-in questo caso i dati vengono mantenuti in una area di memoria statica e che
-quindi la funzione non è \index{funzioni!rientranti} rientrante.
+ricerca sul file \conffile{/etc/services}\footnote{il \textit{Name Service
+ Switch} astrae il concetto a qualunque supporto su cui si possano
+ mantenere i suddetti dati.} ed estraggono i dati dalla prima riga che
+corrisponde agli argomenti specificati; se la risoluzione ha successo viene
+restituito un puntatore ad una apposita struttura \struct{servent} contenente
+tutti i risultati, altrimenti viene restituito un puntatore nullo. Si tenga
+presente che anche in questo caso i dati vengono mantenuti in una area di
+memoria statica e che quindi la funzione non è \index{funzioni!rientranti}
+rientrante.
\begin{figure}[!htb]
\footnotesize \centering
trovati nelle rispettive pagine di manuale.
Oltre alle funzioni di ricerca esistono delle ulteriori funzioni che prevedono
-una lettura sequenziale delle informazioni mantenute nel
-\itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch} (in sostanza
-permettono di leggere i file contenenti le informazioni riga per riga), che
-sono analoghe a quelle elencate in tab.~\ref{tab:sys_passwd_func} per le
-informazioni relative ai dati degli utenti e dei gruppi. Nel caso specifico
-dei servizi avremo allora le tre funzioni \funcd{setservent},
-\funcd{getservent} e \funcd{endservent} i cui prototipi sono:
+una lettura sequenziale delle informazioni mantenute nel \textit{Name Service
+ Switch} (in sostanza permettono di leggere i file contenenti le informazioni
+riga per riga), che sono analoghe a quelle elencate in
+tab.~\ref{tab:sys_passwd_func} per le informazioni relative ai dati degli
+utenti e dei gruppi. Nel caso specifico dei servizi avremo allora le tre
+funzioni \funcd{setservent}, \funcd{getservent} e \funcd{endservent} i cui
+prototipi sono:
\begin{functions}
\headdecl{netdb.h}
\funcdecl{void setservent(int stayopen)}
\hline
\end{tabular}
\caption{Funzioni lettura sequenziale dei dati del
- \itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch}.}
+ \textit{Name Service Switch}.}
\label{tab:name_sequential_read}
\end{table}
nel file \texttt{Documentation/networking/ip-sysctl.txt}; la maggior parte di
questi però non è documentato:
\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
-\item[\sysctlrelfile{net/core}{dev\_weight}] blocco di lavoro
- (\textit{work quantum}) dello scheduler di processo dei pacchetti.
+\item[\sysctlrelfile{net/core}{dev\_weight}] blocco di lavoro (\textit{work
+ quantum}) dello \textit{scheduler} di processo dei pacchetti.
% TODO da documentare meglio
all'interno di una stessa organizzazione, in modo da mantenere coerenti i
dati, ha portato anche alla necessità di poter recuperare e memorizzare dette
informazioni su supporti diversi dai file citati, introducendo il sistema del
-\itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch} che
-tratteremo brevemente più avanti (in sez.~\ref{sec:sock_resolver}) dato che la
-sua applicazione è cruciale nella procedura di risoluzione di nomi di rete.
+\itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch} (che
+tratteremo brevemente in sez.~\ref{sec:sock_resolver}) dato che la sua
+applicazione è cruciale nella procedura di risoluzione di nomi di rete.
In questo paragrafo ci limiteremo comunque a trattare le funzioni classiche
per la lettura delle informazioni relative a utenti e gruppi tralasciando
Le funzioni viste finora sono in grado di leggere le informazioni sia
direttamente dal file delle password in \conffile{/etc/passwd} che tramite il
-sistema del \itindex{Name~Service~Switch~(NSS)} \textit{Name Service Switch} e
-sono completamente generiche. Si noti però che non c'è una funzione che
-permetta di impostare direttamente una password.\footnote{in realtà questo può
- essere fatto ricorrendo alle funzioni della libreria PAM, ma questo non è un
- argomento che tratteremo qui.} Dato che POSIX non prevede questa possibilità
-esiste un'altra interfaccia che lo fa, derivata da SVID le cui funzioni sono
-riportate in tab.~\ref{tab:sys_passwd_func}. Questa interfaccia però funziona
-soltanto quando le informazioni sono mantenute su un apposito file di
-\textsl{registro} di utenti e gruppi, con il formato classico di
-\conffile{/etc/passwd} e \conffile{/etc/group}.
+sistema del \textit{Name Service Switch} e sono completamente generiche. Si
+noti però che non c'è una funzione che permetta di impostare direttamente una
+password.\footnote{in realtà questo può essere fatto ricorrendo alle funzioni
+ della libreria PAM, ma questo non è un argomento che tratteremo qui.} Dato
+che POSIX non prevede questa possibilità esiste un'altra interfaccia che lo
+fa, derivata da SVID le cui funzioni sono riportate in
+tab.~\ref{tab:sys_passwd_func}. Questa interfaccia però funziona soltanto
+quando le informazioni sono mantenute su un apposito file di \textsl{registro}
+di utenti e gruppi, con il formato classico di \conffile{/etc/passwd} e
+\conffile{/etc/group}.
\begin{table}[htb]
\footnotesize
istruzioni in \textit{user space}, e quello impiegato dal kernel nelle
\textit{system call} eseguite per conto del processo (vedi
sez.~\ref{sec:sys_unix_time}). I campi \var{ru\_minflt} e \var{ru\_majflt}
-servono a quantificare l'uso della memoria virtuale\index{memoria~virtuale} e
-corrispondono rispettivamente al numero di \itindex{page~fault} \textit{page
- fault} (vedi sez.~\ref{sec:proc_mem_gen}) avvenuti senza richiedere I/O su
-disco (i cosiddetti \textit{minor page fault}), a quelli che invece han
-richiesto I/O su disco (detti invece \textit{major page
+servono a quantificare l'uso della memoria virtuale e corrispondono
+rispettivamente al numero di \textit{page fault} (vedi
+sez.~\ref{sec:proc_mem_gen}) avvenuti senza richiedere I/O su disco (i
+cosiddetti \textit{minor page fault}), a quelli che invece han richiesto I/O
+su disco (detti invece \textit{major page
fault}).% mentre \var{ru\_nswap} ed al numero di volte che
% il processo è stato completamente tolto dalla memoria per essere inserito
% nello swap.
La gestione della memoria è già stata affrontata in dettaglio in
sez.~\ref{sec:proc_memory}; abbiamo visto allora che il kernel provvede il
-meccanismo della \index{memoria~virtuale} memoria virtuale attraverso la
-divisione della memoria fisica in pagine. In genere tutto ciò è del tutto
-trasparente al singolo processo, ma in certi casi, come per l'I/O mappato in
-memoria (vedi sez.~\ref{sec:file_memory_map}) che usa lo stesso meccanismo per
-accedere ai file, è necessario conoscere le dimensioni delle pagine usate dal
-kernel. Lo stesso vale quando si vuole gestire in maniera ottimale
-l'interazione della memoria che si sta allocando con il meccanismo della
-\index{paginazione} paginazione.
+meccanismo della memoria virtuale attraverso la divisione della memoria fisica
+in pagine. In genere tutto ciò è del tutto trasparente al singolo processo,
+ma in certi casi, come per l'I/O mappato in memoria (vedi
+sez.~\ref{sec:file_memory_map}) che usa lo stesso meccanismo per accedere ai
+file, è necessario conoscere le dimensioni delle pagine usate dal kernel. Lo
+stesso vale quando si vuole gestire in maniera ottimale l'interazione della
+memoria che si sta allocando con il meccanismo della paginazione.
Un tempo la dimensione delle pagine di memoria era fissata una volta per tutte
dall'architettura hardware, per cui il relativo valore veniva mantenuto in una
\end{funcproto}
La funzione restituisce in ciascun elemento di \param{loadavg} il numero medio
-di processi attivi sulla coda dello \itindex{scheduler} scheduler, calcolato
-su diversi intervalli di tempo. Il numero di intervalli che si vogliono
-leggere è specificato da \param{nelem}, dato che nel caso di Linux il carico
-viene valutato solo su tre intervalli (corrispondenti a 1, 5 e 15 minuti),
-questo è anche il massimo valore che può essere assegnato a questo argomento.
+di processi attivi sulla coda dello \textit{scheduler}, calcolato su diversi
+intervalli di tempo. Il numero di intervalli che si vogliono leggere è
+specificato da \param{nelem}, dato che nel caso di Linux il carico viene
+valutato solo su tre intervalli (corrispondenti a 1, 5 e 15 minuti), questo è
+anche il massimo valore che può essere assegnato a questo argomento.
\subsection{La \textsl{contabilità} in stile BSD}