Iniziato I/O formattato (finito quello di linea).
[gapil.git] / process.tex
index d95f13e3b46e6ad3af862d00d09f6888b948fcd1..f29f993320cbda410a2f40761726231514c56fad 100644 (file)
@@ -33,6 +33,7 @@ posto in esecuzione esso apparir
 discorso dei \textit{thread} comunque in Linux necessita di una trattazione a
 parte per la peculiarità dell'implementazione).
 
+
 \subsection{La funzione \func{main}} 
 \label{sec:proc_main}
 
@@ -130,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
@@ -149,10 +150,10 @@ 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 (sui tenga
+La funzione chiude tutti i file descriptor appartenenti al processo (si tenga
 presente che questo non comporta il salvataggio dei dati bufferizzati degli
 stream), fa si che ogni figlio del processo sia ereditato da \cmd{init}
 (vedi \secref{cha:process_handling}), manda un segnale \macro{SIGCHLD} al
@@ -181,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
@@ -198,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
@@ -233,11 +234,12 @@ Lo schema delle modalit
 
 \begin{figure}[htb]
   \centering
-  
+  \includegraphics[width=12cm]{img/proc_beginend}
   \caption{Schema dell'avvio e della conclusione di un programma.}
   \label{fig:proc_prog_start_stop}
 \end{figure}
 
+
 Si ricordi infine che un programma può anche essere interrotto dall'esterno
 attraverso l'uso di un segnale (modalità di conclusione non mostrata in
 \curfig); torneremo su questo aspetto in \secref{cha:signals}.
@@ -389,7 +391,7 @@ programma C viene suddiviso nei seguenti segmenti:
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=5cm]{img/memory_layout.eps}
+  \includegraphics[width=5cm]{img/memory_layout}
   \caption{Disposizione tipica dei segmenti di memoria di un processo}
   \label{fig:proc_mem_layout}
 \end{figure}
@@ -522,7 +524,7 @@ 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}).
+  (vedi \secref{sec:file_std_stream}).
 \item se è posta a 2 viene chiamata \func{abort}, che in genere causa
   l'immediata conclusione del programma.
 \end{itemize*}
@@ -562,13 +564,13 @@ segmento di stack della funzione corrente. La sintassi 
   di successo e \macro{NULL} in caso di fallimento, nel qual caso
   \var{errno} viene settata a \macro{ENOMEM}.
 \end{prototype}
-ma in questo caso non è più necessario liberare la memoria in quanto questa
-viene rilasciata automaticamente al ritorno della funzione.
+\noindent ma in questo caso non è più necessario liberare la memoria in quanto
+questa viene rilasciata automaticamente al ritorno della funzione.
 
 Come è evidente questa funzione ha molti vantaggi, e permette di evitare i
 problemi di memory leak non essendo più necessaria la deallocazione esplicita;
 una delle ragioni principali per usarla è però che funziona anche quando si
-usa \func{longjump} per uscire con un salto non locale da una funzione (vedi
+usa \func{longjmp} per uscire con un salto non locale da una funzione (vedi
 \secref{sec:proc_longjmp}),
 
 Un altro vantaggio e che in Linux la funzione è molto veloce e non viene
@@ -599,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
@@ -706,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
-    corripondono 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
-    corripondono 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
@@ -740,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
@@ -815,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}
@@ -844,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 */
@@ -959,7 +955,7 @@ un esempio del contenuto dell'ambiente, in si 
 variabili che normalmente sono definite dal sistema, è riportato in \nfig.
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=11cm]{img/environ_var.eps}
+  \includegraphics[width=11cm]{img/environ_var}
   \caption{Esempio di lista delle variabili di ambiente.}
   \label{fig:proc_envirno_list}
 \end{figure}
@@ -967,7 +963,7 @@ 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 essere usate da diversi programmi e
-funzioni: per queste c'è l'ulteriore convezione di usare nomi espressi in
+funzioni: per queste c'è l'ulteriore convenzione di usare nomi espressi in
 caratteri maiuscoli.
 
 Il kernel non usa mai queste variabili, il loro uso e la loro interpretazione è
@@ -985,9 +981,138 @@ 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 più completa si può controllare \cmd{man environ}.
 
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|c|c|c|p{7cm}|}
+    \hline
+    \textbf{Variabile} & \textbf{POSIX} & \textbf{XPG3} 
+    & \textbf{Linux} & \textbf{Descrizione} \\
+    \hline
+    \hline
+    \macro{USER} & $\bullet$ & $\bullet$ & $\bullet$ & Nome utente\\
+    \macro{LOGNAME} & $\bullet$ & $\bullet$ & $\bullet$ & Nome utente\\
+    \macro{HOME} & $\bullet$ & $\bullet$ & $\bullet$ & 
+    Directory base dell'utente\\
+    \macro{LANG} & $\bullet$ & $\bullet$ & $\bullet$ & Localizzazione\\
+    \macro{PATH} & $\bullet$ & $\bullet$ & $\bullet$ & Elenco delle directory
+    dei programmi\\
+    \macro{PWD} & $\bullet$ & $\bullet$ & $\bullet$ & Directory corrente\\
+    \macro{SHELL} & $\bullet$ & $\bullet$ & $\bullet$ & Shell in uso\\
+    \macro{TERM} & $\bullet$ & $\bullet$ & $\bullet$ & Tipo di terminale\\
+    \macro{PAGER} & $\bullet$ & $\bullet$ & $\bullet$ & Programma per vedere i
+    testi\\
+    \macro{EDITOR} & $\bullet$ & $\bullet$ & $\bullet$ & Editor di default\\
+    \macro{BROWSER} & $\bullet$ & $\bullet$ & $\bullet$ & Browser di default\\
+    \hline
+  \end{tabular}
+  \caption{Variabile di ambiente più comuni definite da vari standard}
+  \label{tab:proc_env_var}
+\end{table}
+
+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}. 
+  
+  \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}
@@ -1043,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}
 
@@ -1071,6 +1207,39 @@ 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}. 
+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)}
+  
+  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.
+  
+  \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
+  \func{setjmp} con l'argomento \param{env}. Il programma prosegue dal ritorno
+  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.
+
+  \bodydesc{La funzione non ritorna.}
+\end{functions}
+