From: Simone Piccardi Date: Sun, 1 Jul 2007 16:11:26 +0000 (+0000) Subject: Tolti un puoi di todo, chiarita la parte sulle calling convention, X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=6ffcce00491cea4ac7c621fe412269f15ee23f57 Tolti un puoi di todo, chiarita la parte sulle calling convention, sulla costante HZ ed il timer tickless, risistemate un po' le funzioni sui processi, predisposte le cose per introdurre {{{waitid}}}. --- diff --git a/process.tex b/process.tex index 3f50045..9d749c0 100644 --- a/process.tex +++ b/process.tex @@ -402,10 +402,16 @@ seguenti segmenti: viene il nome \itindex{stack} \textit{stack}) in sequenza uno sull'altro; in questo modo le funzioni possono essere chiamate ricorsivamente. Al ritorno della funzione lo spazio è automaticamente rilasciato e - ``\textsl{ripulito}''. La pulizia in C e C++ viene fatta dal - chiamante.\footnote{a meno che non sia stato specificato l'utilizzo di una - calling convention diversa da quella standard.} -% TODO verificare le modalità di cambiamento della calling convention + ``\textsl{ripulito}''.\footnote{il compilatore si incarica di generare + automaticamente il codice necessario, seguendo quella che viene chiamata + una \textit{calling convention}; quella standard usata con il C ed il C++ + è detta \textit{cdecl} e prevede che gli argomenti siano caricati nello + stack fal chiamante da destra a sinistra, e che si il chimante stesso ad + eseguire la ripulitura dello stack al ritorno della funzione, se ne + possono però utilizzare di alternative (ad esempio nel pascal gli + argomenti sono inseriti da sinistra a destra ed è compito del chiamato + ripulire lo stack), in genere non ci si deve preoccupare di questo + fintanto che non si mescolano funzioni scritte con linguaggi diversi.} La dimensione di questo segmento aumenta seguendo la crescita dello \itindex{stack} \textit{stack} del programma, ma non viene ridotta quando diff --git a/prochand.tex b/prochand.tex index 960a88f..ada9b4f 100644 --- a/prochand.tex +++ b/prochand.tex @@ -138,7 +138,7 @@ fig.~\ref{fig:proc_task_struct}. \begin{figure}[htb] \centering - \includegraphics[width=13cm]{img/task_struct} + \includegraphics[width=11cm]{img/task_struct} \caption{Schema semplificato dell'architettura delle strutture usate dal kernel nella gestione dei processi.} \label{fig:proc_task_struct} @@ -150,15 +150,23 @@ eseguito ad ogni system call ed ad ogni interrupt,\footnote{pi 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 \const{HZ}, definita -in \file{asm/param.h}, ed il cui valore è espresso in Hertz.\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. Occorre fare attenzione - a non confondere questo valore con quello dei clock tick (vedi - sez.~\ref{sec:sys_unix_time}).} -% TODO verificare gli ultimi cambiamenti del 2.6 -% Si ha cioè un interrupt dal timer ogni centesimo di secondo. +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 + attenzione a non confondere questo valore con quello dei clock tick (vedi + sez.~\ref{sec:sys_unix_time}).} definita in \file{asm/param.h}, ed il cui +valore è espresso in Hertz.\footnote{a partire dal kernel 2.6.21 è stato + introdotto (a cura di Ingo Molnar) un meccanismo completamente diverso, + detto \textit{tickless}, in cui non c'è più una interruzione periodica con + frequenza prefissata, ma ad ogni chiamata del time viene programmata + l'interruzione successiva sulla base di una stima; in questo modo si evita + di dover eseguire un migliaio di interruzioni al secondo anche su macchine + che non stanno facendo nulla, con un forte risparmio nell'uso dell'energia + 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 @@ -291,7 +299,7 @@ dell'identit affrontato in dettaglio in sez.~\ref{sec:proc_perms}. -\subsection{La funzione \func{fork}} +\subsection{La funzione \func{fork} e le funzioni di creazione dei processi} \label{sec:proc_fork} La funzione \funcd{fork} è la funzione fondamentale della gestione dei @@ -607,7 +615,7 @@ comune dopo l'esecuzione di una \func{fork} sez.~\ref{sec:ipc_sysv_shm}); \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit}); \item le priorità real-time e le affinità di processore (vedi - sez.~\ref{sec:proc_real_time}); + sez.~\ref{sec:proc_real_time} e sez.\ref{sec:proc_sched_multiprocess}); \item le variabili di ambiente (vedi sez.~\ref{sec:proc_environ}). \end{itemize*} Le differenze fra padre e figlio dopo la \func{fork} invece sono: @@ -625,10 +633,8 @@ Le differenze fra padre e figlio dopo la \func{fork} invece sono: \end{itemize*} -\subsection{La funzione \func{vfork}} -\label{sec:proc_vfork} - -La funzione \func{vfork} è esattamente identica a \func{fork} ed ha la stessa +Una seconda funzione storica usata per la creazione di un nuovo processo è +\func{vfork}, che è esattamente identica a \func{fork} ed ha la stessa semantica e gli stessi errori; la sola differenza è che non viene creata la tabella delle pagine né la struttura dei task per il nuovo processo. Il processo padre è posto in attesa fintanto che il figlio non ha eseguito una @@ -870,8 +876,10 @@ Per questo motivo lo standard POSIX.1 ha introdotto la funzione \funcd{waitpid} che effettua lo stesso servizio, ma dispone di una serie di funzionalità più ampie, legate anche al controllo di sessione (si veda sez.~\ref{sec:sess_job_control}). Dato che è possibile ottenere lo stesso -comportamento di \func{wait} si consiglia di utilizzare sempre questa -funzione, il cui prototipo è: +comportamento di \func{wait}\footnote{in effetti eseguire il codice + \code{wait(\&s)} è del tutto equivalente a \code{waitpid(WAIT\_ANY}, \&s, + 0)}. } si consiglia di utilizzare sempre questa funzione, il cui prototipo +è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/wait.h} @@ -901,7 +909,7 @@ secondo lo specchietto riportato in tab.~\ref{tab:proc_waidpid_pid}. \footnotesize \begin{tabular}[c]{|c|c|p{8cm}|} \hline - \textbf{Valore} & \textbf{Opzione} &\textbf{Significato}\\ + \textbf{Valore} & \textbf{Costante} &\textbf{Significato}\\ \hline \hline $<-1$& -- & attende per un figlio il cui @@ -1026,10 +1034,6 @@ Si tenga conto che nel caso di conclusione anomala il valore restituito da \file{signal.h} ed elencate in tab.~\ref{tab:sig_signal_list}, e stampato usando le apposite funzioni trattate in sez.~\ref{sec:sig_strsignal}. - -\subsection{Le funzioni \func{wait3} e \func{wait4}} -\label{sec:proc_wait4} - Linux, seguendo un'estensione di BSD, supporta altre due funzioni per la lettura dello stato di terminazione di un processo, analoghe alle precedenti ma che prevedono un ulteriore argomento attraverso il quale il kernel può @@ -3119,17 +3123,21 @@ l'esecuzione non sar in modalità \textit{fifo}, per permettere l'esecuzione degli altri processi con pari priorità quando la sezione più urgente è finita. + +\subsection{Il controllo dello \textit{scheduler} per i sistemi multiprocessore} +\label{sec:proc_sched_multiprocess} + Infine 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 -\index{effetto~ping-pong} dell'\textsl{effetto ping-pong}. Può accadere cioè -che lo 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}. +che si pongono nei sistemi multiprocessore è infatti quello del cosiddetto +\index{effetto~ping-pong} \textsl{effetto ping-pong}. Può accadere cioè che lo +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 @@ -3152,13 +3160,13 @@ 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 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 -scheduler dei kernel della 2.6.x questo problema è stato risolto ed esso cerca -di mantenere il più possibile ciascun processo sullo stesso processore. + 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 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 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 diff --git a/system.tex b/system.tex index ec3a084..dfc71d9 100644 --- a/system.tex +++ b/system.tex @@ -1367,7 +1367,7 @@ utilizzo. \subsection{L'uso delle risorse} \label{sec:sys_resource_use} -Come abbiamo accennato in sez.~\ref{sec:proc_wait4} le informazioni riguardo +Come abbiamo accennato in sez.~\ref{sec:proc_wait} le informazioni riguardo l'utilizzo delle risorse da parte di un processo è mantenuto in una struttura di tipo \struct{rusage}, la cui definizione (che si trova in \file{sys/resource.h}) è riportata in fig.~\ref{fig:sys_rusage_struct}. @@ -1411,7 +1411,7 @@ ai tempi di utilizzo del processore, che sono definiti come strutture di tipo \struct{timeval}. Questa è la stessa struttura utilizzata da \func{wait4} (si ricordi quando -visto in sez.~\ref{sec:proc_wait4}) per ricavare la quantità di risorse +visto in sez.~\ref{sec:proc_wait}) per ricavare la quantità di risorse impiegate dal processo di cui si è letto lo stato di terminazione, ma essa può anche essere letta direttamente utilizzando la funzione \funcd{getrusage}, il cui prototipo è: