X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=process.tex;h=d3e98e435f9a2e6df9fbd963e085c3f9bfb4088f;hp=3069d292982dddf97840eb29484c09a5d403ca41;hb=ff2d0141751ed62ef56e5bfd226c589311b8b669;hpb=46029a05c9009df38022e82b0f20732290388ef1 diff --git a/process.tex b/process.tex index 3069d29..d3e98e4 100644 --- a/process.tex +++ b/process.tex @@ -64,7 +64,7 @@ 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 -\func{main}, che prevede la presenza di un terzo parametro, \var{char +\func{main}, che prevede la presenza di un terzo parametro, \code{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. @@ -125,11 +125,10 @@ valori di tipo \ctyp{int} 0 e 1. \label{sec:proc_exit} Come accennato le funzioni usate per effettuare un'uscita ``normale'' da un -programma sono due, la prima è la funzione \func{exit} che è definita dallo +programma sono due, la prima è la funzione \funcd{exit}, che è definita dallo standard ANSI C ed il cui prototipo è: \begin{prototype}{stdlib.h}{void exit(int status)} - Causa la conclusione ordinaria del programma restituendo il valore - \var{status} al processo padre. + Causa la conclusione ordinaria del programma. \bodydesc{La funzione non ritorna. Il processo viene terminato.} \end{prototype} @@ -140,15 +139,14 @@ che sono state registrate con \func{atexit} e \func{on\_exit} (vedi \secref{sec:proc_atexit}), e chiude tutti gli stream effettuando il salvataggio dei dati sospesi (chiamando \func{fclose}, vedi \secref{sec:file_fopen}), infine passa il controllo al kernel chiamando -\func{\_exit} e passando \param{status} come stato di uscita. +\func{\_exit} e restituendo il valore di \param{status} come stato di uscita. -La system call \func{\_exit} restituisce direttamente il controllo al kernel, +La system call \funcd{\_exit} restituisce direttamente il controllo al kernel, concludendo immediatamente il processo; i dati sospesi nei buffer degli stream non vengono salvati e le eventuali funzioni registrate con \func{atexit} e \func{on\_exit} non vengono eseguite. Il prototipo della funzione è: \begin{prototype}{unistd.h}{void \_exit(int status)} - Causa la conclusione immediata del programma restituendo \param{status} al - processo padre come stato di uscita. + Causa la conclusione immediata del programma. \bodydesc{La funzione non ritorna. Il processo viene terminato.} \end{prototype} @@ -179,37 +177,37 @@ 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 è: +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 essere chiamata all'uscita dal - programma. + Registra la funzione \param{function} per la chiamata all'uscita dal + programma. \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, \var{errno} non viene modificata.} \end{prototype} -\noindent la funzione richiede come argomento l'indirizzo della opportuna -funzione di pulizia da chiamare all'uscita, che non deve prendere argomenti e -non deve ritornare niente (deve essere essere cioè definita come \code{void - function(void)}). +\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)}). -Un'estensione di \func{atexit} è la funzione \func{on\_exit}, che le +Un'estensione di \func{atexit} è la funzione \funcd{on\_exit}, che le \acr{glibc} includono per compatibilità con SunOS, ma che non è detto sia definita su altri sistemi; il suo prototipo è: \begin{prototype}{stdlib.h} -{void on\_exit(void (*function)(int status, void *arg), void *arg)} - Registra la funzione \param{function} per essere chiamata all'uscita dal - programma. Tutte le funzioni registrate vengono chiamate in ordine inverso - rispetto a quello di registrazione. +{void on\_exit(void (*function)(int , void *), void *arg)} + Registra la funzione \param{function} per la chiamata all'uscita dal + programma. \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, \var{errno} non viene modificata.} \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 -\func{exit} ed il secondo al puntatore generico specificato come secondo -argomento nella chiamata di \func{on\_exit}. Così diventa possibile passare -dei dati alla funzione di chiusura. +In questo caso la funzione da chiamare all'uscita prende i due parametri +specificati nel prototipo, dovrà cioè essere definita come \code{void + function(int status, void *argp)}. Il primo argomento sarà inizializzato +allo stato di uscita con cui è stata chiamata \func{exit} ed il secondo al +puntatore \param{arg} passato come secondo argomento di \func{on\_exit}. Così +diventa possibile passare dei dati alla funzione di chiusura. Nella sequenza di chiusura tutte le funzioni registrate verranno chiamate in ordine inverso rispetto a quello di registrazione (ed una stessa funzione @@ -268,7 +266,7 @@ la cosiddetta \textsl{memoria virtuale}\index{memoria virtuale} che consiste nell'assegnare ad ogni processo uno spazio virtuale di indirizzamento lineare, in cui gli indirizzi vanno da zero ad un qualche valore massimo.\footnote{nel caso di Linux fino al kernel 2.2 detto massimo era, per macchine a 32bit, di - 2Gb, con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite + 2Gb. Con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite è stato esteso.} Come accennato in \capref{cha:intro_unix} questo spazio di indirizzi è @@ -318,8 +316,8 @@ a tempi molto pi Normalmente questo è il prezzo da pagare per avere un multitasking reale, ed in genere il sistema è molto efficiente in questo lavoro; quando però ci siano esigenze specifiche di prestazioni è possibile usare delle funzioni che -permettono di bloccare il meccanismo della paginazione e mantenere fisse delle -pagine in memoria (vedi \ref{sec:proc_mem_lock}). +permettono di bloccare il meccanismo della paginazione\index{paginazione} e +mantenere fisse delle pagine in memoria (vedi \ref{sec:proc_mem_lock}). \subsection{La struttura della memoria di un processo} @@ -458,31 +456,31 @@ attraverso dei puntatori. \label{sec:proc_mem_malloc} Le funzioni previste dallo standard ANSI C per la gestione della memoria sono -quattro: \func{malloc}, \func{calloc}, \func{realloc} e \func{free}, i loro -prototipi sono i seguenti: +quattro: \funcd{malloc}, \funcd{calloc}, \funcd{realloc} e \funcd{free}, i +loro prototipi sono i seguenti: \begin{functions} \headdecl{stdlib.h} \funcdecl{void *calloc(size\_t size)} - Alloca \var{size} byte nello heap. La memoria viene inizializzata a 0. + Alloca \param{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 \val{NULL} in caso di fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}. \funcdecl{void *malloc(size\_t size)} - Alloca \var{size} byte nello heap. La memoria non viene inizializzata. + Alloca \param{size} byte nello heap. La memoria non viene inizializzata. La funzione restituisce il puntatore alla zona di memoria allocata in caso di successo e \val{NULL} in caso di fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}. \funcdecl{void *realloc(void *ptr, size\_t size)} - Cambia la dimensione del blocco allocato all'indirizzo \var{ptr} - portandola a \var{size}. + Cambia la dimensione del blocco allocato all'indirizzo \param{ptr} + portandola a \param{size}. La funzione restituisce il puntatore alla zona di memoria allocata in caso di successo e \val{NULL} in caso di fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}. \funcdecl{void free(void *ptr)} - Disalloca lo spazio di memoria puntato da \var{ptr}. + Disalloca lo spazio di memoria puntato da \param{ptr}. La funzione non ritorna nulla e non riporta errori. \end{functions} @@ -529,7 +527,7 @@ spazio aggiunto non viene inizializzato. Si deve sempre avere ben presente il fatto che il blocco di memoria restituito da \func{realloc} può non essere un'estensione di quello che gli si è passato in ingresso; per questo si dovrà \emph{sempre} eseguire la riassegnazione di -\var{ptr} al valore di ritorno della funzione, e reinizializzare o provvedere +\param{ptr} al valore di ritorno della funzione, e reinizializzare o provvedere ad un adeguato aggiornamento di tutti gli altri puntatori all'interno del blocco di dati ridimensionato. @@ -618,20 +616,22 @@ molto complesse riguardo l'allocazione della memoria. Una possibile alternativa all'uso di \func{malloc}, che non soffre dei problemi di \textit{memory leak} descritti in precedenza, è la funzione -\func{alloca}, che invece di allocare la memoria nello heap usa il segmento di -stack della funzione corrente. La sintassi è identica a quella di +\funcd{alloca}, che invece di allocare la memoria nello heap usa il segmento +di stack della funzione corrente. La sintassi è identica a quella di \func{malloc}, il suo prototipo è: \begin{prototype}{stdlib.h}{void *alloca(size\_t size)} - Alloca \var{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 - di successo e \val{NULL} in caso di fallimento, nel qual caso - \var{errno} assumerà il valore \errval{ENOMEM}. + Alloca \param{size} byte nello stack. + + \bodydesc{La funzione restituisce il puntatore alla zona di memoria allocata + in caso di successo e \val{NULL} in caso di fallimento, nel qual caso + \var{errno} assumerà il valore \errval{ENOMEM}.} \end{prototype} -\noindent ma in questo caso non è più necessario liberare la memoria (e quindi -non esiste un analogo della \func{free}) in quanto essa viene rilasciata -automaticamente al ritorno della funzione. + +La funzione alloca la quantità di memoria (non inizializzata) richiesta +dall'argomento \param{size} nel segmento di stack della funzione chiamante. +Con questa funzione non è più necessario liberare la memoria allocata (e +quindi non esiste un analogo della \func{free}) in quanto essa viene +rilasciata automaticamente al ritorno della funzione. Come è evidente questa funzione ha molti vantaggi, anzitutto permette di evitare alla radice i problemi di memory leak, dato che non serve più la @@ -670,33 +670,43 @@ cui torneremo in \secref{sec:proc_auto_var}. \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. I loro prototipi sono: -\begin{functions} - \headdecl{unistd.h} - \funcdecl{int brk(void *end\_data\_segment)} - Sposta la fine del segmento dei dati all'indirizzo specificato da - \var{end\_data\_segment}. +Queste due funzioni vengono utilizzate soltanto quando è necessario effettuare +direttamente la gestione della memoria associata allo spazio dati di un +processo, ad esempio qualora si debba implementare la propria versione delle +routine di allocazione della memoria viste in \secref{sec:proc_mem_malloc}. La +prima funzione è \funcd{brk}, ed il suo prototipo è: +\begin{prototype}{unistd.h}{int brk(void *end\_data\_segment)} + Sposta la fine del segmento dei dati. - La funzione restituisce 0 in caso di successo e -1 in caso di - fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}. + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}.} +\end{prototype} - \funcdecl{void *sbrk(ptrdiff\_t increment)} Incrementa lo spazio dati di un - programma di \var{increment}. Un valore zero restituisce l'attuale posizione - della fine del segmento dati. +La funzione è un'interfaccia diretta all'ominima system call ed imposta +l'indirizzo finale del segmento dati di un processo all'indirizzo specificato +da \param{end\_data\_segment}. Quest'ultimo deve essere un valore ragionevole, +ed inoltre la dimensione totale del segmento non deve comunque eccedere un +eventuale limite (si veda \secref{sec:sys_resource_limit}) imposto sulle +dimensioni massime dello spazio dati del processo. + +La seconda funzione per la manipolazione delle dimensioni del segmento +dati\footnote{in questo caso si tratta soltanto di una funzione di libreria, e + non di una sistem call.} è \funcd{sbrk}, ed il suo prototipo è: +\begin{prototype}{unistd.h}{void *sbrk(ptrdiff\_t increment)} + Incrementa la dimensione dello spazio dati. - La funzione restituisce il puntatore all'inizio della nuova zona di memoria - allocata in caso di successo e \val{NULL} in caso di fallimento, nel qual - caso \var{errno} assumerà il valore \errval{ENOMEM}. -\end{functions} -\noindent in genere si usa \func{sbrk} con un valore zero per ottenere -l'attuale posizione della fine del segmento dati. + \bodydesc{La funzione restituisce il puntatore all'inizio della nuova zona + di memoria allocata in caso di successo e \val{NULL} in caso di + fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}.} +\end{prototype} +\noindent la funzione incrementa la dimensione lo spazio dati di un programma +di \param{increment} byte, restituendo il nuovo indirizzo finale dello stesso. +Un valore nullo permette di ottenere l'attuale posizione della fine del +segmento dati. Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e per i programmi normali è sempre opportuno usare le funzioni di allocazione -standard descritte in precedenza, che sono costruite su di esse. L'uso di -queste funzioni è ristretto alle specifiche necessità di chi debba -implementare una sua versione delle routine di allocazione. +standard descritte in precedenza, che sono costruite su di esse. % \subsection{La personalizzazione delle funzioni di allocazione} @@ -717,12 +727,13 @@ trasparente, tutte le pagine che gli occorrono; esistono per particolari in cui non si vuole che questo meccanismo si attivi. In generale i motivi per cui si possono avere di queste necessità sono due: \begin{itemize} -\item \textsl{La velocità}. Il processo della paginazione è trasparente solo - se il programma in esecuzione non è sensibile al tempo che occorre a - riportare la pagina in memoria; per questo motivo processi critici che hanno - esigenze di tempo reale o tolleranze critiche nelle risposte (ad esempio - processi che trattano campionamenti sonori) possono non essere in grado di - sopportare le variazioni della velocità di accesso dovuta alla paginazione. +\item \textsl{La velocità}. Il processo della paginazione\index{paginazione} è + trasparente solo se il programma in esecuzione non è sensibile al tempo che + occorre a riportare la pagina in memoria; per questo motivo processi critici + che hanno esigenze di tempo reale o tolleranze critiche nelle risposte (ad + esempio processi che trattano campionamenti sonori) possono non essere in + grado di sopportare le variazioni della velocità di accesso dovuta alla + paginazione. In certi casi poi un programmatore può conoscere meglio dell'algoritmo di allocazione delle pagine le esigenze specifiche del suo programma e decidere @@ -733,23 +744,25 @@ motivi per cui si possono avere di queste necessit \item \textsl{La sicurezza}. Se si hanno password o chiavi segrete in chiaro in memoria queste possono essere portate su disco dal meccanismo della - paginazione. Questo rende più lungo il periodo di tempo in cui detti segreti - sono presenti in chiaro e più complessa la loro cancellazione (un processo - può cancellare la memoria su cui scrive le sue variabili, ma non può toccare - lo spazio disco su cui una pagina di memoria può essere stata salvata). Per - questo motivo di solito i programmi di crittografia richiedono il blocco di - alcune pagine di memoria. + paginazione\index{paginazione}. Questo rende più lungo il periodo di tempo + in cui detti segreti sono presenti in chiaro e più complessa la loro + cancellazione (un processo può cancellare la memoria su cui scrive le sue + variabili, ma non può toccare lo spazio disco su cui una pagina di memoria + può essere stata salvata). Per questo motivo di solito i programmi di + crittografia richiedono il blocco di alcune pagine di memoria. \end{itemize} -Il meccanismo che previene la paginazione di parte della memoria virtuale di -un processo è chiamato \textit{memory locking} (o \textsl{blocco della - memoria}). Il blocco è sempre associato alle pagine della memoria virtuale -del processo, e non al segmento reale di RAM su cui essa viene mantenuta. +Il meccanismo che previene la paginazione\index{paginazione} di parte della +memoria virtuale di un processo è chiamato \textit{memory locking} (o +\textsl{blocco della memoria}). Il blocco è sempre associato alle pagine della +memoria virtuale del processo, e non al segmento reale di RAM su cui essa +viene mantenuta. La regola è che se un segmento di RAM fa da supporto ad almeno una pagina -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 oppure no. +bloccata allora esso viene escluso dal meccanismo della +paginazione\index{paginazione}. I blocchi non si accumulano, se si blocca due +volte la stessa pagina non è necessario sbloccarla due volte, una pagina o è +bloccata oppure no. Il \textit{memory lock} persiste fintanto che il processo che detiene la memoria bloccata non la sblocca. Chiaramente la terminazione del processo @@ -775,18 +788,17 @@ standard POSIX.1 richiede che sia definita in \file{unistd.h} la macro \textit{memory locking} e la costante \const{PAGESIZE} in \file{limits.h} per indicare la dimensione di una pagina in byte. -Le funzioni per bloccare e sbloccare singole sezioni di memoria sono -\func{mlock} e \func{munlock}; i loro prototipi sono: +Le funzioni per bloccare e sbloccare la paginazione\index{paginazione} di +singole sezioni di memoria sono \funcd{mlock} e \funcd{munlock}; i loro +prototipi sono: \begin{functions} \headdecl{sys/mman.h} \funcdecl{int mlock(const void *addr, size\_t len)} - Blocca la paginazione per l'intervallo di memoria da \var{addr} per - \var{len} byte. Tutte le pagine che contengono una parte dell'intervallo - sono mantenute in RAM per tutta la durata del blocco. + Blocca la paginazione su un intervallo di memoria. \funcdecl{int munlock(const void *addr, size\_t len)} - Sblocca l'intervallo di memoria da \var{addr} per \var{len} byte. + Rimuove il blocco della paginazione su un intervallo di memoria. \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in @@ -796,16 +808,21 @@ Le funzioni per bloccare e sbloccare singole sezioni di memoria sono \item[\errcode{ENOMEM}] alcuni indirizzi dell'intervallo specificato non corrispondono allo spazio di indirizzi del processo o si è ecceduto il numero massimo consentito di pagine bloccate. - \item[\errcode{EINVAL}] \var{len} non è un valore positivo. + \item[\errcode{EINVAL}] \param{len} non è un valore positivo. \end{errlist} e, per \func{mlock}, anche \errval{EPERM} quando il processo non ha i privilegi richiesti per l'operazione.} \end{functions} -Altre due funzioni, \func{mlockall} e \func{munlockall}, consentono di -bloccare genericamente lo spazio di indirizzi di un processo. I prototipi di -queste funzioni sono: +Le due funzioni permettono rispettivamente di bloccare e sbloccare la +paginazione per l'intervallo di memoria specificato dagli argomenti, che ne +indicano nell'ordine l'indirizzo iniziale e la lunghezza. Tutte le pagine che +contengono una parte dell'intervallo sono mantenute in RAM per tutta la durata +del blocco. +Altre due funzioni, \funcd{mlockall} e \funcd{munlockall}, consentono poi di +bloccare genericamente la paginazione\index{paginazione} per l'intero spazio +di indirizzi di un processo. I prototipi di queste funzioni sono: \begin{functions} \headdecl{sys/mman.h} @@ -819,7 +836,7 @@ queste funzioni sono: e \func{munlock}.} \end{functions} -Il parametro \var{flags} di \func{mlockall} permette di controllarne il +L'argomento \param{flags} di \func{mlockall} permette di controllarne il comportamento; esso può essere specificato come l'OR aritmetico delle due costanti: \begin{basedescript}{\desclabelwidth{2.5cm}} @@ -857,7 +874,7 @@ che esse siano state effettivamente portate in memoria, ci si scrive sopra. Tutti i programmi hanno la possibilità di ricevere parametri e opzioni quando vengono lanciati. Il passaggio dei parametri è effettuato attraverso gli -argomenti \var{argc} e \var{argv} della funzione \func{main}, che vengono +argomenti \param{argc} e \param{argv} della funzione \func{main}, che vengono passati al programma dalla shell (o dal processo che esegue la \func{exec}, secondo le modalità che vedremo in \secref{sec:proc_exec}) quando questo viene messo in esecuzione. @@ -883,14 +900,14 @@ di ambiente \cmd{IFS}. \begin{figure}[htb] \centering \includegraphics[width=11cm]{img/argv_argc} - \caption{Esempio dei valori di \var{argv} e \var{argc} generati nella + \caption{Esempio dei valori di \param{argv} e \param{argc} generati nella scansione di una riga di comando.} \label{fig:proc_argv_argc} \end{figure} -Nella scansione viene costruito il vettore di puntatori \var{argv} inserendo +Nella scansione viene costruito il vettore di puntatori \param{argv} inserendo in successione il puntatore alla stringa costituente l'$n$-simo parametro; la -variabile \var{argc} viene inizializzata al numero di parametri trovati, in +variabile \param{argc} viene inizializzata al numero di parametri trovati, in questo modo il primo parametro è sempre il nome del programma; un esempio di questo meccanismo è mostrato in \figref{fig:proc_argv_argc}. @@ -900,8 +917,8 @@ questo meccanismo 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 il carattere \texttt{'-'} e che -non sia un singolo \texttt{'-'} o un \texttt{'--'} viene considerato +tali: un elemento di \param{argv} che inizia con il carattere \texttt{'-'} e +che non sia un singolo \texttt{'-'} o un \texttt{'--'} viene considerato un'opzione. In genere le opzioni sono costituite da una lettera singola (preceduta dal carattere \cmd{'-'}) e possono avere o no un parametro associato; un comando tipico può essere quello mostrato in @@ -910,25 +927,25 @@ e la prima vuole un parametro mentre la seconda no (\cmd{questofile.txt} argomento del programma, non un parametro di \cmd{-m}). Per gestire le opzioni all'interno dei argomenti a linea di comando passati in -\var{argv} le librerie standard del C forniscono la funzione \func{getopt} +\param{argv} le librerie standard del C forniscono la funzione \funcd{getopt}, che ha il seguente prototipo: \begin{prototype}{unistd.h} {int getopt(int argc, char *const argv[], const char *optstring)} Esegue il parsing degli argomenti passati da linea di comando -riconoscendo le possibili opzioni segnalate con \var{optstring}. +riconoscendo le possibili opzioni segnalate con \param{optstring}. \bodydesc{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} -passate a \func{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 un'opzione -valida. +Questa funzione prende come argomenti le due variabili \param{argc} e +\param{argv} passate a \func{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 un'opzione valida. -La stringa \var{optstring} indica quali sono le opzioni riconosciute ed è +La stringa \param{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 di \figref{fig:proc_argv_argc} ad esempio la @@ -937,11 +954,11 @@ stringa di opzioni avrebbe dovuto contenere \texttt{"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{'?'} +dichiarata in \param{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 \texttt{'--'} la scansione viene considerata conclusa, anche se vi sono altri -elementi di \var{argv} che cominciano con il carattere \texttt{'-'}. +elementi di \param{argv} che cominciano con il carattere \texttt{'-'}. \begin{figure}[htb] \footnotesize @@ -986,7 +1003,7 @@ carattere, in questo modo si possono eseguire azioni specifiche usando uno \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. + primo elemento di \param{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. @@ -1005,21 +1022,21 @@ opzioni che prevedono un parametro si (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 rimanenti nella linea di comando. - -Normalmente \func{getopt} compie una permutazione degli elementi di \var{argv} -cosicché 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 è impostata la variabile di ambiente \val{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}. +in \code{argv[]} del primo degli argomenti rimanenti nella linea di comando. + +Normalmente \func{getopt} compie una permutazione degli elementi di +\param{argv} cosicché 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 \param{argv}; se \param{optstring} inizia +con il carattere \texttt{'+'} (o è impostata 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 \param{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 \param{argv}. \subsection{Opzioni in formato esteso} @@ -1043,8 +1060,8 @@ 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 -\val{NULL}. A differenza di \var{argv[]} in questo caso non si ha una -lunghezza dell'array data da un equivalente di \var{argc}, ma la lista è +\val{NULL}. A differenza di \code{argv[]} in questo caso non si ha una +lunghezza dell'array data da un equivalente di \param{argc}, ma la lista è terminata da un puntatore nullo. L'indirizzo della lista delle variabili di ambiente è passato attraverso la @@ -1128,7 +1145,7 @@ controllare \cmd{man environ}. Lo standard ANSI C prevede l'esistenza di un ambiente, e pur non entrando nelle specifiche di come sono strutturati i contenuti, definisce la funzione -\func{getenv} che permette di ottenere i valori delle variabili di ambiente; +\funcd{getenv} che permette di ottenere i valori delle variabili di ambiente; il suo prototipo è: \begin{prototype}{stdlib.h}{char *getenv(const char *name)} Esamina l'ambiente del processo cercando una stringa che corrisponda a @@ -1172,7 +1189,7 @@ in \tabref{tab:proc_env_func}. In Linux sono definite solo le prime quattro delle funzioni elencate in \tabref{tab:proc_env_func}. La prima, \func{getenv}, l'abbiamo appena -esaminata; delle tre restanti le prime due, \func{putenv} e \func{setenv}, +esaminata; delle tre restanti le prime due, \funcd{putenv} e \funcd{setenv}, servono per assegnare nuove variabili di ambiente, i loro prototipi sono i seguenti: \begin{functions} @@ -1187,7 +1204,7 @@ seguenti: \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 per un errore, che è sempre \errval{ENOMEM}.} \end{functions} -\noindent la terza, \func{unsetenv}, serve a cancellare una variabile di +\noindent la terza, \funcd{unsetenv}, serve a cancellare una variabile di ambiente; il suo prototipo è: \begin{functions} \headdecl{stdlib.h} @@ -1207,7 +1224,7 @@ variabile esista gi immutata se uguale a zero. La seconda funzione prende come parametro una stringa analoga quella -restituita da \func{getenv}, e sempre nella forma \var{NOME=valore}. Se la +restituita da \func{getenv}, e sempre nella forma \code{NOME=valore}. Se la variabile specificata non esiste la stringa sarà aggiunta all'ambiente, se invece esiste il suo valore sarà impostato a quello specificato da \param{string}. Si tenga presente che, seguendo lo standard SUSv2, le @@ -1296,7 +1313,7 @@ Come vedremo nei capitoli successivi, non sempre numero fisso di parametri per una funzione. Lo standard ISO C prevede nella sua sintassi la possibilità di definire delle \textit{variadic function} che abbiano un numero variabile di argomenti, attraverso l'uso della -\textit{ellipsis} \var{...} nella dichiarazione della funzione; ma non +\textit{ellipsis} \code{...} nella dichiarazione della funzione; ma non provvede a livello di linguaggio alcun meccanismo con cui dette funzioni possono accedere ai loro argomenti. @@ -1322,7 +1339,7 @@ il prototipo della funzione \func{execl} che vedremo in \end{lstlisting} 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 \var{argv} passato al nuovo processo). Lo standard ISO C richiede +del vettore \param{argv} passato al nuovo processo). Lo standard ISO C richiede inoltre che l'ultimo degli argomenti fissi sia di tipo \textit{self-promoting}\footnote{il linguaggio C prevede che quando si mescolano vari tipi di dati, alcuni di essi possano essere \textsl{promossi} @@ -1380,7 +1397,7 @@ In generale si possono avere pi ciascuno andrà inizializzato con \macro{va\_start} e letto con \macro{va\_arg} e ciascuno potrà scandire la lista degli argomenti per conto suo. -Dopo l'uso di \macro{va\_end} la variabile \var{ap} diventa indefinita e +Dopo l'uso di \macro{va\_end} la variabile \param{ap} diventa indefinita e successive chiamate a \macro{va\_arg} non funzioneranno. Si avranno risultati indefiniti anche chiamando \macro{va\_arg} specificando un tipo che non corrisponde a quello del parametro. @@ -1390,7 +1407,7 @@ corpo principale della funzione, il passo 2) invece pu in una subroutine passandole il puntatore alla lista di argomenti; in questo caso però si richiede che al ritorno della funzione il puntatore non venga più usato (lo standard richiederebbe la chiamata esplicita di \macro{va\_end}), -dato che il valore di \var{ap} risulterebbe indefinito. +dato che il valore di \param{ap} risulterebbe indefinito. Esistono dei casi in cui è necessario eseguire più volte la scansione dei parametri e poter memorizzare una posizione durante la stessa. La cosa più @@ -1496,7 +1513,7 @@ ciclo di lettura principale, scartando l'input come errato.\footnote{a meno Tutto ciò può essere realizzato salvando il contesto dello stack nel punto in cui si vuole tornare in caso di errore, e ripristinandolo quando l'occorrenza capita. La funzione che permette di salvare il contesto dello stack è -\func{setjmp}, il cui prototipo è: +\funcd{setjmp}, il cui prototipo è: \begin{functions} \headdecl{setjmp.h} \funcdecl{void setjmp(jmp\_buf env)} @@ -1522,7 +1539,7 @@ chiamato \func{setjmp} ritorna, nel qual caso l'uso di \func{longjmp} pu comportare conseguenze imprevedibili (e di norma fatali per il processo). Come accennato per effettuare un salto non-locale ad un punto precedentemente -stabilito con \func{setjmp} si usa la funzione \func{longjmp}; il suo +stabilito con \func{setjmp} si usa la funzione \funcd{longjmp}; il suo prototipo è: \begin{functions} \headdecl{setjmp.h}