X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=73f2e7fb7e154388c55ce952497a41d5ab27e972;hp=cc64ab80a9210683e22b5e6b6bf61cdf0a1d6356;hb=e861c0f37f9eb16aed0f8bfbdb37afa04df1f685;hpb=6a94b0f6f36bad6daf7b8d3f52d211661a135836 diff --git a/prochand.tex b/prochand.tex index cc64ab8..73f2e7f 100644 --- a/prochand.tex +++ b/prochand.tex @@ -133,7 +133,8 @@ riprese), Come accennato in \secref{sec:intro_unix_struct} è lo \textit{scheduler} che decide quale processo mettere in esecuzione; esso viene eseguito ad ogni -system call ed ad ogni interrupt, (ma può essere anche attivato +system call ed ad ogni interrupt,\footnote{più in una serie di altre + occasioni. NDT completare questa parte.} (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 \macro{HZ}, definita in \file{asm/param.h}. Il @@ -1423,11 +1424,11 @@ processo, come copie dell'\textit{effective user id} e dell'\textit{effective fossero utente e gruppo effettivi all'inizio dell'esecuzione di un nuovo programma. -Il \textit{filesystem user id} e il \textit{filesystem group id} sono una -estensione introdotta in Linux per rendere più sicuro l'uso di NFS (torneremo -sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una replica dei -corrispondenti \textit{effective id}, ai quali si sostituiscono per tutte le -operazioni di verifica dei permessi relativi ai file (trattate in +Il \textit{filesystem user id} e il \textit{filesystem group id} sono +un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS +(torneremo sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una +replica dei corrispondenti \textit{effective id}, ai quali si sostituiscono +per tutte le operazioni di verifica dei permessi relativi ai file (trattate in \secref{sec:file_perm_overview}). Ogni cambiamento effettuato sugli \textit{effective id} viene automaticamente riportato su di essi, per cui in condizioni normali se ne può tranquillamente ignorare l'esistenza, in quanto @@ -1587,9 +1588,10 @@ Lo stesso problema di propagazione dei privilegi ad eventuali processi figli si porrebbe per i \textit{saved id}: queste funzioni derivano da un'implementazione che non ne prevede la presenza, e quindi non è possibile usarle per correggere la situazione come nel caso precedente. Per questo -motivo in Linux tutte le volte che vengono usate per modificare uno degli -identificatori ad un valore diverso dal \textit{real id} precedente, il -\textit{saved id} viene sempre settato al valore dell'\textit{effective id}. +motivo in Linux tutte le volte che tali funzioni vengono usate per modificare +uno degli identificatori ad un valore diverso dal \textit{real id} precedente, +il \textit{saved id} viene sempre settato al valore dell'\textit{effective + id}. @@ -1820,11 +1822,9 @@ 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}\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 prenderemo in esame i vari meccanismi -con cui viene gestita l'assegnazione del tempo di CPU, ed illustreremo le -varie funzioni di gestione. +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. \subsection{I meccanismi di \textit{scheduling}} @@ -1835,29 +1835,47 @@ il tempo di CPU per l'esecuzione dei processi ed oggetto di numerose ricerche; in ogni caso essa dipende in maniera essenziale anche dal tipo di utilizzo che deve essere fatto del sistema. -Si tenga presente comunque 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 caratteristica specifica di un sistema multitasking come Linux è quella del cosiddetto \textit{prehemptive multitasking}: questo significa che al contrario di altri sistemi (che usano invece il cosiddetto \textit{cooperative multitasking}) non sono i singoli processi, ma il kernel stesso a decidere quando la CPU deve essere passata ad un altro processo. Come accennato in -\secref{sec:proc_hierarchy} questa scelta viene eseguita dallo -\textit{scheduler} il cui scopo è quello di distribuire al meglio il tempo di -CPU fra i vari processi. +\secref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione +apposita del kernel, lo \textit{scheduler}, il cui scopo è quello di +distribuire al meglio il tempo di CPU fra i vari processi. -Il Linux un processo può trovarsi in uno degli stati riportati in +La cosa è resa ancora più complicata dal fatto che con le architetture +multi-processore si introduce anche la problematica 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 determinare 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, anche +quando si hanno più processori (e dei processi che sono eseguiti davvero in +contemporanea), si può pensare alle politiche di scheduling come concernenti +la risorsa \textsl{tempo di esecuzione}, la cui assegnazione sarà governata +dagli stessi meccanismi di scelta di priorità, solo che nel caso di più +processori sarà a disposizione di più di un processo alla volta. + +I processi non devono solo eseguire del codice, ad esempio molto spesso +saranno impegnati in operazioni di I/O, possono venire bloccati da un +comando dal terminale, sospesi per un certo periodo di tempo. In tutti questi +casi la CPU diventa disponibile ed è compito dello kernel provvedere a mettere +in esecuzione un altro processo. +Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del +processo , + +In Linux un processo può trovarsi in uno degli stati riportati in +\tabref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato +\textit{runnable} concorrono per l'esecuzione. Questo vuol di \begin{table}[htb] \centering - \begin{tabular}[c]{|l|c|p{8cm}|} + \begin{tabular}[c]{|p{3cm}|c|p{8cm}|} \hline \textbf{Stato} & \texttt{STAT} & \textbf{Descrizione} \\ \hline @@ -1875,40 +1893,27 @@ Il Linux un processo pu terminazione non è ancora stato letto dal padre. \\ \hline \end{tabular} - \caption{Tabella degli stati possibili per processo in Linux, si sono - riportati nella colonna \texttt{STAT} i valori dello stato ottenibili - dall'output del comando \cmd{ps}.} + \caption{Elenco dei possibili stati di un processo in Linux, nella colonna + \texttt{STAT} si è riportata la corripondente lettera usata dal comando + \cmd{ps} nell'omonimo campo.} \label{tab:proc_proc_states} \end{table} +Si deve quindi tenere presente che l'utilizzo della CPU è soltanto una delle +risorse che sono necessarie per l'esecuzione di un programma, e spesso non è +neanche la più importante. Per questo motivo non è affatto detto che dare ad +un programma la massima priorità di esecuzione abbia risultati significativi +in termini di prestazioni. -Una delle caratteristiche c -,\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} -La cosa è resa ancora più complicata dal fatto che con le architetture -multi-processore si introduce anche la problematica 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 determinare 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, anche -quando si hanno più processori (e dei processi che sono eseguiti davvero in -contemporanea), si può pensare alle politiche di scheduling come concernenti -la risorsa \textsl{tempo di esecuzione}, la cui assegnazione sarà governata -dagli stessi meccanismi di scelta di priorità, solo che nel caso di più -processori sarà a disposizione di più di un processo alla volta. +Una delle caratteristiche c +la priorità assoluta viene invece ignorata per quelli che sono bloccati su una +richiesta di I/O o in stato di \textit{sleep} @@ -1950,6 +1955,7 @@ assoluta nel qual caso un processo avr priorità inferiore che saranno eseguiti solo quando quest'ultimo non avrà bisogno della CPU. + \subsection{Il meccanismo di \textit{scheduling} standard} \label{sec:proc_sched_stand} @@ -2034,7 +2040,7 @@ qualunque momento, e le operazioni di un eventuale \textit{signal handler} sono compiute nello stesso spazio di indirizzi del processo. Per questo, anche il solo accesso o l'assegnazione di una variabile possono non essere più operazioni atomiche (torneremo su questi aspetti in -\secref{sec:sign_control}). +\secref{sec:sig_control}). In questo caso il sistema provvede un tipo di dato, il \type{sig\_atomic\_t}, il cui accesso è assicurato essere atomico. In pratica comunque si può @@ -2047,6 +2053,7 @@ le strutture. In tutti questi casi condiviso, onde evitare problemi con le ottimizzazioni del codice. + \subsection{Le \textit{race condition} e i \textit{deadlock}} \label{sec:proc_race_cond} @@ -2068,7 +2075,7 @@ funzioner Per questo occorre essere ben consapevoli di queste problematiche, e del fatto che l'unico modo per evitarle è quello di riconoscerle come tali e prendere -gli adeguati provvedimenti per far si che non si verifichino. Casi tipici di +gli adeguati provvedimenti per far sì che non si verifichino. Casi tipici di \textit{race condition} si hanno quando diversi processi accedono allo stesso file, o nell'accesso a meccanismi di intercomunicazione come la memoria condivisa. In questi casi, se non si dispone della possibilità di eseguire @@ -2114,12 +2121,12 @@ mai rientrante se usa una variabile globale o statica. Nel caso invece la funzione operi su un oggetto allocato dinamicamente, la cosa viene a dipendere da come avvengono le operazioni: se l'oggetto è creato ogni volta e ritornato indietro la funzione può essere rientrante, se invece -esso viene individuato dalla funzione stessa, due chiamate alla stessa -funzione potranno interferire quando entrambe faranno riferimento allo stesso -oggetto. Allo stesso modo una funzione può non essere rientrante se usa e -modifica un oggetto che le viene fornito dal chiamante: due chiamate possono -interferire se viene passato lo stesso oggetto; in tutti questi casi occorre -molta cura da parte del programmatore. +esso viene individuato dalla funzione stessa due chiamate alla stessa funzione +potranno interferire quando entrambe faranno riferimento allo stesso oggetto. +Allo stesso modo una funzione può non essere rientrante se usa e modifica un +oggetto che le viene fornito dal chiamante: due chiamate possono interferire +se viene passato lo stesso oggetto; in tutti questi casi occorre molta cura da +parte del programmatore. In genere le funzioni di libreria non sono rientranti, molte di esse ad esempio utilizzano variabili statiche, le \acr{glibc} però mettono a