X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=prochand.tex;h=90da68176a6c4159f16cd0eb25900d6530d0008f;hb=2df3e366683f4df738d40a05b97f820fde1648d9;hp=8f8beaffd588c9f45d0654c6a40cde391548d823;hpb=0d1802dcd969187e6133ba143ebc473c9fefc259;p=gapil.git diff --git a/prochand.tex b/prochand.tex index 8f8beaf..90da681 100644 --- a/prochand.tex +++ b/prochand.tex @@ -272,26 +272,68 @@ sempre un solo padre (il cui \acr{pid} pu \func{getppid}, vista in \secref{sec:proc_pid}) e si usa il valore nullo, che non può essere il \acr{pid} di nessun processo. -In \curfig\ si è riportato il corpo del codice dell'esempio \cmd{forktest}, -che ci permette di illustrare l'uso della funzione \func{fork}, creando un -numero di figli specificato a linea di comando; il codice completo, compresa -la parte che gestisce le opzioni a riga di comando, è disponibile nel file -\file{ForkTest.c}. - -Decifrato il numero di figli da creare il ciclo principale del programma +In \curfig\ si è riportato il corpo del codice del programma di esempio +\cmd{forktest}, che ci permette di illustrare l'uso della funzione +\func{fork}. Il programma permette di creare un numero di figli specificato a +linea di comando, e prende anche due opzioni \cmd{-p} e \cmd{-c} per indicare +dei tempi di attesa (in seconda) per il padre ed il figlio; il codice +completo, compresa la parte che gestisce le opzioni a riga di comando, è +disponibile nel file \file{ForkTest.c}. + +Decifrato il numero di figli da creare, il ciclo principale del programma (\texttt{\small 28--40}) esegue in successione la creazione dei processi figli -(\texttt{\small 29--31}) controllando il successo della chiamata a -\func{fork}; ciascun figlio (\texttt{\small 29--31}) si limita a stampare il -suo numero di successione, attendere 2 secondi e scrivere un messaggio prima +controllando il successo della chiamata a \func{fork} (\texttt{\small + 29--31}); ciascun figlio (\texttt{\small 29--31}) si limita a stampare il +suo numero di successione, attendere 3 secondi e scrivere un messaggio prima di uscire. Il processo padre invece (\texttt{\small 29--31}) stampa un -messaggio di creazione e procede nell'esecuzione del ciclo. - -In generale\footnote{anche se nel kernel 2.4.x è stato introdotto un +messaggio di creazione e procede nell'esecuzione del ciclo. Se eseguiamo il +comando otterremo come output sul terminale: +\begin{verbatim} +[piccardi@selidor sources]$ ./forktest 3 +Test for forking 3 child +Spawned 1 child, pid 2038 +Child 1 successfully executing +Child 1 exiting +Go to next child +Spawned 2 child, pid 2039 +Child 2 successfully executing +Child 2 exiting +Go to next child +Child 3 successfully executing +Child 3 exiting +Spawned 3 child, pid 2040 +Go to next child +\end{verbatim} %$ + +Come si vede non si può dire quale processo fra il padre ed il figlio venga +eseguito per primo\footnote{anche se nel kernel 2.4.x era stato introdotto un meccanismo che metteva in esecuzione sempre il xxx per primo (TODO - recuperare le informazioni esatte)} non si può dire quale processo fra il -padre ed il figlio venga eseguito per primo dopo la chiamata a \func{fork}, -per cui se i due processi devono essere sincronizzati occorre ricorrere ad un -qualche meccanismo di intercomunicazione. + recuperare le informazioni esatte)} dopo la chiamata a \func{fork}, nel caso +mostrato sopra ad esempio si può notare come dopo la creazione il secondo ed +il quinto figlio sia stato stati eseguiti per primi, mantre per gli altri +figli è stato eseguito per primo il padre. + +In generale l'ordine di esecuzione dipenderà, oltre che dall'algoritmo di +scheduling usato dal kernel, dalla particolare situazione in si trova la +macchina al momento della chiamata, risultando del tutto impredicibile. +Eseguendo più volte il programma di prova, si sono ottenute situazioni +completamente diverse, compreso caso in cui il processo padre ha eseguito più +di una \func{fork} prima che uno dei figli venisse messo in +esecuzione. + +Pertanto non si può fare nessuna assunzione sulla sequenza di esecuzione delle +istruzioni del codice fra padre e figli, e se è necessaria una qualche forma +di precedenza occorrerà provvedere ad espliciti meccanismi di +sincronizzazione, pena il rischio di incorrere nelle cosiddette \textit{race + conditions}. + +Si ricordi inoltre che come accennato, essendo i segmenti di memoria +utilizzati dai singoli processi completamente separati, le modifiche delle +variabili nei processi figli (come l'incremento di \var{i} in \texttt{\small + 33}) saranno effettive solo per essi, e non hanno alcun effetto sul valore +che le stesse variabili hanno nel processo padre. + +L'esempio mostra anche \subsection{Le funzioni \texttt{wait} e \texttt{waitpid}}