X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=4bd9a46c034a1d34de5fcae5775838f1e71b6d5d;hp=79ba6f129bfdbaca381d6ce7d9cf85d295534728;hb=01e363536700694f191264cf2c2955b31116d1e3;hpb=c7fb856f311d5aa072df08bd8fd61b66dcb1ec6b diff --git a/prochand.tex b/prochand.tex index 79ba6f1..4bd9a46 100644 --- a/prochand.tex +++ b/prochand.tex @@ -113,7 +113,6 @@ organizzati in un albero di directory (si veda comando \cmd{pstree} che permette di visualizzare questa struttura, alla cui base c'è \cmd{init} che è progenitore di tutti gli altri processi. - Il kernel mantiene una tabella dei processi attivi, la cosiddetta \textit{process table}; per ciascun processo viene mantenuta una voce nella tabella dei processi costituita da una struttura \type{task\_struct}, che @@ -895,18 +894,18 @@ specchietto riportato in \ntab: \begin{table}[!htb] \centering \footnotesize - \begin{tabular}[c]{|c|p{10cm}|} + \begin{tabular}[c]{|c|c|p{8cm}|} \hline - \textbf{Valore} & \textbf{Significato}\\ + \textbf{Valore} & \textbf{Macro} &\textbf{Significato}\\ \hline \hline - $<-1$& attende per un figlio il cui \textit{process group} è uguale al + $<-1$& -- & attende per un figlio il cui \textit{process group} è uguale al valore assoluto di \var{pid}. \\ - $-1$ & attende per un figlio qualsiasi, usata in questa maniera è - equivalente a \func{wait}.\\ - $0$ & attende per un figlio il cui \textit{process group} è uguale a - quello del processo chiamante. \\ - $>0$ & attende per un figlio il cui \acr{pid} è uguale al + $-1$ & \macro{WAIT\_ANY} & attende per un figlio qualsiasi, usata in + questa maniera è equivalente a \func{wait}.\\ + $0$ & \macro{WAIT\_MYPGRP} & attende per un figlio il cui \textit{process + group} è uguale a quello del processo chiamante. \\ + $>0$ & -- &attende per un figlio il cui \acr{pid} è uguale al valore di \var{pid}.\\ \hline \end{tabular} @@ -1348,7 +1347,7 @@ rispettivamente \textit{real} ed \textit{effective}. \hline \end{tabular} \caption{Identificatori di utente e gruppo associati a ciascun processo con - indicazione dei suffissi usate dalle varie funzioni di manipolazione.} + indicazione dei suffissi usati dalle varie funzioni di manipolazione.} \label{tab:proc_uid_gid} \end{table} @@ -1424,11 +1423,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 @@ -1588,9 +1587,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}. @@ -1836,6 +1836,66 @@ 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. + +Il Linux un processo può trovarsi in uno degli stati riportati in + + + +\begin{table}[htb] + \centering + \begin{tabular}[c]{|l|c|p{8cm}|} + \hline + \textbf{Stato} & \texttt{STAT} & \textbf{Descrizione} \\ + \hline + \hline + \textbf{Runnable} & \texttt{R} & Il processo è in esecuzione o è pronto ad + essere eseguito (cioè è in attesa che gli venga assegnata la CPU). \\ + \textbf{Sleep} & \texttt{S} & Il processo processo è in attesa di un + risposta dal sistema, ma può essere interrotto da un segnale. \\ + \textbf{Uninterrutible Sleep} & \texttt{D} & Il processo è in + attesa di un risposta dal sistema (in genere per I/O), e non può essere + interrotto in nessuna circostanza. \\ + \textbf{Stopped} & \texttt{T} & Il processo è stato fermato con un + \macro{SIGSTOP}, o è tracciato.\\ + \textbf{Zombie} & \texttt{Z} & Il processo è terminato ma il suo stato di + 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}.} + \label{tab:proc_proc_states} +\end{table} + + + + +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 @@ -1850,12 +1910,8 @@ la risorsa \textsl{tempo di esecuzione}, la cui assegnazione sar dagli stessi meccanismi di scelta di priorità, solo 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. + + Il meccanismo tradizionale di scheduling di Unix (che tratteremo in \secref{sec:proc_sched_stand}) è sempre stato basato su delle \textsl{priorità @@ -1882,13 +1938,7 @@ Il concetto di priorit l'esecuzione, vince sempre quello con la priorità assoluta più alta, anche quando l'altro è in esecuzione (grazie al \textit{prehemptive scheduling}). 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}. La priorità assoluta viene in +eseguiti (cioè nello stato \textit{runnable}). La priorità assoluta viene in genere indicata con un numero intero, ed un valore più alto comporta una priorità maggiore. Su questa politica di scheduling torneremo in \secref{sec:proc_real_time}. @@ -1984,7 +2034,8 @@ stesso processo, e pure alcune system call, possono essere interrotti in 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_xxx}). +operazioni atomiche (torneremo su questi aspetti in +\secref{sec:sign_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ò @@ -1997,6 +2048,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} @@ -2018,7 +2070,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 @@ -2064,12 +2116,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