X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=process.tex;h=d436a4fa963e55375a4a207fd6b2a6c87b67ac54;hp=dae486ffe1efc64812c09dd5dec1c863c094ed2e;hb=c6bb1ae340cad082718e43163b9595608ed123e1;hpb=ae7699cee1a9b906265387f78a08bc64da553b01 diff --git a/process.tex b/process.tex index dae486f..d436a4f 100644 --- a/process.tex +++ b/process.tex @@ -9,7 +9,7 @@ richiedere servizi al sistema, su cosa deve fare quando ha finito la sua esecuzione. In genere un programma viene eseguito quando un processo lo fa partire -eseguendo una funzione della famiglia \texttt{exec}; torneremo su questo e +eseguendo una funzione della famiglia \func{exec}; torneremo su questo e sulla la creazione e gestione dei processi nel prossimo capitolo, in questo affronteremo l'avvio e il funzionamento di un singolo processo partendo dal punto di vista del programma posto in esecuzione. @@ -32,25 +32,25 @@ posto in esecuzione esso apparir discorso dei \textit{thread} comunque in Linux necessita di una trattazione a parte per la peculiarità dell'implementazione). -\section{La funzione \texttt{main}} +\subsection{La funzione \func{main}} \label{sec:proc_main} Quando un programma viene lanciato il kernel esegue una opportuna routine di -avvio, usando il programma \texttt{ld-linux.so}, è questo programma che prima +avvio, usando il programma \cmd{ld-linux.so}, è questo programma che prima carica le librerie condivise che servono al programma, effettua il link dinamico del codice e poi alla fine lo esegue. Infatti, a meno di non aver specificato il flag \texttt{-static} durante la compilazione, tutti i programmi in Linux sono incompleti e necessitano di essere linkati alle librerie condivise quando vengono avviati. La procedura è controllata da -alcune variabili di ambiente e dal contenuto di \texttt{/etc/ld.so.conf}, i -dettagli sono riportati nella man page di \texttt{ld.so}. +alcune variabili di ambiente e dal contenuto di \file{/etc/ld.so.conf}, i +dettagli sono riportati nella man page di \cmd{ld.so}. -Il sistema fa partire qualunque programma chiamando la funzione \texttt{main}; +Il sistema fa partire qualunque programma chiamando la funzione \func{main}; sta al programmatore chiamare così la funzione principale del programma da cui si suppone iniziale l'esecuzione; in ogni caso senza questa funzione lo stesso linker darebbe luogo ad errori. -Lo standard ISO C specifica che la funzione \texttt{main} può non avere +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]{} @@ -58,29 +58,29 @@ linea di comando, in sostanza un prototipo che va sempre bene \end{lstlisting} In realtà nei sistemi unix esiste un'altro modo per definire la funzione -\texttt{main}, che prevede la presenza di un terzo parametro, \texttt{char +\func{main}, che prevede la presenza di un terzo parametro, \var{char *envp[]}, che fornisce l'\textsl{ambiente} (vedi \secref{sec:proc_environ}) del programma; questa forma però non è prevista dallo standard POSIX.1 per cui se si vogliono scrivere programmi portabili è meglio evitarla. \subsection{Come chiudere un programma} -\label{sec:proc_termination} +\label{sec:proc_conclusion} -La via normale per la quale un programma finisce è quando la funzione main -ritorna, una modalità equivalente di conclusione è quella di chiamare -direttamente la funzione \texttt{exit} (che viene comunque chiamata dalla -routine di avvio del programma quando la funzione main ritorna). Una forma -alternativa è quella di chiamare direttamente la system call \texttt{\_exit} -che passa il controllo direttamente al kernel. +La via normale per la quale un programma finisce è quando la funzione +\func{main} ritorna, una modalità equivalente di conclusione è quella di +chiamare direttamente la funzione \func{exit} (che viene comunque chiamata +dalla routine di avvio del programma quando la funzione \func{main} ritorna). +Una forma alternativa è quella di chiamare direttamente la system call +\func{\_exit} che passa il controllo direttamente al kernel. Oltre alla conclusione ``normale'' esiste anche la possibilità di una conclusione ``anomala'' del programma a causa di segnali o della chiamata alla -funzione \texttt{abort} (che comunque genera un segnale che termina il -programma); torneremo su questo in \secref{sec:sig_prog_error}. +funzione \func{abort} (che comunque genera un segnale che termina il +programma); torneremo su questo in \secref{sec:proc_termination}. Il valore di ritorno della funzione main, o quello usato nelle chiamate ad -\texttt{exit} e \texttt{\_exit}, viene chiamato \textit{exit status} e passato +\func{exit} e \func{\_exit}, viene chiamato \textit{exit status} e passato al processo padre che aveva lanciato il programma (in genere la shell). In generale si usa questo valore per fornire un'informazione generica sulla riuscita o il fallimento del programma; l'informazione è necessariamente @@ -88,11 +88,11 @@ generica, ed il valore deve essere compreso fra 0 e 255. In generale si usa la convenzione di restituire 0 in caso di successo e 1 in caso di fallimento, i programmi che effettuano dei confronti (come -\texttt{diff}) usano invece una notazione leggermente diversa, usando 0 per +\cmd{diff}) usano invece una notazione leggermente diversa, usando 0 per indicare la corrispondenza, 1 per indicare la non corrispondenza e 2 per indicare l'incapacità di effettuare il confronto. È opportuno adottare una di queste convenzioni a seconda dei casi. Si tenga presente che se si raggiunge -la fine della funzione \texttt{main} senza ritornare esplicitamente si ha un +la fine della funzione \func{main} senza ritornare esplicitamente si ha un valore di uscita indefinito, è pertanto consigliabile di concludere sempre in maniera esplicita detta funzione. @@ -102,13 +102,13 @@ programma in un sottoprocesso. Bench universalmente seguita è una buona idea tenerne conto. Si tenga presente inoltre che non è una buona idea usare il valore dell'errore -restituito dalla variabile \texttt{errno} come stato di uscita, in generale +restituito dalla variabile \var{errno} come stato di uscita, in generale una shell non si cura di tutto questo e comunque il valore dello stato di uscita è sempre troncato ad 8 bit, per cui si potrebbe incorrere nel caso in cui l'errore 256, diventando zero, verrebbe interpretato come un successo. In -\texttt{stdlib.h} sono definite due macro \texttt{EXIT\_SUCCESS} e -\texttt{EXIT\_FAILURE}, che in Linux sono poste rispettivamente ai valori 0 e -1 (di tipo \texttt{int}), seguendo lo standard POSIX. +\file{stdlib.h} sono definite due macro \macro{EXIT\_SUCCESS} e +\macro{EXIT\_FAILURE}, che in Linux sono poste rispettivamente ai valori 0 e +1 (di tipo \type{int}), seguendo lo standard POSIX. Infine occorre distinguere fra lo stato di uscita di un programma (l'\textit{exit status}) e lo stato di conclusione di un processo (il @@ -116,54 +116,54 @@ Infine occorre distinguere fra lo stato di uscita di un programma possibile un processo possa essere terminato (da un segnale) prima che il programma in esecuzione si sia concluso. In caso di conclusione normale del programma però lo stato di uscita diventa parte dello stato di conclusione del -processo (vedi \secref{sec:prochand_xxx}). +processo (vedi \secref{sec:proc_termination}). -\subsection{Le funzioni \texttt{exit} e \texttt{\_exit}} +\subsection{Le funzioni \func{exit} e \func{\_exit}} \label{sec:proc_exit} Come accennato funzioni per l'uscita ``normale'' da un programma sono due, la -prima è la funzione \texttt{exit} che è definita dallo standard ANSI C; il +prima è la funzione \func{exit} che è definita dallo standard ANSI C; il prototipo della funzione è il seguente: \begin{prototype}{stdlib.h}{void exit(int status)} Causa la conclusione ordinaria del programma restituendo il valore - \texttt{status} al processo padre. + \var{status} al processo padre. La funzione non ritorna. Il processo viene terminato \end{prototype} -La funzione \texttt{exit} è pensata per una conclusione pulita di un programma +La funzione \func{exit} è pensata per una conclusione pulita di un programma che usa le librerie standard del C; essa esegue tutte le funzioni che sono -state registrate con \texttt{atexit} e \texttt{on\_exit} (vedi +state registrate con \func{atexit} e \func{on\_exit} (vedi \secref{sec:proc_atexit}), e chiude tutti gli stream di I/O effettuando il -salvataggio dei dati sospesi (chiamando \texttt{fclose}, vedi -\secref{sec:filestd_close}), infine ripassa il controllo al kernel chiamando -\texttt{\_exit} e passando il valore \texttt{status} come stato di uscita. +salvataggio dei dati sospesi (chiamando \func{fclose}, vedi +\secref{sec:file_fclose}), infine ripassa il controllo al kernel chiamando +\func{\_exit} e passando il valore \var{status} come stato di uscita. -La system call \texttt{\_exit} restituisce direttamente il controllo al +La system call \func{\_exit} restituisce direttamente il controllo al kernel, concludendo immediatamente il processo, le eventuali funzioni -registrate con \texttt{atexit} e \texttt{on\_exit} non vengono eseguite. Il +registrate con \func{atexit} e \func{on\_exit} non vengono eseguite. Il prototipo della funzione è il seguente: \begin{prototype}{unistd.h}{void \_exit(int status)} Causa la conclusione immediata del programma restituendo il valore - \texttt{status} al processo padre. + \var{status} al processo padre. La funzione non ritorna. Il processo viene terminato. \end{prototype} La funzione chiude tutti i file descriptor appartenenti al processo (sui tenga presente che questo non comporta il salvataggio dei dati bufferizzati degli -stream), fa si che ogni figlio del processo sia ereditato da \texttt{init} -(vedi \secref{cha:process_handling}), manda un segnale \texttt{SIGCHLD} al +stream), fa si che ogni figlio del processo sia ereditato da \cmd{init} +(vedi \secref{cha:process_handling}), manda un segnale \macro{SIGCHLD} al processo padre (vedi \ref{sec:sig_job_control}) ed infine ritorna lo stato di -uscita specificato in \texttt{status} che può essere raccolto usando la -funzione \texttt{wait} (vedi \secref{sec:prochand_wait}). +uscita specificato in \var{status} che può essere raccolto usando la +funzione \func{wait} (vedi \secref{sec:proc_wait}). -\subsection{Le funzioni \texttt{atexit} e \texttt{on\_exit}} +\subsection{Le funzioni \func{atexit} e \func{on\_exit}} \label{sec:proc_atexit} -Come accennato l'uso di \texttt{exit} al posto della \texttt{\_exit} è fatto +Come accennato l'uso di \func{exit} al posto della \func{\_exit} è fatto principalmente per permettere una uscita pulita dalle funzioni delle librerie standard del C (in particolare per quel che riguarda la chiusura degli stream). @@ -177,10 +177,10 @@ di 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 \textit{exit} che per il ritorno di \texttt{main}). La prima +la chiamata ad \func{exit} che per il ritorno di \func{main}). La prima funzione che si può utilizzare a tal fine è: \begin{prototype}{stdlib.h}{void atexit(void (*function)(void))} - Registra la funzione \texttt{function} per essere chiamata all'uscita dal + Registra la funzione \var{function} per essere chiamata all'uscita dal programma. La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, @@ -189,28 +189,28 @@ funzione che si pu La funzione richiede come argomento l'indirizzo della opportuna da chiamare all'uscita che non deve prendere argomenti e non deve ritornare niente. Una -estensione di \texttt{atexit} è la funzione \texttt{on\_exit} (che la glibc +estensione di \func{atexit} è la funzione \func{on\_exit} (che la glibc include per compatibilità con SunOS e che non è detto sia definita su altri sistemi), il cui prototipo è: \begin{prototype}{stdlib.h} {void on\_exit(void (*function)(int status, void *arg), void *arg)} - Registra la funzione \texttt{function} per essere chiamata all'uscita dal + Registra la funzione \var{function} per essere chiamata all'uscita dal programma. Tutte le funzioni registrate vengono chiamate in ordine inverso rispetto a quello di registrazione. La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, - \texttt{errno} non viene settata. + \var{errno} non viene settata. \end{prototype} In questo caso la funzione da chiamare prende due parametri, il primo dei quali sarà inizializzato allo stato di uscita con cui è stata chiamata -\texttt{exit} ed il secondo al puntatore generico specificato come secondo -argomento nella chiamata di \texttt{on\_exit}. +\func{exit} ed il secondo al puntatore generico specificato come secondo +argomento nella chiamata di \func{on\_exit}. Nella sequenza di chiusura tutte le funzioni registrate verranno chiamate in ordine inverso rispetto a quello di registrazione (ed una stessa funzione registrata più volte sarà chiamata più volte); poi verranno chiusi tutti gli -stream aperti, infine verrà chiamata \texttt{\_exit}. +stream aperti, infine verrà chiamata \func{\_exit}. \subsection{Conclusioni} @@ -218,14 +218,14 @@ stream aperti, infine verr Data l'importanza dell'argomento è opportuno sottolineare ancora una volta che in un sistema unix l'unico modo in cui un programma può essere eseguito dal -kernel è attraverso la chiamata alla system call \texttt{execve} (in genere -attraverso una delle funzioni \texttt{exec} che vedremo in -\secref{sec:prochand_exec}). +kernel è attraverso la chiamata alla system call \func{execve} (in genere +attraverso una delle funzioni \func{exec} che vedremo in +\secref{sec:proc_exec}). Allo stesso modo l'unico modo in cui un programma può concludere volontariamente la sua esecuzione è attraverso una chiamata alla system call -\texttt{\_exit} sia esplicitamente o che in maniera indiretta attraverso l'uso -di \texttt{exit} o il ritorno della funzione \texttt{main}. +\func{\_exit} sia esplicitamente o che in maniera indiretta attraverso l'uso +di \func{exit} o il ritorno della funzione \func{main}. Lo schema delle modalità con cui si avvia e conclude normalmente un programma è riportato in \nfig. @@ -279,7 +279,7 @@ 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 accade in genere per le pagine che contengono il codice delle librerie -condivise). Ad esempio il codice della funzione \texttt{printf} starà su una +condivise). Ad esempio il codice della funzione \func{printf} starà su una sola pagina di memoria reale che farà da supporto a tutte le pagine di memoria virtuale di tutti i processi hanno detta funzione nel loro codice. @@ -322,7 +322,7 @@ commette quando si chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o scrivere da un indirizzo per il quale non esiste una associazione della pagina virtuale il kernel risponde al relativo \textit{page fault}, mandando un -segnale \texttt{SIGSEGV} al processo, che normalmente ne causa la terminazione +segnale \macro{SIGSEGV} al processo, che normalmente ne causa la terminazione immediata. È pertanto importante capire come viene strutturata la memoria virtuale di un @@ -337,7 +337,7 @@ programma C viene suddiviso nei seguenti segmenti: utilizzarlo, e viene marcato in sola lettura per evitare sovrascritture accidentali (o maliziose) che ne modifichino le istruzioni. - Viene allocato da \texttt{exec} all'avvio del programma e resta invariato + Viene allocato da \func{exec} all'avvio del programma e resta invariato per tutto il tempo dell'esecuzione. \item Il segmento dei dati (\textit{data segment}). Contiene le variabili @@ -351,7 +351,7 @@ programma C viene suddiviso nei seguenti segmenti: double pi = 3.14; \end{lstlisting} questo valore sarà immagazzinato in questo segmento. La memoria di questo - segmento viene preallocato dalla \texttt{exec} e inizializzata ai valori + segmento viene preallocato dalla \func{exec} e inizializzata ai valori specificati. La seconda parte è il segmento dei dati non inizializzati, che contiene le @@ -362,7 +362,7 @@ programma C viene suddiviso nei seguenti segmenti: \end{lstlisting} questo valore sarà immagazzinato in questo segmento. Anch'esso viene allocato all'avvio, e tutte le variabili vengono inizializzate a - zero (ed i puntatori a \texttt{NULL}). + zero (ed i puntatori a \macro{NULL}). Storicamente questo segmento viene chiamato BBS (da \textit{block started by symbol}. La sua dimensione è fissa. @@ -394,7 +394,7 @@ programma C viene suddiviso nei seguenti segmenti: \end{figure} Una disposizione tipica di questi segmenti è riportata in \nfig. Usando il -comando \texttt{size} su un programma se ne può stampare le dimensioni dei +comando \cmd{size} su un programma se ne può stampare le dimensioni dei segmenti di testo e di dati (inizializzati e BSS); il BSS però non è mai salvato sul file, in quanto viene inizializzato a zero al caricamento del programma. @@ -407,7 +407,7 @@ Il C supporta due tipi di allocazione della memoria, l'allocazione statica quella in cui vanno le variabili globali e le variabili statiche (e viene effettuata nel segmento dei dati), lo spazio per queste variabili viene allocati all'avvio del programma (come parte delle operazioni svolte da -\texttt{exec}) e non viene liberato fino alla sua conclusione. +\func{exec}) e non viene liberato fino alla sua conclusione. L'allocazione automatica è quella che avviene per le cosiddette variabili automatiche, cioè gli argomenti delle funzioni o le variabili locali. Lo @@ -425,12 +425,12 @@ cio possano essere modificate durante l'esecuzione del programma; però le librerie del C forniscono una serie opportuna di funzioni per permettere l'allocazione dinamica di spazio in memoria (in genere nello heap, usando la system call -\texttt{sbrk}), solo che a questo punto detto spazio sarà accessibile solo in +\func{sbrk}), solo che a questo punto detto spazio sarà accessibile solo in maniera indiretta attraverso dei puntatori. -\subsection{Le funzioni \texttt{malloc}, \texttt{calloc}, \texttt{realloc} e - \texttt{free}} +\subsection{Le funzioni \func{malloc}, \func{calloc}, \func{realloc} e + \func{free}} \label{sec:proc_mem_malloc} Le funzioni previste dallo standard ANSI C per la gestione della memoria sono @@ -438,26 +438,26 @@ quattro, i prototipi sono i seguenti: \begin{functions} \headdecl{stdlib.h} \funcdecl{void *calloc(size\_t size)} - Alloca \texttt{size} bytes nello heap. La memoria viene inizializzata a 0. + Alloca \var{size} bytes nello heap. La memoria viene inizializzata a 0. La funzione restituisce il puntatore alla 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}. + 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 \texttt{size} bytes nello heap. La memoria non viene inizializzata. + Alloca \var{size} bytes nello heap. La memoria non viene inizializzata. La funzione restituisce il puntatore alla 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}. + 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 \texttt{ptr} - portandola a \texttt{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 \texttt{NULL} in caso di fallimento, nel qual caso - \texttt{errno} viene settata a \texttt{ENOMEM}. + 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 \texttt{ptr}. + Disalloca lo spazio di memoria puntato da \var{ptr}. La funzione non ritorna nulla. \end{functions} @@ -466,29 +466,29 @@ sempre correttamente allineato per tutti i tipi di dati; ad esempio sulle macchine a 32 bit in genere è allineato a multipli di 4 byte e sulle macchine a 64 bit a multipli di 8 byte. -In genere su usano le funzioni \texttt{malloc} e \texttt{calloc} per allocare +In genere su usano le funzioni \func{malloc} e \func{calloc} per allocare dinamicamente la memoria necessaria al programma, siccome i puntatori ritornati sono di tipo generico non è necessario effettuare un cast per assegnarli a puntatori al tipo di variabile per la quale si effettua la allocazione. La memoria allocata dinamicamente deve essere esplicitamente rilasciata usando -\texttt{free}\footnote{le glibc provvedono anche una funzione \texttt{cfree} +\func{free}\footnote{le glibc provvedono anche una funzione \func{cfree} defininita 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 -\texttt{free}, in caso contrario il comportamento della funzione è indefinito. +\func{free}, in caso contrario il comportamento della funzione è indefinito. -La funzione \texttt{realloc} si usa invece per cambiare (in genere aumentare) +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 -\texttt{malloc} (se è passato un valore \texttt{NULL} allora la funzione si -comporta come \texttt{malloc}\footnote{questo è vero per linux e +\func{malloc} (se è passato un valore \macro{NULL} allora la funzione si +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 \texttt{realloc} anche per un puntatore liberato con - \texttt{free} purché non ci fossero state altre chiamate a funzioni di + 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 vettore; in questo caso se è disponibile dello spazio adiacente al precedente @@ -503,20 +503,26 @@ essere altri puntatori che puntino all'interno di un'area che si vuole ridimensionare. Uno degli errori più comuni (specie se si ha a che fare con array di -puntatori) è infatti quello di chiamare \texttt{free} più di una volta sullo +puntatori) è infatti quello di chiamare \func{free} più di una volta sullo stesso puntatore; per evitare questo problema una soluzione di ripiego è -quella di assegnare sempre a \texttt{NULL} ogni puntatore liberato con -\texttt{free}, dato che, quando il parametro è un puntatore nullo, -\texttt{free} non esegue nessuna operazione. +quella di assegnare sempre a \macro{NULL} ogni puntatore liberato con +\func{free}, dato che, quando il parametro è un puntatore nullo, +\func{free} non esegue nessuna operazione. Linux e le glibc hanno una implementazione delle routine di allocazione che è controllabile dall'utente attraverso alcune variabili di ambiente, in particolare diventa possibile tracciare questo tipo di errori usando la -variabile \texttt{MALLOC\_CHECK\_} che quando viene settata mette in uso una +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 \texttt{free}; in -particolare se la variabile è posta a zero gli errori vengono ignorati, se è -posta ad 1 viene stampato un avviso sullo standard error e se +confronti di piccoli errori come quello di chiamate doppie a \func{free}; in +particolare: +\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} 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 @@ -698,7 +704,7 @@ annidate occorre usare la funzione \func{longjump}. Il passaggio dei parametri e delle variabili di ambiente dalla riga di comando al singolo programma quando viene lanciato è effettuato attraverso le -variabili \texttt{argc}, \texttt{argv} che vengono passate al programma +variabili \var{argc}, \var{argv} che vengono passate al programma come argomenti della funzione principale. \subsection{Il formato dei parametri} @@ -710,9 +716,9 @@ ciascuna delle quali viene considerata un parametro; di default per individuare le parole viene usato come separatore lo spazio (comportamento modificabile attraverso il settaggio della variabile di ambiente IFS). -Nella scansione viene costruito il vettore di puntatori \texttt{argv} inserendo +Nella scansione viene costruito il vettore di puntatori \var{argv} inserendo in successione il puntatore alla stringa costituente l'$n$-simo parametro; la -variabile \texttt{argc} viene inizializzata al numero di parametri trovati, in +variabile \var{argc} viene inizializzata al numero di parametri trovati, in questo modo il primo parametro è sempre il nome del programma (vedi \nfig). \subsection{La gestione delle opzioni} @@ -720,7 +726,7 @@ questo modo il primo parametro In generale un programma unix riceve da linea di comando sia i parametri che le opzioni, queste ultime sono standardizzate per essere riconosciute come -tali: un elemento di \texttt{argv} che inizia con \texttt{-} e che non sia un +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 le opzioni sono costituite da una lettera preceduta dal meno e possono avere o no un parametro associato; un comando tipico può essere cioè qualcosa del @@ -730,20 +736,26 @@ 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 \texttt{argv} le -librerie standard del C forniscono la funzione \texttt{getopt} (accessibile -includendo \texttt{unistd.h}), che ha il prototipo: -\begin{verbatim} -int getopt(int argc, char * const argv[], const char * optstring); -\end{verbatim} +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: +\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 +opzioni. +\end{prototype} -Questa funzione prende come argomenti le due variabili \texttt{argc} e -\texttt{argv} ed una stringa che indica quali sono le opzioni valide; la +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 \texttt{-} e ritorna ogni volta che trova una opzione +stringa che comincia con \cmd{-} e ritorna ogni volta che trova una opzione valida. -La stringa \texttt{optstring} indica quali sono le opzioni riconosciute ed è +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 @@ -755,7 +767,8 @@ all'interno di un ciclo di while fintanto che essa non ritorna il valore 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. +considerata conclusa, anche se vi sono altri parametri che cominciano con +\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 @@ -770,8 +783,7 @@ case; la funzione inizializza inoltre alcune variabili globali: \item \texttt{int optopt} contiene il carattere dell'opzione non riconosciuta. \end{itemize} -In \nfig\ è mostrato un programma di esempio, - +In \nfig\ è mostrato un programma di esempio: \begin{figure}[htbp] \footnotesize \begin{lstlisting}{} @@ -823,8 +835,9 @@ In \nfig\ 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 -versione estesa di \texttt{getopt}. +versione estesa di \func{getopt}. +(NdA: da finire). \subsection{Le variabili di ambiente} \label{sec:proc_environ} @@ -878,4 +891,3 @@ 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} -