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
\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}
\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}
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
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}.
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
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à
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}.
condiviso, onde evitare problemi con le ottimizzazioni del codice.
+
\subsection{Le \textit{race condition} e i \textit{deadlock}}
\label{sec:proc_race_cond}
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
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