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
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
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
\end{functions}
La funzione ripristina il contesto dello stack salvato da una chiamata a
-\func{setjmp} nell'argomento \param{env}. Dopo l'esecuzione della funzione
+\func{setjmp} nell'argomento \param{env}. Dopo l'esecuzione della funzione il
programma prosegue nel codice successivo al ritorno della \func{setjmp} con
cui si era salvato \param{env}, che restituirà il valore \param{val} invece di
zero. Il valore di \param{val} specificato nella chiamata deve essere diverso
Quello che succede infatti è che i valori delle variabili che sono tenute in
memoria manterranno il valore avuto al momento della chiamata di
\func{longjmp}, mentre quelli tenuti nei registri del processore (che nella
-chiamata ad un'altra funzioni vengono salvati nel contesto nello stack)
+chiamata ad un'altra funzione vengono salvati nel contesto nello stack)
torneranno al valore avuto al momento della chiamata di \func{setjmp}; per
questo quando si vuole avere un comportamento coerente si può bloccare
l'ottimizzazione che porta le variabili nei registri dichiarandole tutte come