%% process.tex
%%
-%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2003 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Prefazione",
Lo standard ISO C specifica che la funzione \func{main} può non avere
argomenti o prendere due argomenti che rappresentano gli argomenti passati da
linea di comando, in sostanza un prototipo che va sempre bene è il seguente:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
- int main (int argc, char *argv[])
-\end{lstlisting}
+\includecodesnip{listati/main_def.c}
In realtà nei sistemi Unix esiste un'altro modo per definire la funzione
\func{main}, che prevede la presenza di un terzo parametro, \code{char
all'utente, avere la possibilità di effettuare automaticamente la chiamata ad
una funzione che effettui tali operazioni all'uscita dal programma. A questo
scopo lo standard ANSI C prevede la possibilità di registrare un certo numero
-funzioni che verranno eseguite all'uscita dal programma (sia per la chiamata
-ad \func{exit} che per il ritorno di \func{main}). La prima funzione che si
-può utilizzare a tal fine è \funcd{atexit} il cui prototipo è:
+di funzioni che verranno eseguite all'uscita dal programma (sia per la
+chiamata ad \func{exit} che per il ritorno di \func{main}). La prima funzione
+che si può utilizzare a tal fine è \funcd{atexit} il cui prototipo è:
\begin{prototype}{stdlib.h}{void atexit(void (*function)(void))}
Registra la funzione \param{function} per la chiamata all'uscita dal
programma.
\end{prototype}
\noindent la funzione richiede come argomento l'indirizzo di una opportuna
funzione di pulizia da chiamare all'uscita del programma, che non deve
-prendere argomenti e non deve ritornare niente (deve essere essere cioè
-definita come \code{void function(void)}).
+prendere argomenti e non deve ritornare niente (deve essere cioè definita come
+\code{void function(void)}).
Un'estensione di \func{atexit} è la funzione \funcd{on\_exit}, che le
\acr{glibc} includono per compatibilità con SunOS, ma che non è detto sia
Per la gestione da parte del kernel la memoria virtuale viene divisa in pagine
di dimensione fissa (che ad esempio sono di 4kb su macchine a 32 bit e 8kb
sulle alpha, valori strettamente connessi all'hardware di gestione della
-memoria), e ciascuna pagina della memoria virtuale è associata ad un supporto
-che può essere una pagina di memoria reale o ad un dispositivo di stoccaggio
-secondario (in genere lo spazio disco riservato alla swap, o i file che
-contengono il codice).
+memoria),\footnote{con le versioni più recenti del kernel è possibile anche
+ utilizzare pagine di dimensioni maggiori, per sistemi con grandi
+ quantitativi di memoria in cui l'uso di pagine troppo piccole comporta una
+ perdita di prestazioni.} e ciascuna pagina della memoria virtuale è
+associata ad un supporto che può essere una pagina di memoria reale o ad un
+dispositivo di stoccaggio secondario (in genere lo spazio disco riservato alla
+swap, o i file che contengono il codice).
Lo stesso pezzo di memoria reale (o di spazio disco) può fare da supporto a
diverse pagine di memoria virtuale appartenenti a processi diversi (come
La prima parte è il segmento dei dati inizializzati, che contiene le
variabili il cui valore è stato assegnato esplicitamente. Ad esempio
se si definisce:
- \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
- double pi = 3.14;
- \end{lstlisting}
+\includecodesnip{listati/pi.c}
questo valore sarà immagazzinato in questo segmento. La memoria di questo
segmento viene preallocata all'avvio del programma e inizializzata ai valori
specificati.
La seconda parte è il segmento dei dati non inizializzati, che contiene le
variabili il cui valore non è stato assegnato esplicitamente. Ad esempio se
si definisce:
- \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
- int vect[100];
- \end{lstlisting}
+\includecodesnip{listati/vect.c}
questo vettore sarà immagazzinato in questo segmento. Anch'esso viene
allocato all'avvio, e tutte le variabili vengono inizializzate a zero (ed i
puntatori a \val{NULL}).\footnote{si ricordi che questo vale solo per le
variabili che vanno nel segmento dati, e non è affatto vero in generale.}
- Storicamente questo segmento viene chiamato BBS (da \textit{block started by
+ Storicamente questo segmento viene chiamato BSS (da \textit{block started by
symbol}). La sua dimensione è fissa.
\item Lo \textit{heap}. Tecnicamente lo si può considerare l'estensione del
In C e C++ il problema è particolarmente sentito. In C++, per mezzo della
programmazione ad oggetti, il problema dei \textit{memory leak} è notevolmente
ridimensionato attraverso l'uso accurato di appositi oggetti come gli
-\textit{smartpointers}. Questo però va a scapito delle performance
+\textit{smartpointers}. Questo però va a scapito delle prestazioni
dell'applicazione in esecuzione.
In altri linguaggi come il java e recentemente il C\# il problema non si pone
riferita da nessuna parte del codice in esecuzione, può essere deallocata
automaticamente in qualunque momento dall'infrastruttura.
-Anche questo va a scapito delle performance dell'applicazione in esecuzione
+Anche questo va a scapito delle prestazioni dell'applicazione in esecuzione
(inoltre le applicazioni sviluppate con tali linguaggi di solito non sono
eseguibili compilati, come avviene invece per il C ed il C++, ed è necessaria
la presenza di una infrastruttura per la loro interpretazione e pertanto hanno
-di per sé delle performance più scadenti rispetto alle stesse applicazioni
+di per sé delle prestazioni più scadenti rispetto alle stesse applicazioni
compilate direttamente). Questo comporta però il problema della non
predicibilità del momento in cui viene deallocata la memoria precedentemente
allocata da un oggetto.
elementi di \param{argv} che cominciano con il carattere \texttt{'-'}.
\begin{figure}[htb]
- \footnotesize
- \begin{lstlisting}{}
- opterr = 0; /* don't want writing to stderr */
- while ( (i = getopt(argc, argv, "hp:c:e:")) != -1) {
- switch (i) {
- /*
- * Handling options
- */
- case 'h': /* help option */
- printf("Wrong -h option use\n");
- usage();
- return -1;
- break;
- case 'c': /* take wait time for children */
- wait_child = strtol(optarg, NULL, 10); /* convert input */
- break;
- case 'p': /* take wait time for children */
- wait_parent = strtol(optarg, NULL, 10); /* convert input */
- break;
- case 'e': /* take wait before parent exit */
- wait_end = strtol(optarg, NULL, 10); /* convert input */
- break;
- case '?': /* unrecognized options */
- printf("Unrecognized options -%c\n",optopt);
- usage();
- default: /* should not reached */
- usage();
- }
- }
- debug("Optind %d, argc %d\n",optind,argc);
- \end{lstlisting}
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/option_code.c}
+ \end{minipage}
+ \normalsize
\caption{Esempio di codice per la gestione delle opzioni.}
\label{fig:proc_options_code}
\end{figure}
L'indirizzo della lista delle variabili di ambiente è passato attraverso la
variabile globale \var{environ}, a cui si può accedere attraverso una semplice
dichiarazione del tipo:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-extern char ** environ;
-\end{lstlisting}
+\includecodesnip{listati/env_ptr.c}
un esempio della struttura di questa lista, contenente alcune delle variabili
più comuni che normalmente sono definite dal sistema, è riportato in
\figref{fig:proc_envirno_list}.
questo si usa il cosiddetto \textit{value result argument}, si passa cioè,
invece di una normale variabile, un puntatore alla stessa; vedremo alcuni
esempi di questa modalità nelle funzioni che gestiscono i socket (in
-\secref{sec:TCPel_functions}), in cui, per permettere al kernel di restituire
+\secref{sec:TCP_functions}), in cui, per permettere al kernel di restituire
informazioni sulle dimensioni delle strutture degli indirizzi utilizzate,
viene usato questo meccanismo.
deve essere incluso l'apposito header file \file{stdarg.h}; un esempio di
dichiarazione è il prototipo della funzione \func{execl} che vedremo in
\secref{sec:proc_exec}:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
- int execl(const char *path, const char *arg, ...);
-\end{lstlisting}
+\includecodesnip{listati/exec_sample.c}
in questo caso la funzione prende due parametri fissi ed un numero variabile
di altri parametri (che verranno a costituire gli elementi successivi al primo
del vettore \param{argv} passato al nuovo processo). Lo standard ISO C richiede
normale pensare di poter effettuare questa operazione.
In generale però possono esistere anche realizzazioni diverse, per questo
-motivo \macro{va\_list} è definito come \textsl{tipo opaco}\index{tipo opaco}
+motivo \macro{va\_list} è definito come \textsl{tipo opaco}\index{tipo!opaco}
e non può essere assegnato direttamente ad un'altra variabile dello stesso
tipo. Per risolvere questo problema lo standard ISO C99\footnote{alcuni
sistemi che non hanno questa macro provvedono al suo posto
salvare il contesto dello stack è \funcd{setjmp}, il cui prototipo è:
\begin{functions}
\headdecl{setjmp.h}
- \funcdecl{void setjmp(jmp\_buf env)}
+ \funcdecl{int setjmp(jmp\_buf env)}
Salva il contesto dello stack.
\func{longjmp}, ma quelli delle variabili automatiche (o di quelle dichiarate
\direct{register}\footnote{la direttiva \direct{register} del compilatore
chiede che la variabile dichiarata tale sia mantenuta, nei limiti del
- possibile, all'interno di un registro del processore. Questa direttiva
- origina dai primi compilatori, quando stava al programmatore scrivere codice
- ottimizzato, riservando esplicitamente alle variabili più usate l'uso dei
- registri del processore. Oggi questa direttiva oggi è in disuso dato che
- tutti i compilatori sono normalmente in grado di valutare con maggior
- efficacia degli stessi programmatori quando sia il caso di eseguire questa
- ottimizzazione.}) sono in genere indeterminati.
+ possibile, all'interno di un registro del processore. Questa direttiva è
+ originaria dell'epoca dai primi compilatori, quando stava al programmatore
+ scrivere codice ottimizzato, riservando esplicitamente alle variabili più
+ usate l'uso dei registri del processore. Oggi questa direttiva è in disuso
+ dato che tutti i compilatori sono normalmente in grado di valutare con
+ maggior efficacia degli stessi programmatori quando sia il caso di eseguire
+ questa ottimizzazione.}) sono in genere indeterminati.
Quello che succede infatti è che i valori delle variabili che sono tenute in
memoria manterranno il valore avuto al momento della chiamata di