X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=process.tex;h=a096d6a866c6d87f152ad5888b92fb17e9e8f294;hp=71eec012f6317636968ee5aae1162321c6c38dd7;hb=23010d9e9a5dd36da44a8a2a89eb8bd95cb18dfa;hpb=6fd382ec7c31bd1265edceba7ee0c2c6c3e61f88 diff --git a/process.tex b/process.tex index 71eec01..a096d6a 100644 --- a/process.tex +++ b/process.tex @@ -6,7 +6,8 @@ sistema unix alloca ed utilizza le risorse. Questo capitolo tratter l'interfaccia base fra il sistema e i processi, su come vengono passati i parametri, come viene gestita e allocata la memoria, su come un processo può richiedere servizi al sistema, su cosa deve fare quando ha finito la sua -esecuzione. +esecuzione. Nella sezione finale acceneremo ad alcune problematiche generiche +di programmazione. In genere un programma viene eseguito quando un processo lo fa partire eseguendo una funzione della famiglia \func{exec}; torneremo su questo e @@ -438,13 +439,13 @@ quattro, i prototipi sono i seguenti: \begin{functions} \headdecl{stdlib.h} \funcdecl{void *calloc(size\_t size)} - Alloca \var{size} bytes nello heap. La memoria viene inizializzata a 0. + Alloca \var{size} byte nello heap. La memoria viene inizializzata a 0. La funzione restituisce il puntatore alla zona di memoria allocata in caso di successo e \macro{NULL} in caso di fallimento, nel qual caso \var{errno} viene settata a \macro{ENOMEM}. \funcdecl{void *malloc(size\_t size)} - Alloca \var{size} bytes nello heap. La memoria non viene inizializzata. + Alloca \var{size} byte nello heap. La memoria non viene inizializzata. La funzione restituisce il puntatore alla zona di memoria allocata in caso di successo e \macro{NULL} in caso di fallimento, nel qual caso @@ -474,7 +475,7 @@ allocazione. La memoria allocata dinamicamente deve essere esplicitamente rilasciata usando \func{free}\footnote{le glibc provvedono anche una funzione \func{cfree} - defininita per compatibilità con SunOS, che è deprecata} una volta che non + definita per compatibilità con SunOS, che è deprecata} una volta che non sia più necessaria. Questa funzione vuole come parametro un puntatore restituito da una precedente chiamata a una qualunque delle funzioni di allocazione e che non sia già stato liberato da un'altra chiamata a @@ -484,13 +485,13 @@ La funzione \func{realloc} si usa invece per cambiare (in genere aumentare) la dimensione di un'area di memoria precedentemente allocata, la funzione vuole in ingresso il puntatore restituito dalla precedente chiamata ad una \func{malloc} (se è passato un valore \macro{NULL} allora la funzione si -comporta come \func{malloc}\footnote{questo è vero per linux e +comporta come \func{malloc}\footnote{questo è vero per Linux e l'implementazione secondo lo standard ANSI C, ma non è vero per alcune vecchie implementazioni, inoltre alcune versioni delle librerie del C consentivano di usare \func{realloc} anche per un puntatore liberato con \func{free} purché non ci fossero state altre chiamate a funzioni di allocazione, questa funzionalità è totalmente deprecata e non è consentita - sotto linux}), ad esempio quando si deve far crescere la dimensione di un + sotto Linux}), ad esempio quando si deve far crescere la dimensione di un vettore; in questo caso se è disponibile dello spazio adiacente al precedente la funzione lo utilizza, altrimenti rialloca altrove un blocco della dimensione voluta copiandoci automaticamente il contenuto, lo spazio in più non viene @@ -516,13 +517,13 @@ variabile \macro{MALLOC\_CHECK\_} che quando viene settata mette in uso una versione meno efficiente delle funzioni, che però è più tollerante nei confronti di piccoli errori come quello di chiamate doppie a \func{free}; in particolare: -\begin{itemize} +\begin{itemize*} \item se la variabile è posta a zero gli errori vengono ignorati. \item se è posta ad 1 viene stampato un avviso sullo \textit{standard error} (vedi \secref{sec:file_stdfiles}). \item se è posta a 2 viene chiamata \func{abort}, che in genere causa l'immediata conclusione del programma. -\end{itemize} +\end{itemize*} Il problema più comune e più difficile da tracciare che si incontra con l'allocazione della memoria è però quando la memoria non più utilizzata non @@ -552,7 +553,7 @@ di problemi di memory leak descritti in precedenza \texttt{alloca} che invece che allocare la memoria nello heap usa lo il segmento di stack della funzione corrente. La sintassi è identica: \begin{prototype}{stdlib.h}{void *alloca(size\_t size)} - Alloca \texttt{size} bytes nel segmento di stack della funzione chiamante. + Alloca \texttt{size} byte nel segmento di stack della funzione chiamante. La memoria non viene inizializzata. La funzione restituisce il puntatore alla zona di memoria allocata in caso @@ -591,32 +592,32 @@ puntatore ad una di queste variabili, che sar all'uscita della funzione, con gli stessi problemi appena citati per \func{alloca}. -\subsection{Le funzioni \texttt{brk} e \texttt{sbrk}} +\subsection{Le funzioni \func{brk} e \func{sbrk}} \label{sec:proc_mem_sbrk} L'uso di queste funzioni è necessario solo quando si voglia accedere alle analoghe system call a cui fanno da interfaccia (ad esempio per implementare -una propria versione di \texttt{malloc}. Le funzione sono: +una propria versione di \func{malloc}. Le funzione sono: \begin{prototype}{unistd.h}{int *brk(void end\_data\_segment)} Sposta la fine del segmento dei dati all'indirizzo specificato da - \texttt{end\_data\_segment}. + \var{end\_data\_segment}. La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, - nel qual caso \texttt{errno} viene settata a \texttt{ENOMEM}. + nel qual caso \var{errno} viene settata a \macro{ENOMEM}. \end{prototype} \begin{prototype}{unistd.h}{int *sbrk(ptrdiff\_t increment)} - Incrementa lo spazio dati di un programma di \texttt{increment}. Un valore + Incrementa lo spazio dati di un programma di \var{increment}. Un valore zero restituisce l'attuale posizione della fine del segmento dati. La funzione restituisce il puntatore all'inizio della nuova zona di memoria - allocata in caso di successo e \texttt{NULL} in caso di fallimento, nel qual - caso \texttt{errno} viene settata a \texttt{ENOMEM}. + allocata in caso di successo e \macro{NULL} in caso di fallimento, nel qual + caso \macro{errno} viene settata a \macro{ENOMEM}. \end{prototype} Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e per i programmi normali è opportuno usare le funzioni di allocazione standard descritte in precedenza, che sono costruite su di esse. In genere si usa -\texttt{sbrk} con un valore zero per ottenere l'attuale posizione della fine +\func{sbrk} con un valore zero per ottenere l'attuale posizione della fine del segmento dati. @@ -670,33 +671,53 @@ bloccata allora esso viene escluso dal meccanismo della paginazione. I blocchi non si accumulano, se si blocca due volte la stessa pagina non è necessario sbloccarla due volte, una pagina o è bloccata o no. -Il blocco di memoria persiste fintanto che il processo che lo detiene la +Il \textit{memory lock} persiste fintanto che il processo che detiene la memoria bloccata non la sblocca. Chiaramente la terminazione del processo comporta anche la fine dell'uso della sua memoria virtuale, e quindi anche di -tutti i blocchi di memoria. - -I memory lock non sono ereditati dai processi figli\footnote{ma siccome Linux - usa il copy on write gli indirizzi virtuali del figlio sono mantenuti sullo - stesso segmento di RAM del padre, quindi usufruiscono dei memory lock di - questo}. Siccome la presenza di memory lock ha un impatto sugli altri -processi solo root ha la capacità di bloccare una pagina, ogni processo può -però sbloccare le sue pagine. Il sistema pone dei limiti all'ammontare di +tutti i \textit{memory lock}. + +I \textit{memory lock} non sono ereditati dai processi figli\footnote{ma + siccome Linux usa il copy on write gli indirizzi virtuali del figlio sono + mantenuti sullo stesso segmento di RAM del padre, quindi fintanto che un + figlio non scrive su un segmento, può usufruire dei memory lock del padre}. +Siccome la presenza di \textit{memory lock} ha un impatto sugli altri processi +solo l'amministratore ha la capacità di bloccare una pagina; ogni processo +però può sbloccare le sue pagine. Il sistema pone dei limiti all'ammontare di memoria di un processo che può essere bloccata e al totale di memoria fisica che può dedicare a questo. +Le funzioni per bloccare e sbloccare singole sezioni di memoria sono +\func{mlock} e \func{munlock}; i loro prototipi sono: + +\begin{functions} +\headdecl{stdlib.h} +\funcdecl{void *calloc(size\_t size)} + Alloca \var{size} byte nello heap. La memoria viene inizializzata a 0. + + La funzione restituisce il puntatore alla zona di memoria allocata in caso + di successo e \macro{NULL} in caso di fallimento, nel qual caso + \var{errno} viene settata a \macro{ENOMEM}. +\funcdecl{void *malloc(size\_t size)} + Alloca \var{size} byte nello heap. La memoria non viene inizializzata. + + La funzione restituisce il puntatore alla zona di memoria allocata in caso + di successo e \macro{NULL} in caso di fallimento, nel qual caso + \var{errno} viene settata a \macro{ENOMEM}. +\funcdecl{void *realloc(void *ptr, size\_t size)} + Cambia la dimensione del blocco allocato all'indirizzo \var{ptr} + portandola a \var{size}. + + La funzione restituisce il puntatore alla zona di memoria allocata in caso + di successo e \macro{NULL} in caso di fallimento, nel qual caso + \var{errno} viene settata a \macro{ENOMEM}. +\funcdecl{void free(void *ptr)} + Disalloca lo spazio di memoria puntato da \var{ptr}. + + La funzione non ritorna nulla. +\end{functions} -\section{Il controllo di flusso non locale} -\label{sec:proc_longjmp} -Il controllo del flusso di un programma in genere viene effettuato con le -varie istruzioni del linguaggio C, la più bistrattata delle quali è il -\func{goto}, ampiamente deprecato in favore di costrutti più puliti; esiste -però un caso in l'uso di questa istruzione porta all'implementazione più -efficiente, quello dell'uscita in caso di errore. -Il C però non consente di effettuare un salto ad una label definita in -un'altra funzione, per cui se l'errore avviene in funzioni profondamente -annidate occorre usare la funzione \func{longjump}. \section{La gestione di parametri e opzioni} @@ -724,7 +745,7 @@ questo modo il primo parametro \subsection{La gestione delle opzioni} \label{sec:proc_opt_handling} -In generale un programma unix riceve da linea di comando sia i parametri che +In generale un programma unix riceve da linea di comando sia gli argomenti che le opzioni, queste ultime sono standardizzate per essere riconosciute come tali: un elemento di \var{argv} che inizia con \texttt{-} e che non sia un singolo \texttt{-} o \texttt{--} viene considerato un'opzione. In in genere @@ -736,89 +757,67 @@ touch -r riferimento.txt -m questofile.txt \end{verbatim} ed in questo caso le opzioni sono \texttt{m} ed \texttt{r}. -Per gestire le opzioni all'interno dei parametri passati in \func{argv} le -librerie standard del C forniscono la funzione \func{getopt} che ha il -prototipo: +Per gestire le opzioni all'interno dei argomenti a linea di comando passati in +\func{argv} le librerie standard del C forniscono la funzione \func{getopt} +che ha il seguente prototipo: \begin{prototype}{unistd.h} {int getopt(int argc, char * const argv[], const char * optstring)} La funzione esegue il parsing degli argomenti passati da linea di comando riconoscendo le possibili opzioni segnalate con \var{optstring}. -Ritorna il carattere che segue l'opzione, \cmd{:} se manca un paramatro -all'opzione, \cmd{?} se l'opzione è sconosciuta, e -1 se non esistono altre +Ritorna il carattere che segue l'opzione, \cmd{':'} se manca un parametro +all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e -1 se non esistono altre opzioni. \end{prototype} -Questa funzione prende come argomenti le due variabili \var{argc} e -\var{argv} ed una stringa che indica quali sono le opzioni valide; la -funzione effettua la scansione della lista dei parametri ricercando ogni -stringa che comincia con \cmd{-} e ritorna ogni volta che trova una opzione -valida. +Questa funzione prende come argomenti le due variabili \var{argc} e \var{argv} +passate a \func{main} (vedi \secref{sec:proc_main}) ed una stringa che indica +quali sono le opzioni valide; la funzione effettua la scansione della lista +degli argomenti ricercando ogni stringa che comincia con \cmd{-} e ritorna ogni +volta che trova una opzione valida. La stringa \var{optstring} indica quali sono le opzioni riconosciute ed è costituita da tutti i caratteri usati per identificare le singole opzioni, se l'opzione ha un parametro al carattere deve essere fatto seguire un segno di -due punti \texttt{:} nel caso appena accennato ad esempio la stringa di -opzioni sarebbe \texttt{"r:m"}. - -La modalità di uso è pertanto quella di chiamare più volte la funzione -all'interno di un ciclo di while fintanto che essa non ritorna il valore -\texttt{-1} che indica che non ci sono più opzioni. Nel caso si incontri -un'opzione non dichiarata in \texttt{optstring} viene ritornato un \texttt{?} -mentre se l'opzione non è seguita da un parametro viene ritornato un -\texttt{:} infine se viene incontrato il valore \texttt{--} la scansione viene -considerata conclusa, anche se vi sono altri parametri che cominciano con -\texttt{-}. +due punti \var{':'}, nel caso appena accennato ad esempio la stringa di +opzioni sarebbe \var{"r:m"}. + +La modalità di uso di \func{getopt} è pertanto quella di chiamare più volte la +funzione all'interno di un ciclo fintanto che essa non ritorna il valore -1 +che indica che non ci sono più opzioni. Nel caso si incontri un'opzione non +dichiarata in \var{optstring} viene ritornato il carattere \texttt{'?'} +mentre se un opzione che lo richiede non è seguita da un parametro viene +ritornato il carattere \texttt{':'}, infine se viene incontrato il valore +\cmd{--} la scansione viene considerata conclusa, anche se vi sono altri +elementi di \var{argv} che cominciano con il carattere \texttt{'-'}. -Quando la funzione trova un'opzione essa ritorna il valore numerico del -carattere, in questo modo si possono prendere le azioni relative usando un -case; la funzione inizializza inoltre alcune variabili globali: -\begin{itemize} -\item \texttt{char * optarg} contiene il puntatore alla stringa argomento - dell'opzione. -\item \texttt{int optind} alla fine della scansione restituisce l'indice del - primo argomento che non è un'opzione. -\item \texttt{int opterr} previene, se posto a zero, la stampa di un messaggio - di errore in caso di riconoscimento di opzioni non definite. -\item \texttt{int optopt} contiene il carattere dell'opzione non riconosciuta. -\end{itemize} - -In \nfig\ è mostrato un programma di esempio: \begin{figure}[htbp] \footnotesize \begin{lstlisting}{} opterr = 0; /* don't want writing to stderr */ - while ( (i = getopt(argc, argv, "o:a:i:hve")) != -1) { + while ( (i = getopt(argc, argv, "hp:c:e:")) != -1) { switch (i) { - case 'i': /* input file */ - in_file=open(optarg,O_RDONLY); - if (in_file<0) { - perror("Cannot open input file"); - exit(1); - } - break; - case 'o': /* output file (overwrite) */ - out_file=open(optarg,O_WRONLY|O_CREAT); - if (out_file<0) { - perror("Cannot open output file"); - exit(1); - } + /* + * Handling options + */ + case 'h': /* help option */ + printf("Wrong -h option use\n"); + usage(); + return -1; break; - case 'a': /* output file (append) */ - out_file=open(optarg,O_WRONLY|O_CREAT|O_APPEND); + case 'c': /* take wait time for childen */ + wait_child = strtol(optarg, NULL, 10); /* convert input */ break; - case 'h': /* print help usage */ - usage(); + case 'p': /* take wait time for childen */ + wait_parent = strtol(optarg, NULL, 10); /* convert input */ break; - case 'v': /* set verbose mode */ - debug("Option -v active\n"); - verbose=1; + 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 */ - debug("default option\n"); usage(); } } @@ -828,13 +827,56 @@ In \nfig\ \label{fig:proc_options_code} \end{figure} +Quando la funzione trova un'opzione essa ritorna il valore numerico del +carattere, in questo modo si possono prendere le azioni relative usando uno +\func{switch}; la funzione inizializza inoltre alcune variabili globali: +\begin{itemize*} +\item \var{char * optarg} contiene il puntatore alla stringa parametro + dell'opzione. +\item \var{int optind} alla fine della scansione restituisce l'indice del + primo elemento di \var{argv} che non è un'opzione. +\item \var{int opterr} previene, se posto a zero, la stampa di un messaggio + di errore in caso di riconoscimento di opzioni non definite. +\item \var{int optopt} contiene il carattere dell'opzione non riconosciuta. +\end{itemize*} + +In \figref{fig:proc_options_code} è mostrata la sezione del programma +\file{ForkTest.c} (che useremo nel prossimo capitolo per effettuare dei test +sulla creazione dei processi) deputata alla decodifica delle opzioni a riga di +comando. + +Anzitutto si può notare che si è anzitutto (\texttt{\small 1}) disabilitata la +stampa di messaggi di errore per opzioni non riconosciute, per poi passare al +ciclo per la verifica delle opzioni (\texttt{\small 2-27}); per ciascuna delle +opioni possibili si è poi provveduto ad una opportuna azione, ad esempio per +le tre opzioni che prevedono un parametro si è effettuata la decodifica del +medesimo, il cui indirizzo è contenuto nella variabile \var{optarg}, +avvalorando la relativa variabile (\texttt{\small 12-14}, \texttt{\small + 15-17} e \texttt{\small 18-20}). Completato il ciclo troveremo in +\var{optind} l'indice in \var{argv[]} del primo degli argomenti a linea di +comando restanti. + +Normalmente \func{getopt} compie una permutazione degli elementi di \var{argv} +così che alla fine della scansione gli elementi che non sono opzioni sono +spostati in coda al vettore. Oltre a questa esistono altre due modalità di +gestire gli elementi di \var{argv}; se \var{optstring} inizia con il carattere +\texttt{'+'} (o è settata la variabile di ambiente \macro{POSIXLY\_CORRECT}) +la scansione viene fermata non appena si incontra un elemento che non è +un'opzione. L'ultima modalità, usata quando un programma può gestire la +mescolanza fra opzioni e argomenti, ma se li aspetta in un ordine definito, si +attiva quando \var{optstring} inizia con il carattere \texttt{'-'}. In questo +caso ogni elemento che non è un'opzione viene considerato comunque un'opzione +e associato ad un valore di ritorno pari ad 1, questo permette di identificare +gli elementi che non sono opzioni, ma non effettua il riordinamento del +vettore \var{argv}. + \subsection{Opzioni in formato esteso} \label{sec:proc_opt_extended} Un'estensione di questo schema è costituito dalle cosiddette -\textit{long-options} espresse nella forma \texttt{--option=parameter}, anche -la gestione di queste ultime è stata standardizzata attraverso l'uso di una +\textit{long-options} espresse nella forma \cmd{--option=parameter}, anche la +gestione di queste ultime è stata standardizzata attraverso l'uso di una versione estesa di \func{getopt}. (NdA: da finire). @@ -843,16 +885,16 @@ versione estesa di \func{getopt}. \subsection{Le variabili di ambiente} \label{sec:proc_environ} -Oltre ai parametri passati da linea di comando ogni processo riceve dal +Oltre agli argomenti passati a linea di comando ogni processo riceve dal sistema un \textsl{ambiente}, nella forma di una lista di variabili -(\textit{environment list}) messa a disposizione dal processo costruita nella -chiamata ad \func{exec} che lo ha lanciato. +(\textit{environment list}) messa a disposizione dal processo, e costruita +nella chiamata alla funzione \func{exec} quando questo viene lanciato. Come per la lista dei parametri anche questa lista è un array di puntatori a -caratteri, ciascuno dei quali punta ad una stringa (terminata da un null). A -differenza di \var{argv[]} però in questo caso non si ha la lunghezza -dell'array dato da un equivalente di \var{argc}, ma la lista è terminata da un -puntatore nullo. +caratteri, ciascuno dei quali punta ad una stringa (terminata da un +\macro{NULL}). A differenza di \var{argv[]} però in questo caso non si ha una +lunghezza dell'array data da un equivalente di \var{argc}, ma la lista è +terminata da un puntatore nullo. L'indirizzo della lista delle variabili di ambiente è passato attraverso la variabile globale \var{environ}, a cui si può accedere attraverso una semplice @@ -871,10 +913,11 @@ variabili che normalmente sono definite dal sistema, Per convenzione le stringhe che definiscono l'ambiente sono tutte del tipo \textsl{\texttt{nome=valore}}. Inoltre alcune variabili, come quelle elencate -in \curfig, sono definite dal sistema per queste c'è la convezione di usare -nomi espressi in caratteri maiuscoli. +in \curfig, sono definite dal sistema per essere usate da diversi programmi e +funzioni: per queste c'è l'ulteriore convezione di usare nomi espressi in +caratteri maiuscoli. -Il kernel non usa mai queste variabili, il loro uso e la loro intepretazione è +Il kernel non usa mai queste variabili, il loro uso e la loro interpretazione è riservata alle applicazioni e ad alcune funzioni di libreria; in genere esse costituiscono un modo comodo per definire un comportamento specifico senza dover ricorrere all'uso di opzioni a linea di comando o di file di @@ -889,11 +932,92 @@ l'editor preferito da invocare in caso di necessit Gli standard POSIX e XPG3 definiscono alcune di queste variabili (le più comuni), come riportato in \ntab. GNU/Linux le supporta tutte e ne definisce -anche altre per una lista parziale si può controllare \cmd{man environ}. - - - +anche altre: per una lista parziale si può controllare \cmd{man environ}. + + + + +\section{Problematiche di programmazione generica} +\label{sec:proc_gen_prog} + +Benché questo non sia un libro di C, è opportuno affrontare alcune delle +problematiche generali che possono emergere nella programmazione e di quali +precauzioni o accorgimenti occorre prendere per risolverle. Queste +problematiche non sono specifiche di sistemi unix-like o multitasking, ma +avendo trattato in questo capitolo il comportamento dei processi visti come +entità a se stanti, le riportiamo qui. + + +\subsection{Il passaggio delle variabili e dei valori di ritorno} +\label{sec:proc_var_passing} + +Una delle caratteristiche standard del C è che le variabili vengono passate +alle subroutine attraverso un meccanismo che viene chiamato \textit{by value} +(diverso ad esempio da quanto avviene con il Fortran, dove le variabli sono +passate, come suol dirsi, \textit{by reference}, o dal C++ dove la modalità del +passaggio può essere controllata con l'operatore \cmd{\&}). + +Il passaggio di una variabile \textit{by value} significa che in realtà quello +che viene passato alla subroutine è una copia del valore attuale di quella +variabile, copia che la subroutine potrà modificare a piacere, senza che il +valore originale nella routine chiamante venga toccato. In questo modo non +occorre preoccuparsi di eventuali effetti delle operazioni della subroutine +sulla variabile passata come parametro. + +Questo però va inteso nella maniera corretta. Il passaggio \textit{by value} +vale per qualunque variabile, puntatori compresi; quando però in una +subroutine si usano dei puntatori (ad esempio per scrivere in un buffer) in +realtà si va a modificare la zona di memoria a cui essi puntano, per cui anche +se i puntatori sono copie, i dati a cui essi puntano sono sempre gli stessi, e +le eventuali modifiche avranno effetto e saranno visibili anche nella routine +chiamante. + +Nella maggior parte delle funzioni di libreria e delle system call i puntatori +vengono usati per scambiare dati (attraverso buffer o strutture) e le +variabili semplici vengono usate per specificare parametri; in genere le +informazioni a riguardo dei risultati vengono passate alla routine chiamante +attraverso il valore di ritorno. È buona norma seguire questa pratica anche +nella programmazione normale. + + +Talvolta però è necessario che la funzione possa restituire indietro alla +funzione chiamante un valore relativo ad uno dei suoi parametri. Per far +questo si usa il cosiddetto \textit{value result argument}, si passa cioè, +invece di una normale variabile un puntatore; 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 +informazioni sulle dimensioni delle strutture degli indirizzi utilizzate, +viene usato questo meccanismo. + + +\subsection{Potenziali problemi con le variabili automatiche} +\label{sec:proc_auto_var} + +Uno dei possibili problemi che si possono avere con le subroutine è quello di +restituire alla funzione chiamante dei dati che sono contenuti in una +variabile automatica. Ovviamente quando la subroutine ritorna la sezione +dello stack che conteneva la variabile automatica potrà essere riutilizzata da +una nuova funzione, con le conseguenze immaginabili di sovrapposizione. + +Per questo una delle regole fondamentali della programmazione in C è che +all'uscita di una funzione non deve restare nessun riferimento a variabili +locali di quella funzione; qualora necessiti di utilizzare variabili che +possano essere viste anche dalla funzione chiamante queste devono essere +allocate esplicitamente, o in maniera statica (usando variabili di tipo +\type{static} o \type{extern}), o dinamicamente con una delle funzioni della +famiglia \func{malloc}. + +\subsection{Il controllo di flusso non locale} +\label{sec:proc_longjmp} +Il controllo del flusso di un programma in genere viene effettuato con le +varie istruzioni del linguaggio C, la più bistrattata delle quali è il +\func{goto}, ampiamente deprecato in favore di costrutti più puliti; esiste +però un caso in l'uso di questa istruzione porta all'implementazione più +efficiente, quello dell'uscita in caso di errore. +Il C però non consente di effettuare un salto ad una label definita in +un'altra funzione, per cui se l'errore avviene in funzioni profondamente +annidate occorre usare la funzione \func{longjump}.