X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=dcad87688627b3e71577586a24b12835bb8941a4;hp=4eb3d74603609dbed04093089a5cf81e3d6bd93d;hb=2bb235e9ba8e8d532251205d30b82455dc119894;hpb=470f15a82390d6120981e85202f45fc102f3e8a3 diff --git a/prochand.tex b/prochand.tex index 4eb3d74..dcad876 100644 --- a/prochand.tex +++ b/prochand.tex @@ -290,12 +290,19 @@ il processo figlio continuano ad essere eseguiti normalmente alla istruzione seguente la \func{fork}; il processo figlio è però una copia del padre, e riceve una copia dei segmenti di testo, stack e dati (vedi \secref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del -padre, ma la memoria è copiata, non condivisa\footnote{In generale il segmento - di testo, che è identico, è condiviso e tenuto in read-only, Linux poi - utilizza la tecnica del \textit{copy-on-write}, per cui la memoria degli - altri segmenti viene copiata dal kernel per il nuovo processo solo in caso - di scrittura, rendendo molto più efficiente il meccanismo della creazione di - un nuovo processo.}, pertanto padre e figlio vedono variabili diverse. +padre. Si tenga presente però che la memoria è copiata, non condivisa, pertanto +padre e figlio vedono variabili diverse. + +Per quanto riguarda la gestione della memoria in generale il segmento di +testo, che è identico, è condiviso e tenuto in read-only per il padre e per i +figli. Per gli altri segmenti Linux utilizza la tecnica del \textit{copy on + write}\index{copy on write}; questa tecnica comporta che una pagina di +memoria viene effettivamente copiata per il nuovo processo solo quando ci +viene effettuata sopra una scrittura (e si ha quindi una reale differenza fra +padre e figlio). In questo modo si rende molto più efficiente il meccanismo +della creazione di un nuovo processo, non essendo più necessaria la copia di +tutto lo spazio degli indirizzi virtuali del padre, ma solo delle pagine di +memoria che sono state modificate, e solo al momento della modifica stessa. La differenza che si ha nei due processi è che nel processo padre il valore di ritorno della funzione \func{fork} è il \acr{pid} del processo figlio, mentre @@ -591,8 +598,8 @@ comune dopo l'esecuzione di una \func{fork} \item la directory di lavoro e la directory radice (vedi \secref{sec:file_work_dir} e \secref{sec:file_chroot}). \item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}). -\item la maschera dei segnali bloccati e le azioni installate (vedi -\secref{sec:sig_xxx}). +\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigpending}) e le + azioni installate (vedi \secref{sec:sig_gen_beha}). \item i segmenti di memoria condivisa agganciati al processo (vedi \secref{sec:ipc_xxx}). \item i limiti sulle risorse (vedi \secref{sec:sys_xxx}). @@ -608,7 +615,8 @@ le differenze fra padre e figlio dopo la \func{fork} invece sono: nel figlio sono posti a zero. \item i \textit{file lock} (vedi \secref{sec:file_locking}), che non vengono ereditati dal figlio. -\item gli allarmi ed i segnali pendenti (vedi \secref{sec:sig_xxx}), che per il figlio vengono cancellati. +\item gli allarmi ed i segnali pendenti (vedi \secref{sec:sig_gen_beha}), che + per il figlio vengono cancellati. \end{itemize*} @@ -1199,7 +1207,7 @@ la lista completa \secref{sec:file_umask}) ed i \textit{lock} sui file (vedi \secref{sec:file_locking}). \item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda - \secref{sec:sig_xxx}). + \secref{sec:sig_sigpending}). \item i limiti sulle risorse (vedi \secref{sec:sys_limits}). \item i valori delle variabili \var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}). @@ -1210,7 +1218,7 @@ processo chiamante mantengono lo stesso settaggio pure nel nuovo programma, tutti gli altri segnali vengono settati alla loro azione di default. Un caso speciale è il segnale \macro{SIGCHLD} che, quando settato a \macro{SIG\_IGN}, può anche non essere resettato a \macro{SIG\_DFL} (si veda -\secref{sec:sig_xxx}). +\secref{sec:sig_gen_beha}). La gestione dei file aperti dipende dal valore che ha il flag di \textit{close-on-exec} (trattato in \secref{sec:file_fcntl}) per ciascun file @@ -1806,11 +1814,87 @@ quando si definisce \macro{\_POSIX\_SOURCE} o si compila con il flag \label{sec:proc_priority} In questa sezione tratteremo più approfonditamente i meccanismi con il quale -lo \textit{scheduler} assegna la CPU ai vari processi attivi, illustrando le -varie funzioni che permettono di leggere e modificare le priorità di -esecuzione dei programmi. - - +lo \textit{scheduler}\footnote{che è la parte del kernel che si occupa di + stabilire quale processo dovrà essere posto in esecuzione.} assegna la CPU +ai vari processi attivi. In particolare prendremo in esame i vari meccanismi +con cui viene gestita l'assgnazione del tempo di CPU, ed illustreremo le varie +funzioni di gestione. + + +\subsection{I meccanismi di \textit{scheduling}} +\label{sec:proc_sched} + +La scelta di un meccanismo che sia in grado di distribuire in maniera efficace +il tempo di CPU per l'esecuzione dei processi è sempre una questione delicata, +ed oggetto di numerose ricerche; in ogni caso essa dipende in maniera +essenziale anche dal tipo di utilizzo che deve essere fatto del sistema. + +La cosa è resa ancora più complicata dal fatto che con sistemi +multi-processore si introduce anche la complessità dovuta alla scelta di quale +sia la CPU più opportuna da utilizzare.\footnote{nei processori moderni la + presenza di ampie cache può rendere poco efficiente trasferire l'esecuzione + di un processo da una CPU ad un'altra, per cui occorrono meccanismi per + determininare quale è la migliore scelta fra le diverse CPU.} Tutto questo +comunque appartiene alle sottigliezze dell'implementazione del kernel, e dal +punto di vista dei programmi che girano in user space di può pensare sempre +alla risorsa tempo di esecuzione, governata dagli stessi mecca, che nel caso +di più processori sarà a disposizione di più di un processo alla volta. + +Si tenga presente inoltre che l'utilizzo della CPU è soltanto una delle +risorse (insieme alla memoria e all'accesso alle periferiche) che sono +necessarie per l'esecuzione di un programma, e spesso non è neanche la più +importante. Per questo non è affatto detto che dare ad un programma la massima +priorità di esecuzione abbia risultati significativi in termini di +prestazioni. + +La politica tradizionale di scheduling di Unix (che tratteremo in +\secref{sec:proc_sched_stand}) è sempre stata basata su delle priorità +dinamiche, che assicurassaro che tutti i processi, anche i meno importanti, +potessero ricevere un po' di tempo di CPU. + +Lo standard POSIX però per tenere conto dei sistemi real-time,\footnote{per + sistema real-time si intende un sistema in grado di eseguire operazioni in + tempo reale; in genere si tende a distinguere fra l'\textit{hard real-time} + in cui è necessario che i tempi di esecuzione di un programma siano + determinabili con certezza assoluta, come nel caso di meccanismi di + controllo di macchine, dove uno sforamento dei tempi avrebbe conseguenze + disastrose, e \textit{soft-real-time} in cui un occasionale sforamento è + ritenuto accettabile.} in cui è vitale che i processi in che devono essere +eseguiti in un determinato momento non debbano aspettare la conclusione di un +altri processi che non hanno questa necessità, ha introdotto il concetto di +\textsl{priorità assoluta}, chimata anche \textsl{priorità statica}, in +contrapposizione con la normale priorità dinamica. + +Il concetto di prorità assoluta dice che quando due processi si contendono +l'esecuzione, vince sempre quello con la priorità assoluta più alta, anche, +grazie al \textit{prehemptive scheduling}, se l'altro è in esecuzione. +Ovviamente questo avviene solo per i processi che sono pronti per essere +eseguiti (cioè nello stato \textit{runnable}\footnote{lo stato di un processo + è riportato nel campo \texttt{STAT} dell'output del comando \cmd{ps}, + abbiamo già visto che lo stato di \textit{zombie} è indicato con \texttt{Z}, + gli stati \textit{runnable}, \textit{sleep} e di I/O (\textit{uninteruttible + sleep}) sono invece indicati con \texttt{R}, \texttt{S} e \texttt{D}.}), +la priorità assoluta viene invece ignorata per quelli che sono bloccati su una +richiesta di I/O o in stato di \textit{sleep}. + +Questa viene in genere indicata con un numero + + + + + +\subsection{Il meccanismo di \textit{scheduling} standard} +\label{sec:proc_sched_stand} + +In Linux tutti i processi hanno sostanzialmente la stessa priorità; benché sia +possibile specificare una priorità assoluta secondo lo standard POSIX +(argomento che tratteremo più avanti) l'uso comune segue quello che è il +meccanismo tradizionale con cui i sistemi + +\subsection{Il meccanismo di \textit{scheduling real-time}} +\label{sec:proc_real_time} + +Per settare le