X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=process.tex;h=f29f993320cbda410a2f40761726231514c56fad;hp=ed4cb07879c6cb45c815df2f58bf61127140bbe6;hb=d0822135edba0f7daa5c1edec3f2c9f2fb1b6347;hpb=e20a546af590a50e7ac47f68f6c7d4648bb4f31a diff --git a/process.tex b/process.tex index ed4cb07..f29f993 100644 --- a/process.tex +++ b/process.tex @@ -131,7 +131,7 @@ prototipo della funzione Causa la conclusione ordinaria del programma restituendo il valore \var{status} al processo padre. - La funzione non ritorna. Il processo viene terminato + \bodydesc{La funzione non ritorna. Il processo viene terminato.} \end{prototype} La funzione \func{exit} è pensata per una conclusione pulita di un programma @@ -150,7 +150,7 @@ prototipo della funzione Causa la conclusione immediata del programma restituendo il valore \var{status} al processo padre. - La funzione non ritorna. Il processo viene terminato. + \bodydesc{La funzione non ritorna. Il processo viene terminato.} \end{prototype} La funzione chiude tutti i file descriptor appartenenti al processo (si tenga @@ -182,11 +182,11 @@ 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 è: \begin{prototype}{stdlib.h}{void atexit(void (*function)(void))} - Registra la funzione \var{function} per essere chiamata all'uscita dal + Registra la funzione \param{function} per essere chiamata all'uscita dal programma. - - La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, - \texttt{errno} non viene settata. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + fallimento, \var{errno} non viene settata.} \end{prototype} La funzione richiede come argomento l'indirizzo della opportuna da chiamare @@ -199,9 +199,9 @@ sistemi), il cui prototipo 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, - \var{errno} non viene settata. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + fallimento, \var{errno} non viene settata.} \end{prototype} In questo caso la funzione da chiamare prende due parametri, il primo dei @@ -601,21 +601,23 @@ avere con le variabili automatiche, su cui torneremo in 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 \func{malloc}. Le funzioni sono: -\begin{prototype}{unistd.h}{int *brk(void end\_data\_segment)} +\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}. - La funzione restituisce 0 in caso di successo e -1 in caso di fallimento, - 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 \var{increment}. Un valore - zero restituisce l'attuale posizione della fine del segmento dati. + La funzione restituisce 0 in caso di successo e -1 in caso di + fallimento, nel qual caso \var{errno} viene settata a \macro{ENOMEM}. + + \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 restituisce il puntatore all'inizio della nuova zona di memoria allocata in caso di successo e \macro{NULL} in caso di fallimento, nel qual caso \macro{errno} viene settata a \macro{ENOMEM}. -\end{prototype} +\end{functions} Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e per i programmi normali è opportuno usare le funzioni di allocazione standard @@ -708,28 +710,21 @@ Le funzioni per bloccare e sbloccare singole sezioni di memoria sono \var{len} byte. Tutte le pagine che contengono una parte dell'intervallo sono mantenute in RAM per tutta la durata del blocco. - La funzione ritorna 0 in caso di successo e -1 in caso di errore, nel qual - caso \var{errno} è settata ad uno dei valori seguenti: - \begin{errlist} - \item \macro{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 \macro{EPERM} il processo non ha i privilegi richiesti per - l'operazione. - \item \macro{EINVAL} \var{len} non è un valore positivo. - \end{errlist} - \funcdecl{int munlock(const void *addr, size\_t len)} - Alloca \var{size} byte nello heap. La memoria non viene inizializzata. + Sblocca l'intervallo di memoria da \var{addr} per \var{len} byte. - Sblocca l'intervallo di memoria da \var{addr} per \var{len} byte. La - funzione ritorna 0 in caso di successo e -1 in caso di errore, nel qual caso - \var{errno} è settata ad uno dei valori seguenti: + + \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in + caso di errore, nel qual caso \var{errno} è settata ad uno dei + valori seguenti: \begin{errlist} - \item \macro{ENOMEM} alcuni indirizzi dell'intervallo specificato non - corrispondono allo spazio di indirizzi del processo. - \item \macro{EINVAL} \var{len} non è un valore positivo. + \item[\macro{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[\macro{EINVAL}] \var{len} non è un valore positivo. \end{errlist} + e, per \func{mlock}, anche \macro{EPERM} quando il processo non ha i + privilegi richiesti per l'operazione.} \end{functions} Altre due funzioni, \func{mlockall} e \func{munlockall}, consentono di @@ -742,23 +737,22 @@ queste funzioni sono: \funcdecl{int mlockall(int flags)} Blocca la paginazione per lo spazio di indirizzi del processo corrente. - Codici di ritorno ed errori sono gli stessi di \func{mlock}. - \funcdecl{int munlockall(void)} Sblocca la paginazione per lo spazio di indirizzi del processo corrente. - Codici di ritorno ed errori sono gli stessi di \func{munlock}. + \bodydesc{Codici di ritorno ed errori sono gli stessi di \func{mlock} + e \func{munlock}.} \end{functions} Il parametro \var{flags} di \func{mlockall} permette di controllarne il comportamento; esso può essere specificato come l'OR aritmetico delle due costanti: -\begin{description*} -\item \macro{MCL\_CURRENT} blocca tutte le pagine correntemente mappate nello +\begin{basedescript}{\desclabelwidth{2.5cm}} +\item[\macro{MCL\_CURRENT}] blocca tutte le pagine correntemente mappate nello spazio di indirizzi del processo. -\item \macro{MCL\_FUTURE} blocca tutte le pagine che saranno mappate nello +\item[\macro{MCL\_FUTURE}] blocca tutte le pagine che saranno mappate nello spazio di indirizzi del processo. -\end{description*} +\end{basedescript} Con \func{mlockall} si può bloccare tutte le pagine mappate nello spazio di indirizzi del processo, sia che comprendano il segmento di testi, di dati, lo @@ -817,12 +811,12 @@ Per gestire le opzioni all'interno dei argomenti a linea di comando passati in 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 +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 parametro -all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e -1 se non esistono altre -opzioni. +\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} @@ -846,7 +840,7 @@ 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{'-'}. -\begin{figure}[htbp] +\begin{figure}[htb] \footnotesize \begin{lstlisting}{} opterr = 0; /* don't want writing to stderr */ @@ -991,9 +985,10 @@ anche altre: per una lista pi \begin{table}[htb] \centering - \begin{tabular}[c]{|l|c|c|c|p{6cm}|} + \begin{tabular}[c]{|l|c|c|c|p{7cm}|} \hline - \textbf{Variabile} & POSIX & XPG & Linux & \textbf{Descrizione} \\ + \textbf{Variabile} & \textbf{POSIX} & \textbf{XPG3} + & \textbf{Linux} & \textbf{Descrizione} \\ \hline \hline \macro{USER} & $\bullet$ & $\bullet$ & $\bullet$ & Nome utente\\ @@ -1016,18 +1011,108 @@ anche altre: per una lista pi \label{tab:proc_env_var} \end{table} -Lo standard ANSI C, pur lasciando alle varie implementazioni i contenuti, -definisce la funzione \func{getenv} che permetta di ottenere i valori delle -variabili di ambiente, il suo prototipo è: - +Lo standard ANSI C, 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, il suo prototipo è: \begin{prototype}{stdlib.h}{char *getenv(const char *name)} Esamina l'ambiente del processo cercando una stringa che corrisponda a quella specificata da \param{name}. - La funzione \macro{NULL} se non trova nulla, o il puntatore alla stringa che - corrisponde (di solito nella forma \texttt{NOME=valore}). + \bodydesc{La funzione ritorna \macro{NULL} se non trova nulla, o il + puntatore alla stringa che corrisponde (di solito nella forma + \texttt{NOME=valore}).} \end{prototype} +Oltre a questa funzione di lettura, che è l'unica definita dallo standard ANSI +C, in seguito sono state proposte altre da utilizzare per settare e per +cancellare le variabili di ambiente presenti; uno schema delle funzioni +previste nei vari standard unix e disponibili in Linux è riportato in \ntab. + +\begin{table}[htb] + \centering + \begin{tabular}[c]{|l|c|c|c|c|c|c|} + \hline + \textbf{Funzione} & \textbf{ANSI C} & \textbf{POSIX.1} & \textbf{XPG3} & + \textbf{SVr4} & \textbf{BSD} & \textbf{Linux} \\ + \hline + \hline + \func{getenv} & $\bullet$ & $\bullet$ & $\bullet$ & + $\bullet$ & $\bullet$ & $\bullet$ \\ + \func{setenv} & & & & + & $\bullet$ & $\bullet$ \\ + \func{unsetenv} & & & & + & $\bullet$ & $\bullet$ \\ + \func{putenv} & & opz. & $\bullet$ & + & $\bullet$ & $\bullet$ \\ + \func{clearenv} & & opz. & & + & & \\ + \hline + \end{tabular} + \caption{Funzioni per la gestione delle variabili di ambiente.} + \label{tab:proc_env_func} +\end{table} + +In Linux solo le prime quattro funzioni di \curtab\ sono definite; delle tre +restanti le prime due, \func{putenv} e \func{setenv} servono per assegnare +nuove variabili di ambiente, i loro prototipi sono i seguenti: +\begin{functions} + \headdecl{stdlib.h} + + \funcdecl{int putenv(char *string)} Aggiunge la stringa \param{string} + all'ambiente. + + \funcdecl{int setenv(const char *name, const char *value, int overwrite)} + Setta la variabile di ambiente \param{name} al valore \param{value}. + + \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 per un + errore, che è sempre \macro{ENOMEM}.} +\end{functions} +\noindent la terza è: +\begin{functions} + \headdecl{stdlib.h} + + \funcdecl{void unsetenv(const char *name)} + Rimuove la variabile di ambiente \param{name}. +\end{functions} + +Per cancellare una variabile di ambiente si usa \func{unsetenv}, che elimina +ogni occorrenza della variabile, se la variabile specificata non esiste non +succede nulla, e non è previsto (dato che la funzione è \type{void}) nessuna +segnalazione di errore. + +Per modificare o aggiungere una variabile di ambiente si possono usare le +funzioni \func{setenv} e \func{putenv}. La prima permette di specificare +separatamente nome e valore della variabile di ambiente, inoltre il valore di +\param{overwrite} specifica il comportamento della funzione nel caso la +variabile esista già, sovrascrivendola se diverso da zero, lasciandola +immutata se uguale a zero. + +La seconda funzione prende come parametro una stringa analoga quella +restituita da \func{getenv}, e sempre nella forma \texttt{NOME=valore}. Se la +variabile specificata non esiste la stringa sarà aggiunta all'ambiente, se +invece esiste il suo valore sarà settato a quello specificato da +\func{string}. Si tenga presente che, seguendo lo standard SUSv2, le +\acr{glibc} successive alla versione 2.1.2 aggiungono\footnote{il + comportamento è lo stesso delle vecchie \acr{libc4} e \acr{libc5}; nelle + \acr{glibc}, dalla versione 2.0 alla 2.1.1, veniva invece fatta una copia, + seguendo il comportamento di BSD4.4; dato che questo può dar luogo a perdite + di memoria e non rispetta lo standard il comportamento è stato modificato a + partire dalle 2.1.2, eliminando anche, sempre in conformità a SUSv2, + l'attributo \type{const} dal prototipo.} \func{string} alla lista delle +variabili di ambiente; pertanto ogni cambiamento alla stringa in questione si +riflette automaticamente sull'ambiente, e quindi si deve evitare di passare +alla funzione variabili automatiche (per evitare i problemi esposti in +\secref{sec:proc_auto_var}). + +Si tenga infine presente che se si passa a \func{putenv} solo il nome di una +variabile (cioè \param{string} è nella forma \texttt{NAME} e non contiene un +\var{=}) allora questa viene cancellata dall'ambiente. Infine se la chiamata +di \func{putenv} comporta la necessità di allocare una nuova versione del +vettore \var{environ} questo sarà allocato, ma la versione corrente sarà +deallocata solo se anch'essa risultante da una allocazione fatta in precedenza +da un'altra \func{putenv}, il vettore originale (in genere piazzato al di +sopra dello stack, vedi \figref{fig:proc_mem_layout}), o la memoria associata +alle variabili di ambiente eliminate non viene comunque liberata. \section{Problematiche di programmazione generica} @@ -1083,6 +1168,17 @@ informazioni sulle dimensioni delle strutture degli indirizzi utilizzate, viene usato questo meccanismo. +\subsection{Il passaggio di un numero variabile di argomenti} +\label{sec:proc_variadic} + +Come vedremo nei capitoli successivi, non sempre è possibile specificare +un numero fisso di parametri per una funzione. Lo standard ISO C +prevede la possibilità di definire delle \textit{varadic function} che +abbiano un numero variabile di argomenti, ma non provvede nessun +meccanismo con cui queste funzioni possono accedere a questi argomenti. + +(NdT il resto è da fare). + \subsection{Potenziali problemi con le variabili automatiche} \label{sec:proc_auto_var} @@ -1111,20 +1207,32 @@ 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 funzioni \func{setjmp} e \func{longjmp}, il cui -prototipo è: +annidate occorre usare quello che viene chiamato un salto \textsl{non-locale}; +questo viene fatto usando 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 è: + \begin{functions} \headdecl{setjmp.h} \funcdecl{void setjmp(jmp\_buf env)} - La funzione salva il contesto dello stack in \param{env} per un successivo - uso da parte di \func{longjmp}. Il contesto viene invalidato se la routine - che ha chiamato \func{setjmp} ritorna. + Salva il contesto dello stack in \param{env} per un successivo uso da parte + di \func{longjmp}. Il contesto viene invalidato se la routine che ha + chiamato \func{setjmp} ritorna. - La funzione ritorna zero quando è chiamata direttamente e un valore diverso - da zero quando ritorna da una chiamata di \func{longjmp} che usa il contesto - salvato in precedenza. + \bodydesc{La funzione ritorna zero quando è chiamata direttamente e un + valore diverso da zero quando ritorna da una chiamata di \func{longjmp} + che usa il contesto salvato in precedenza.} +\end{functions} + +Per poter effettuare un salto non locale si usa la funzione \func{longjmp}; il +suo prototipo è: +\begin{functions} + \headdecl{setjmp.h} \funcdecl{void longjmp(jmp\_buf env, int val)} Ripristina il contesto dello stack salvato dall'ultima chiamata di @@ -1132,6 +1240,6 @@ prototipo di \func{setjmp} con un valore \param{val}. Il valore di \param{val} deve essere diverso da zero, se viene specificato 0 sarà usato 1 al suo posto. - La funzione non ritorna. + \bodydesc{La funzione non ritorna.} \end{functions}