%% process.tex
%%
-%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2010 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
tutte le parti uguali siano condivise), avrà un suo spazio di indirizzi,
variabili proprie e sarà eseguito in maniera completamente indipendente da
tutti gli altri.\footnote{questo non è del tutto vero nel caso di un programma
- \textit{multi-thread}, ma la gestione dei \textit{thread} in Linux sarà
- trattata a parte.}
+ \textit{multi-thread}, ma la gestione dei \itindex{thread} \textit{thread}
+ in Linux sarà trattata a parte in cap.~\ref{cha:threads}.}
\subsection{La funzione \func{main}}
specificato il flag \texttt{-static} durante la compilazione, tutti i
programmi in Linux sono incompleti e necessitano di essere \textsl{collegati}
alle librerie condivise quando vengono avviati. La procedura è controllata da
-alcune variabili di ambiente e dal contenuto di \file{/etc/ld.so.conf}. I
-dettagli sono riportati nella man page di \cmd{ld.so}.
+alcune variabili di ambiente e dal contenuto di \conffile{/etc/ld.so.conf}. I
+dettagli sono riportati nella pagina di manuale di \cmd{ld.so}.
Il sistema fa partire qualunque programma chiamando la funzione \func{main};
sta al programmatore chiamare così la funzione principale del programma da cui
Oltre alla conclusione ``\textsl{normale}'' esiste anche la possibilità di una
conclusione ``\textsl{anomala}'' del programma a causa della ricezione di un
-segnale (si veda cap.~\ref{cha:signals}) o della chiamata alla funzione
-\func{abort}; torneremo su questo in sez.~\ref{sec:proc_termination}.
+segnale (tratteremo i segnali in cap.~\ref{cha:signals}) o della chiamata alla
+funzione \func{abort}; torneremo su questo in sez.~\ref{sec:proc_termination}.
Il valore di ritorno della funzione \func{main}, o quello usato nelle chiamate
ad \func{exit} e \func{\_exit}, viene chiamato \textsl{stato di uscita} (o
\bodydesc{La funzione non ritorna. Il processo viene terminato.}
\end{prototype}
-La funzione chiude tutti i file descriptor appartenenti al processo (si 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 sì che ogni figlio del processo sia adottato da \cmd{init} (vedi
-cap.~\ref{cha:process_handling}), manda un segnale \const{SIGCHLD} al processo
-padre (vedi sez.~\ref{sec:sig_job_control}) ed infine ritorna lo stato di
-uscita specificato in \param{status} che può essere raccolto usando la
-funzione \func{wait} (vedi sez.~\ref{sec:proc_wait}).
+stream, (torneremo sulle due interfacce dei file a partire da
+cap.~\ref{cha:file_intro}), fa sì che ogni figlio del processo sia adottato da
+\cmd{init} (vedi cap.~\ref{cha:process_handling}), manda un segnale
+\const{SIGCHLD} al processo padre (vedi sez.~\ref{sec:sig_job_control}) ed
+infine ritorna lo stato di uscita specificato in \param{status} che può essere
+raccolto usando la funzione \func{wait} (vedi sez.~\ref{sec:proc_wait}).
\subsection{Le funzioni \func{atexit} e \func{on\_exit}}
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
+ \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 di una opportuna
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
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
fallimento, \var{errno} non viene modificata.}
\end{prototype}
\begin{figure}[htb]
\centering
- \includegraphics[width=9cm]{img/proc_beginend}
+% \includegraphics[width=9cm]{img/proc_beginend}
+ \begin{tikzpicture}[>=stealth]
+ \filldraw[fill=black!35] (-0.3,0) rectangle (12,1);
+ \draw(5.5,0.5) node {\large{kernel}};
+
+ \filldraw[fill=black!15] (1.5,2) rectangle (4,3);
+ \draw (2.75,2.5) node {\texttt{ld-linux.so}};
+ \draw [->] (2.75,1) -- (2.75,2);
+ \draw (2.75,1.5) node [anchor=west]{\texttt{exec}};
+
+ \filldraw[fill=black!15,rounded corners] (1.5,4) rectangle (4,5);
+ \draw (2.75,4.5) node {\texttt{main}};
+
+ \draw [<->, dashed] (2.75,3) -- (2.75,4);
+ \draw [->] (1.5,4.5) -- (0.3,4.5) -- (0.3,1);
+ \draw (0.9,4.5) node [anchor=south] {\texttt{\_exit}};
+
+ \filldraw[fill=black!15,rounded corners] (1.5,6) rectangle (4,7);
+ \draw (2.75,6.5) node {\texttt{funzione}};
+
+ \draw [<->, dashed] (2.75,5) -- (2.75,6);
+ \draw [->] (1.5,6.5) -- (0.05,6.5) -- (0.05,1);
+ \draw (0.9,6.5) node [anchor=south] {\texttt{\_exit}};
+
+ \draw (6.75,4.5) node (exit) [rectangle,fill=black!15,minimum width=2.5cm,minimum height=1cm,rounded corners, draw]{\texttt{exit}};
+
+ \draw[->] (4,6.5) -- node[anchor=south west]{\texttt{exit}} (exit);
+ \draw[->] (4,4.5) -- node[anchor=south]{\texttt{exit}} (exit);
+ \draw[->] (exit) -- node[anchor=east]{\texttt{\_exit}}(6.75,1);
+
+ \draw (10,4.5) node (exithandler1) [rectangle,fill=black!15,rounded corners, draw]{exit handler};
+ \draw (10,5.5) node (exithandler2) [rectangle,fill=black!15,rounded corners, draw]{exit handler};
+ \draw (10,3.5) node (stream) [rectangle,fill=black!15,rounded corners, draw]{chiusura stream};
+
+ \draw[<->, dashed] (exithandler1) -- (exit);
+ \draw[<->, dashed] (exithandler2) -- (exit);
+ \draw[<->, dashed] (stream) -- (exit);
+ \end{tikzpicture}
\caption{Schema dell'avvio e della conclusione di un programma.}
\label{fig:proc_prog_start_stop}
\end{figure}
Benché lo spazio di indirizzi virtuali copra un intervallo molto ampio, solo
una parte di essi è effettivamente allocato ed utilizzabile dal processo; il
tentativo di accedere ad un indirizzo non allocato è un tipico errore che si
-commette quando si è manipolato male un puntatore e genera quello che viene
-chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o
-scrivere da un indirizzo per il quale non esiste un'associazione della pagina
-virtuale, il kernel risponde al relativo \itindex{page~fault} \textit{page
- fault} mandando un segnale \const{SIGSEGV} al processo, che normalmente ne
-causa la terminazione immediata.
+commette quando si è manipolato male un puntatore e genera quella che viene
+chiamata una \itindex{segment~violation} \textit{segment violation}. Se si
+tenta cioè di leggere o scrivere da un indirizzo per il quale non esiste
+un'associazione della pagina virtuale, il kernel risponde al relativo
+\itindex{page~fault} \textit{page fault} mandando un segnale \const{SIGSEGV}
+al processo, che normalmente ne causa la terminazione immediata.
È pertanto importante capire come viene strutturata \index{memoria~virtuale}
\textsl{la memoria virtuale} di un processo. Essa viene divisa in
viene il nome \itindex{stack} \textit{stack}) in sequenza uno sull'altro; in
questo modo le funzioni possono essere chiamate ricorsivamente. Al ritorno
della funzione lo spazio è automaticamente rilasciato e
- ``\textsl{ripulito}''. La pulizia in C e C++ viene fatta dal
- chiamante.\footnote{a meno che non sia stato specificato l'utilizzo di una
- calling convention diversa da quella standard.}
-% TODO verificare le modalità di cambiamento della calling convention
+ ``\textsl{ripulito}''.\footnote{il compilatore si incarica di generare
+ automaticamente il codice necessario, seguendo quella che viene chiamata
+ una \textit{calling convention}; quella standard usata con il C ed il C++
+ è detta \textit{cdecl} e prevede che gli argomenti siano caricati nello
+ \textit{stack} dal chiamante da destra a sinistra, e che si il chiamante
+ stesso ad eseguire la ripulitura dello \textit{stack} al ritorno della
+ funzione, se ne possono però utilizzare di alternative (ad esempio nel
+ pascal gli argomenti sono inseriti da sinistra a destra ed è compito del
+ chiamato ripulire lo \textit{stack}), in genere non ci si deve preoccupare
+ di questo fintanto che non si mescolano funzioni scritte con linguaggi
+ diversi.}
La dimensione di questo segmento aumenta seguendo la crescita dello
\itindex{stack} \textit{stack} del programma, ma non viene ridotta quando
\begin{figure}[htb]
\centering
- \includegraphics[height=12cm]{img/memory_layout}
+% \includegraphics[height=12cm]{img/memory_layout}
+ \begin{tikzpicture}
+ \draw (0,0) rectangle (4,1);
+ \draw (2,0.5) node {text};
+ \draw (0,1) rectangle (4,2.5);
+ \draw (2,1.75) node {dati inizializzati};
+ \draw (0,2.5) rectangle (4,5);
+ \draw (2,3.75) node {dati non inizializzati};
+ \draw (0,5) rectangle (4,9);
+ \draw[dashed] (0,6) -- (4,6);
+ \draw[dashed] (0,8) -- (4,8);
+ \draw (2,5.5) node {heap};
+ \draw (2,8.5) node {stack};
+ \draw [->] (2,6) -- (2,6.5);
+ \draw [->] (2,8) -- (2,7.5);
+ \draw (0,9) rectangle (4,10);
+ \draw (2,9.5) node {environment};
+ \draw (4,0) node [anchor=west] {\texttt{0x08000000}};
+ \draw (4,5) node [anchor=west] {\texttt{0x08xxxxxx}};
+ \draw (4,9) node [anchor=west] {\texttt{0xC0000000}};
+ \end{tikzpicture}
\caption{Disposizione tipica dei segmenti di memoria di un processo.}
\label{fig:proc_mem_layout}
\end{figure}
operazione.
Le \acr{glibc} hanno un'implementazione delle funzioni di allocazione che è
-controllabile dall'utente attraverso alcune variabili di ambiente, in
-particolare diventa possibile tracciare questo tipo di errori usando la
-variabile di ambiente \val{MALLOC\_CHECK\_} che quando viene definita mette in
-uso una versione meno efficiente delle funzioni suddette, che però è più
-tollerante nei confronti di piccoli errori come quello di chiamate doppie a
-\func{free}. In particolare:
-\begin{itemize*}
+controllabile dall'utente attraverso alcune variabili di ambiente (vedi
+sez.~\ref{sec:proc_environ}), in particolare diventa possibile tracciare
+questo tipo di errori usando la variabile di ambiente \val{MALLOC\_CHECK\_}
+che quando viene definita mette in uso una versione meno efficiente delle
+funzioni suddette, che però è più tollerante nei 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 sez.~\ref{sec:file_std_stream});
\item se è posta a 2 viene chiamata \func{abort}, che in genere causa
l'immediata conclusione del programma.
-\end{itemize*}
+\end{itemize}
Il problema più comune e più difficile da risolvere che si incontra con le
funzioni di allocazione è quando non viene opportunamente liberata la memoria
probabile impossibilità di proseguire l'esecuzione del programma).
Il problema è che l'esaurimento della memoria può avvenire in qualunque
-momento, in corrispondenza ad una qualunque chiamata di \func{malloc}, che può
+momento, in corrispondenza ad una qualunque chiamata di \func{malloc} che può
essere in una sezione del codice che non ha alcuna relazione con la subroutine
che contiene l'errore. Per questo motivo è sempre molto difficile trovare un
\itindex{memory~leak} \textit{memory leak}.
ricompilare il programma,\footnote{esempi sono \textit{Dmalloc}
\href{http://dmalloc.com/}{\textsf{http://dmalloc.com/}} di Gray Watson ed
\textit{Electric Fence} di Bruce Perens.} di eseguire diagnostiche anche
-molto complesse riguardo l'allocazione della memoria.
-
-
-Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
-problemi di \itindex{memory~leak} \textit{memory leak} descritti in
-precedenza, è la funzione \funcd{alloca}, che invece di allocare la memoria
-nello \itindex{heap} \textit{heap} usa il segmento di \itindex{stack}
-\textit{stack} della funzione corrente. La sintassi è identica a quella di
-\func{malloc}, il suo prototipo è:
+molto complesse riguardo l'allocazione della memoria. Vedremo alcune delle
+funzionalità di ausilio presenti nelle \acr{glibc} in
+sez.~\ref{sec:proc_memory_adv_management}.
+
+Una possibile alternativa all'uso di \func{malloc}, per evitare di soffrire
+dei problemi di \itindex{memory~leak} \textit{memory leak} descritti in
+precedenza, è di allocare la memoria nel segmento di \itindex{stack}
+\textit{stack} della funzione corrente invece che nello \itindex{heap}
+\textit{heap}, per farlo si può usare la funzione \funcd{alloca}, la cui
+sintassi è identica a quella di \func{malloc}; il suo prototipo è:
\begin{prototype}{stdlib.h}{void *alloca(size\_t size)}
- Alloca \param{size} byte nello stack.
+ Alloca \param{size} byte nello \textit{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}.}
+ \bodydesc{La funzione restituisce il puntatore alla zona di memoria
+ allocata.}
\end{prototype}
La funzione alloca la quantità di memoria (non inizializzata) richiesta
non può essere usata nella lista degli argomenti di una funzione, perché lo
spazio verrebbe allocato nel mezzo degli stessi.
-% Questo è riportato solo dal manuale delle glibc, nelle pagine di manuale non c'è
-% traccia di tutto ciò
-%
-%Inoltre se si
-%cerca di allocare troppa memoria non si ottiene un messaggio di errore, ma un
-%segnale di \textit{segment violation} analogo a quello che si avrebbe da una
-%ricorsione infinita.
-% TODO inserire più informazioni su alloca come da man page
-
-
Inoltre non è chiaramente possibile usare \func{alloca} per allocare memoria
che deve poi essere usata anche al di fuori della funzione in cui essa viene
chiamata, dato che all'uscita dalla funzione lo spazio allocato diventerebbe
Questo è lo stesso problema che si può avere con le variabili automatiche, su
cui torneremo in sez.~\ref{sec:proc_auto_var}.
+Infine non esiste un modo di sapere se l'allocazione ha avuto successo, la
+funzione infatti viene realizzata inserendo del codice \textit{inline} nel
+programma\footnote{questo comporta anche il fatto che non è possibile
+ sostituirla con una propria versione o modificarne il comportamento
+ collegando il proprio programma con un'altra libreria.} che si limita a
+modificare il puntatore nello \itindex{stack} \textit{stack} e non c'è modo di
+sapere se se ne sono superate le dimensioni, per cui in caso di fallimento
+nell'allocazione il comportamento del programma può risultare indefinito,
+dando luogo ad una \itindex{segment~violation} \textit{segment violation} la
+prima volta che cercherà di accedere alla memoria non effettivamente
+disponibile.
Le due funzioni seguenti\footnote{le due funzioni sono state definite con BSD
- 4.3, non fanno parte delle librerie standard del C e mentre sono state
- esplicitamente escluse dallo standard POSIX.} 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 funzioni di allocazione della memoria.
-La prima funzione è \funcd{brk}, ed il suo prototipo è:
+ 4.3, sono marcate obsolete in SUSv2 e non fanno parte delle librerie
+ standard del C e mentre sono state esplicitamente rimosse dallo standard
+ POSIX/1-2001.} 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
+funzioni di allocazione della memoria. Per poterle utilizzare è necessario
+definire una della macro di funzionalità (vedi
+sez.~\ref{sec:intro_gcc_glibc_std}) fra \macro{\_BSD\_SOURCE},
+\macro{\_SVID\_SOURCE} e \macro{\_XOPEN\_SOURCE} (ad un valore maggiore o
+ugiale di 500). 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.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \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}
-La funzione è un'interfaccia diretta all'omonima system call ed imposta
-l'indirizzo finale del \index{segmento!dati} 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
-sez.~\ref{sec:sys_resource_limit}) imposto sulle dimensioni massime dello
-spazio dati del processo.
-
-Una seconda funzione per la manipolazione delle dimensioni
+La funzione è un'interfaccia all'omonima system call ed imposta l'indirizzo
+finale del \index{segmento!dati} 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 sez.~\ref{sec:sys_resource_limit})
+imposto sulle dimensioni massime dello spazio dati del processo.
+
+Il valore di ritorno della funzione fa riferimento alla versione fornita dalle
+\acr{glibc}, in realtà in Linux la \textit{system call} corrispondente
+restituisce come valore di ritorno il nuovo valore della fine del
+\index{segmento!dati} segmento dati in caso di successo e quello corrente in
+caso di fallimento, è la funzione di interfaccia usata dalle \acr{glibc} che
+fornisce i valori di ritorno appena descritti, questo può non accadere se si
+usano librerie diverse.
+
+Una seconda funzione per la manipolazione diretta delle dimensioni
\index{segmento!dati} del segmento dati\footnote{in questo caso si tratta
soltanto di una funzione di libreria, e non di una system call.} è
\funcd{sbrk}, ed il suo prototipo è:
crittografia richiedono il blocco di alcune pagine di memoria.
\end{itemize}
+Per ottenere informazioni sulle modalità in cui un programma sta usando la
+memoria virtuale è disponibile una apposita funzione, \funcd{mincore}, che
+però non è standardizzata da POSIX e pertanto non è disponibile su tutte le
+versioni di kernel unix-like;\footnote{nel caso di Linux devono essere
+ comunque definite le macro \macro{\_BSD\_SOURCE} e \macro{\_SVID\_SOURCE}.}
+il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{sys/mman.h}
+
+ \funcdecl{int mincore(void *addr, size\_t length, unsigned char *vec)}
+ Ritorna lo stato delle pagine di memoria occupate da un processo.
+
+ \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori seguenti:
+ \begin{errlist}
+ \item[\errcode{ENOMEM}] o \param{addr} + \param{lenght} eccede la dimensione
+ della memoria usata dal processo o l'intervallo di indirizzi specificato
+ non è mappato.
+ \item[\errcode{EINVAL}] \param{addr} non è un multiplo delle dimensioni di
+ una pagina.
+ \item[\errcode{EFAULT}] \param{vec} punta ad un indirizzo non valido.
+ \item[\errcode{EAGAIN}] il kernel è temporaneamente non in grado di fornire
+ una risposta.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione permette di ottenere le informazioni sullo stato della mappatura
+della memoria per il processo chiamante, specificando l'intervallo da
+esaminare con l'indirizzo iniziale (indicato con l'argomento \param{addr}) e
+la lunghezza (indicata con l'argomento \param{length}). L'indirizzo iniziale
+deve essere un multiplo delle dimensioni di una pagina, mentre la lunghezza
+può essere qualunque, fintanto che si resta nello spazio di indirizzi del
+processo,\footnote{in caso contrario si avrà un errore di \errcode{ENOMEM};
+ fino al kernel 2.6.11 in questo caso veniva invece restituito
+ \errcode{EINVAL}, in considerazione che il caso più comune in cui si
+ verifica questo errore è quando si usa per sbaglio un valore negativo
+ di \param{length}, che nel caso verrebbe interpretato come un intero
+ positivo di grandi dimensioni.} ma il risultato verrà comunque fornito per
+l'intervallo compreso fino al multiplo successivo.
+
+I risultati della funzione vengono forniti nel vettore puntato da \param{vec},
+che deve essere allocato preventivamente e deve essere di dimensione
+sufficiente a contenere tanti byte quante sono le pagine contenute
+nell'intervallo di indirizzi specificato.\footnote{la dimensione cioè deve
+ essere almeno pari a \code{(length+PAGE\_SIZE-1)/PAGE\_SIZE}. } Al ritorno
+della funzione il bit meno significativo di ciascun byte del vettore sarà
+acceso se la pagina di memoria corrispondente è al momento residente in
+memoria, o cancellato altrimenti. Il comportamento sugli altri bit è
+indefinito, essendo questi al momento riservati per usi futuri. Per questo
+motivo in genere è comunque opportuno inizializzare a zero il contenuto del
+vettore, così che le pagine attualmente residenti in memoria saranno indicata
+da un valore non nullo del byte corrispondente.
+
+Dato che lo stato della memoria di un processo può cambiare continuamente, il
+risultato di \func{mincore} è assolutamente provvisorio e lo stato delle
+pagine potrebbe essere già cambiato al ritorno stesso della funzione, a meno
+che, come vedremo ora, non si sia attivato il meccanismo che forza il
+mantenimento di una pagina sulla memoria.
+
\itindbeg{memory~locking}
Il meccanismo che previene la \index{paginazione} paginazione di parte della
in byte.\footnote{con Linux questo non avviene e si deve ricorrere alla
funzione \func{getpagesize}, vedi sez.~\ref{sec:sys_memory_res}.}
-
A partire dal kernel 2.6.9 anche un processo normale può bloccare la propria
memoria\footnote{la funzionalità è stata introdotta per non essere costretti a
dare privilegi eccessivi a programmi di crittografia, che necessitano di
\funcdecl{int munlock(const void *addr, size\_t len)}
Rimuove il blocco della paginazione su un intervallo di memoria.
- \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in
+ \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e $-1$ in
caso di errore, nel qual caso \var{errno} assumerà uno dei
valori seguenti:
\begin{errlist}
\itindend{memory~locking}
-% TODO documentare \func{madvise}
-% TODO documentare \func{mincore}
+\index{memoria~virtuale|)}
-\index{memoria~virtuale|)}
+\subsection{Gestione avanzata dell'allocazione della memoria}
+\label{sec:proc_memory_adv_management}
+
+La trattazione delle funzioni di allocazione di sez.~\ref{sec:proc_mem_alloc}
+si è limitata a coprire le esigenze generiche di un programma, in cui non si
+hanno dei requisiti specifici e si lascia il controllo delle modalità di
+allocazione alle funzioni di libreria. Tuttavia esistono una serie di casi in
+cui può essere necessario avere un controllo più dettagliato delle modalità
+con cui la memoria viene allocata; nel qual caso potranno venire in aiuto le
+funzioni trattate in questa sezione.
+
+Le prime funzioni che tratteremo sono quelle che consentono di richiedere di
+allocare un blocco di memoria ``\textsl{allineato}'' ad un multiplo una certa
+dimensione. Questo tipo di esigenza emerge usualmente quando si devono
+allocare dei buffer da utilizzare per eseguire dell'I/O diretto su dispositivi
+a blocchi. In questo caso infatti il trasferimento di dati viene eseguito per
+blocchi di dimensione fissa, ed è richiesto che l'indirizzo di partenza del
+buffer sia un multiplo intero di questa dimensione, usualmente 512 byte. In
+tal caso l'uso di \func{malloc} non è sufficiente, ed occorre utilizzare una
+funzione specifica.
+
+Tradizionalmente per rispondere a questa esigenza sono state crate due
+funzioni diverse, \funcd{memalign} e \funcd{valloc}, oggi obsolete; i
+rispettivi prototipi sono:
+\begin{functions}
+ \headdecl{malloc.h}
+ \funcdecl{void *valloc(size\_t size)} Alloca un blocco di memoria allineato
+ alla dimensione di una pagina di memoria.
-% \subsection{Gestione avanzata dell'allocazione della memoria}
-% \label{sec:proc_mem_malloc_custom}
-% TODO: trattare le funzionalità avanzate di \func{malloc}
+ \funcdecl{void *memalign(size\_t boundary, size\_t size)}
+ Alloca un blocco di memoria allineato ad un multiplo di \param{boundary}.
+
+ \bodydesc{Entrambe le funzioni ritornano un puntatore al blocco di memoria
+ allocato in caso di successo e \val{NULL} in caso di errore, nel qual
+ caso \var{errno} assumerà uno dei valori seguenti:
+ \begin{errlist}
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'allocazione.
+ \item[\errcode{EINVAL}] \param{boundary} non è multiplo di due.
+ \end{errlist}
+}
+\end{functions}
+Le funzioni restituiscono il puntatore al buffer di memoria allocata, che per
+\func{memalign} sarà un multiplo di \param{boundary} mentre per \func{valloc}
+un multiplo della dimensione di una pagina di memoria. Nel caso della versione
+fornita dalle \acr{glibc} la memoria allocata con queste funzioni deve essere
+liberata con \func{free}, cosa che non è detto accada con altre
+implementazioni.
+
+Nessuna delle due funzioni ha una chiara standardizzazione (nessuna delle due
+compare in POSIX.1), ed inoltre ci sono indicazioni discordi sui file che ne
+contengono la definizione;\footnote{secondo SUSv2 \func{valloc} è definita in
+ \texttt{stdlib.h}, mentre sia le \acr{glibc} che le precedenti \acr{libc4} e
+ \acr{lic5} la dichiarano in \texttt{malloc.h}, lo stesso vale per
+ \func{memalign} che in alcuni sistemi è dichiarata in \texttt{stdlib.h}.}
+per questo motivo il loro uso è sconsigliato, essendo state sostituite dalla
+nuova \funcd{posix\_memalign}, che è stata standardizzata in POSIX.1d; il suo
+prototipo è:
+\begin{prototype}{stdlib.h}{posix\_memalign(void **memptr, size\_t alignment,
+ size\_t size) }
+ Alloca un buffer di memoria allineato ad un multiplo di \param{alignment}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e \val{NULL} in caso
+ di fallimento, o uno dei due codici di errore \errcode{ENOMEM} o
+ \errcode{EINVAL}; \var{errno} non viene impostata.}
+\end{prototype}
+La funzione restituisce il puntatore al buffer allocato all'indirizzo indicato
+da \param{memptr}. La funzione fallisce nelle stesse condizioni delle due
+funzioni precedenti, ma a differenza di \func{memalign} restituisce un codice
+di errore \errcode{EINVAL} anche se \param{alignment} non è un multiplo della
+la dimensione di \code{sizeof(void *)}. Come per le precedenti la memoria
+allocata con \func{posix\_memalign} può essere disallocata con
+\func{free}.\footnote{che in questo caso è quanto richiesto dallo standard.}
+
+Un secondo caso in cui risulta estremamente utile poter avere un maggior
+controllo delle modalità di allocazione della memoria è quello in cui cercano
+errori di programmazione. Esempi di questi errori sono chiamate doppie alla
+funzione \func{free} con lo stesso puntatore, o i cosiddetti
+\itindex{buffer~overrun} \textit{buffer overrun}, cioè le scritture su un buffer
+oltre le dimensioni della sua allocazione,\footnote{entrambe queste operazioni
+ causano in genere la corruzione dei dati di controllo delle funzioni di
+ allocazione, che vengono anch'essi mantenuti nello \itindex{heap}
+ \textit{heap} per tenere traccia delle zone di memoria allocata.} o i
+classici \itindex{memory~leak} \textit{memory leak}.
+
+Una prima funzionalità di ausilio nella ricerca di questi errori viene fornita
+dalla \acr{glibc} tramite l'uso della variabile di ambiente
+\var{MALLOC\_CHECK\_}. Quando questa viene definita al posto della versione
+ordinaria delle funzioni di allocazione (\func{malloc}, \func{calloc},
+\func{realloc}, e \func{free}) viene usata una versione meno efficiente ma in
+grado di rilevare (e tollerare) alcuni degli errori più semplici, come le
+doppie chiamate a \func{free} o i \itindex{buffer~overrun} \textit{buffer
+ overrun} di un byte.\footnote{uno degli errori più comuni, causato ad
+ esempio dalla scrittura di una stringa di dimensione pari a quella del
+ buffer, in cui ci si dimentica dello zero di terminazione finale.}
+
+In questo caso a seconda del valore assegnato a \var{MALLOC\_CHECK\_} si
+avranno diversi comportamenti: con 0 l'errore sarà ignorato, con 1 verrà
+stampato un messaggio sullo \textit{standard error} (vedi
+sez.~\ref{sec:file_std_stream}), con 2 verrà invocata la funzione \func{abort}
+(vedi sez.~\ref{sec:sig_alarm_abort}) che termina il programma, con 3 viene
+sia stampato il messaggio d'errore che abortito il programma. In genere è
+opportuno definire la variabile ad un valore diverso da zero che consente di
+rilevare un errore nel momento in cui avviene.
+
+Una modalità alternativa per effettuare dei controlli di consistenza sullo
+stato delle allocazioni di memoria eseguite con \func{malloc}, anche questa
+fornita come estensione specifica (e non standard) delle \acr{glibc}, è quella
+di utilizzare la funzione \funcd{mcheck}, che deve essere chiamata prima di
+eseguire qualunque allocazione con \func{malloc}; il suo prototipo è:
+\begin{prototype}{mcheck.h}{mcheck(void (*abortfn) (enum mcheck\_status
+ status))}
+ Attiva i controlli di consistenza delle allocazioni eseguite da \func{malloc}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ fallimento; \var{errno} non viene impostata.}
+\end{prototype}
-\section{Argomenti, opzioni ed ambiente di un processo}
-\label{sec:proc_options}
+La funzione consente di registrare una funzione di emergenza, da passare come
+argomento, che verrà eseguita tutte le volte che, in una successiva esecuzione
+di \func{malloc}, venissero trovate delle inconsistenze, come delle operazioni
+di scrittura oltre i limiti dei buffer allocati. Per questo motivo la funzione
+deve essere chiamata prima di qualunque allocazione di memoria, altrimenti
+fallirà con un valore di ritorno pari a $-1$.
+
+Se come argomento di \func{mcheck} si passa \var{NULL} verrà utilizzata una
+funzione predefinita che stampa un messaggio di errore ed invoca la funzione
+\func{abort} (vedi sez.~\ref{sec:sig_alarm_abort}), altrimenti si dovrà create
+una funzione personalizzata che verrà eseguita ricevendo un unico argomento di
+tipo \type{mcheck\_status},\footnote{trattasi in sostanza di un codice di
+ errore che la funzione di emergenza potrà utilizzare per prendere le
+ opportune azioni.} un tipo enumerato che può assumere soltanto i valori di
+tab.~\ref{tab:mcheck_status_value}.
-Tutti i programmi hanno la possibilità di ricevere argomenti e opzioni quando
-vengono lanciati. Il passaggio degli argomenti è effettuato attraverso gli
-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 sez.~\ref{sec:proc_exec}) quando questo
-viene messo in esecuzione.
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{7cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{MCHECK\_OK} & riportato (a \func{mprobe}) se nessuna
+ inconsistenza è presente.\\
+ \macro{MCHECK\_DISABLED}& riportato (a \func{mprobe}) se si è chiamata
+ \func{mcheck} dopo aver già usato
+ \func{malloc}.\\
+ \macro{MCHECK\_HEAD} & i dati immediatamente precedenti il buffer sono
+ stati modificati, avviene in genere quando si
+ decrementa eccessivamente il valore di un
+ puntatore scrivendo poi prima dell'inizio del
+ buffer.\\
+ \macro{MCHECK\_TAIL} & i dati immediatamente seguenti il buffer sono
+ stati modificati, succede quando si va scrivere
+ oltre la dimensione correttta del buffer.\\
+ \macro{MCHECK\_FREE} & il buffer è già stato disallocato.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dello stato dell'allocazione di memoria ottenibili dalla
+ funzione di teminazione installata con \func{mcheck}.}
+ \label{tab:mcheck_status_value}
+\end{table}
+
+Una volta che si sia chiamata \func{mcheck} con successo si può anche
+controllare esplicitamente lo stato delle allocazioni (senza aspettare un
+errore nelle relative funzioni) utilizzando la funzione \funcd{mprobe}, il cui
+prototipo è:
+\begin{prototype}{mcheck.h}{enum mcheck\_status mprobe(ptr)}
+ Esegue un controllo di consistenza delle allocazioni.
+
+ \bodydesc{La funzione restituisce un codice fra quelli riportati in
+ tab.\ref{tab:mcheck_status_value}.}
+\end{prototype}
+
+La funzione richiede che si passi come argomento un puntatore ad un blocco di
+memoria precedentemente allocato con \func{malloc} o \func{realloc}, e
+restituisce lo stesso codice di errore che si avrebbe per la funzione di
+emergenza ad una successiva chiamata di una funzione di allocazione, e poi i
+primi due codici che indicano rispettivamente quando tutto è a posto o il
+controllo non è possibile per non aver chiamato \func{mcheck} in tempo.
+
+% TODO: trattare le altre funzionalità avanzate di \func{malloc}, mallopt,
+% mtrace, muntrace, mallinfo e gli hook con le glibc 2.10 c'è pure malloc_info
+% a sostituire mallinfo, vedi http://udrepper.livejournal.com/20948.html
-Oltre al passaggio degli argomenti, un'altra modalità che permette di passare
-delle informazioni che modifichino il comportamento di un programma è quello
-dell'uso del cosiddetto \textit{environment} (cioè l'uso delle
-\textsl{variabili di ambiente}). In questa sezione esamineremo le funzioni che
-permettono di gestire argomenti ed opzioni, e quelle che consentono di
-manipolare ed utilizzare le variabili di ambiente.
+\section{Argomenti, ambiente ed altre proprietà di un processo}
+\label{sec:proc_options}
+
+
+In questa sezione esamineremo le funzioni che permettono di gestire gli
+argomenti e le opzioni, e quelle che consentono di manipolare ed utilizzare le
+variabili di ambiente. Accenneremo infine alle modalità con cui si può gestire
+la localizzazione di un programma modificandone il comportamento a seconda
+della lingua o del paese a cui si vuole faccia riferimento nelle sue
+operazioni.
\subsection{Il formato degli argomenti}
\label{sec:proc_par_format}
-In genere il passaggio degli argomenti al programma viene effettuato dalla
-shell, che si incarica di leggere la linea di comando e di effettuarne la
-scansione (il cosiddetto \textit{parsing}) per individuare le parole che la
-compongono, ciascuna delle quali viene considerata un argomento. Di norma per
-individuare le parole viene usato come carattere di separazione lo spazio o il
-tabulatore, ma il comportamento è modificabile attraverso l'impostazione della
-variabile di ambiente \cmd{IFS}.
+Tutti i programmi hanno la possibilità di ricevere argomenti e opzioni quando
+vengono lanciati. Il passaggio degli argomenti e delle opzioni è effettuato
+attraverso gli 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
+sez.~\ref{sec:proc_exec}) quando questo viene messo in esecuzione.
+
+In genere il passaggio di argomenti ed opzioni ad un programma viene
+effettuato dalla shell, che si incarica di leggere la linea di comando e di
+effettuarne la scansione (il cosiddetto \textit{parsing}) per individuare le
+parole che la compongono, ciascuna delle quali potrà essere considerata un
+argomento o un'opzione. Di norma per individuare le parole che andranno a
+costituire la lista degli argomenti viene usato come carattere di separazione
+lo spazio o il tabulatore, ma la cosa dipende ovviamente dalle modalità con
+cui si effettua la scansione.
\begin{figure}[htb]
\centering
\label{fig:proc_argv_argc}
\end{figure}
-Nella scansione viene costruito il vettore di puntatori \param{argv} inserendo
-in successione il puntatore alla stringa costituente l'$n$-simo argomento; la
-variabile \param{argc} viene inizializzata al numero di argomenti trovati, in
-questo modo il primo argomento è sempre il nome del programma; un esempio di
-questo meccanismo è mostrato in fig.~\ref{fig:proc_argv_argc}.
+Indipendentemente da come viene eseguita, il risultato della scansione deve
+essere la costruzione del vettore di puntatori \param{argv} in cui si devono
+inserire in successione i puntatori alle stringhe costituenti i vari argomenti
+ed opzioni, e della variabile \param{argc} che deve essere inizializzata al
+numero di stringhe passate. Nel caso della shell questo comporta che il primo
+argomento sia sempre il nome del programma; un esempio di questo meccanismo è
+mostrato in fig.~\ref{fig:proc_argv_argc}.
\subsection{La gestione delle opzioni}
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
+ parametro all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e $-1$ se non
esistono altre opzioni.}
\end{prototype}
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
+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 \param{optstring} viene ritornato il carattere \texttt{'?'}
mentre se un'opzione che lo richiede non è seguita da un parametro viene
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}.
-
+elemento che non è un'opzione.
-\subsection{Opzioni in formato esteso}
-\label{sec:proc_opt_extended}
+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}.
-Un'estensione di questo schema è costituita dalle cosiddette
-\textit{long-options} espresse nella forma \cmd{-{}-option=parameter}, anche
-la gestione di queste ultime è stata standardizzata attraverso l'uso di una
-versione estesa di \func{getopt}.
-
-(NdA: questa parte verrà inserita in seguito).
-% TODO opzioni in formato esteso
\subsection{Le variabili di ambiente}
\label{sec:proc_environ}
-Oltre agli argomenti passati a linea di comando ogni processo riceve dal
-sistema un \textsl{ambiente}, nella forma di una lista di variabili (detta
-\textit{environment list}) messa a disposizione dal processo, e costruita
-nella chiamata alla funzione \func{exec} quando questo viene lanciato.
-
-Come per la lista degli argomenti anche questa lista è un vettore di puntatori
-a caratteri, ciascuno dei quali punta ad una stringa, terminata da un
+Oltre agli argomenti passati a linea di comando esiste un'altra modalità che
+permette di trasferire ad un processo delle informazioni in modo da
+modificarne il comportamento. Ogni processo infatti riceve dal sistema, oltre
+alle variabili \param{argv} e \param{argc} anche un \textsl{ambiente} (in
+inglese \textit{environment}); questo viene espresso nella forma di una lista
+(chiamata \textit{environment list}) delle cosiddette \textsl{variabili di
+ ambiente}, i valori di queste variabili possono essere poi usati dal
+programma.
+
+Anche in questo caso la lista delle \textsl{variabili di ambiente} deve essere
+costruita ed utilizzata nella chiamata alla funzione \func{exec} (torneremo su
+questo in sez.~\ref{sec:proc_exec}) quando questo viene lanciato. Come per la
+lista degli argomenti anche questa lista è un vettore di puntatori a
+caratteri, ciascuno dei quali punta ad una stringa, terminata da un
\val{NULL}. A differenza di \code{argv[]} in questo caso non si ha una
lunghezza del vettore 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
-variabile globale \var{environ}, a cui si può accedere attraverso una semplice
+variabile globale \var{environ}, che viene definita automaticamente per
+cisascun processo, e a cui si può accedere attraverso una semplice
dichiarazione del tipo:
\includecodesnip{listati/env_ptr.c}
un esempio della struttura di questa lista, contenente alcune delle variabili
fig.~\ref{fig:proc_envirno_list}.
\begin{figure}[htb]
\centering
- \includegraphics[width=13cm]{img/environ_var}
+ \includegraphics[width=15 cm]{img/environ_var}
\caption{Esempio di lista delle variabili di ambiente.}
\label{fig:proc_envirno_list}
\end{figure}
Per convenzione le stringhe che definiscono l'ambiente sono tutte del tipo
-\textsl{\texttt{nome=valore}}. Inoltre alcune variabili, come quelle elencate
-in fig.~\ref{fig:proc_envirno_list}, sono definite dal sistema per essere usate
+\textsl{\texttt{nome=valore}} ed in questa forma che le funzioni di gestione
+che vedremo a breve se le aspettano, se pertanto si dovesse costruire
+manualemente un ambiente si abbia cura di rispettare questa convenzione.
+Inoltre alcune variabili, come quelle elencate in
+fig.~\ref{fig:proc_envirno_list}, sono definite dal sistema per essere usate
da diversi programmi e funzioni: per queste c'è l'ulteriore convenzione di
-usare nomi espressi in caratteri maiuscoli.\footnote{la convenzione vuole che
- si usino dei nomi maiuscoli per le variabili di ambiente di uso generico, i
- nomi minuscoli sono in genere riservati alle variabili interne degli script
- di shell.}
+usare nomi espressi in caratteri maiuscoli.\footnote{ma si tratta solo di una
+ convenzione, niente vieta di usare caratteri minuscoli.}
Il kernel non usa mai queste variabili, il loro uso e la loro interpretazione è
riservata alle applicazioni e ad alcune funzioni di libreria; in genere esse
queste variabili al programma messo in esecuzione attraverso un uso opportuno
delle relative chiamate (si veda sez.~\ref{sec:proc_exec}).
-La shell ad esempio ne usa molte per il suo funzionamento (come \texttt{PATH}
-per la ricerca dei comandi, o \texttt{IFS} per la scansione degli argomenti),
-e alcune di esse (come \texttt{HOME}, \texttt{USER}, ecc.) sono definite al
-login (per i dettagli si veda sez.~\ref{sec:sess_login}). In genere è cura
-dell'amministratore definire le opportune variabili di ambiente in uno script
-di avvio. Alcune servono poi come riferimento generico per molti programmi
-(come \texttt{EDITOR} che indica l'editor preferito da invocare in caso di
-necessità).
+La shell ad esempio ne usa molte per il suo funzionamento, come \texttt{PATH}
+per indicare la lista delle directory in cui effettuare la ricerca dei comandi
+o \texttt{PS1} per impostare il proprio \textit{prompt}. Alcune di esse, come
+\texttt{HOME}, \texttt{USER}, ecc. sono invece definite al login (per i
+dettagli si veda sez.~\ref{sec:sess_login}), ed in genere è cura della propria
+distribuzione definire le opportune variabili di ambiente in uno script di
+avvio. Alcune servono poi come riferimento generico per molti programmi, come
+\texttt{EDITOR} che indica l'editor preferito da invocare in caso di
+necessità. Una in particolare, \texttt{LANG}, serve a controllare la
+localizzazione del programma (su cui torneremo in
+sez.~\ref{sec:proc_localization}) per adattarlo alla lingua ed alle convezioni
+dei vari paesi.
Gli standard POSIX e XPG3 definiscono alcune di queste variabili (le più
comuni), come riportato in tab.~\ref{tab:proc_env_var}. GNU/Linux le supporta
-tutte e ne definisce anche altre: per una lista più completa si può
-controllare \cmd{man 5 environ}.
+tutte e ne definisce anche altre, in particolare poi alcune funzioni di
+libreria prevedono la presenza di specifiche variabili di ambiente che ne
+modificano il comportamento, come quelle usate per indicare una localizzazione
+e quelle per indicare un fuso orario; una lista più completa che comprende
+queste ed ulteriori variabili si può ottenere con il comando \cmd{man 7
+ environ}.
\begin{table}[htb]
\centering
\funcdecl{int putenv(char *string)} Aggiunge la stringa \param{string}
all'ambiente.
- \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 per un
+ \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e $-1$ per un
errore, che è sempre \errval{ENOMEM}.}
\end{functions}
-\noindent la terza, \funcd{unsetenv}, serve a cancellare una variabile di
-ambiente; il suo prototipo è:
+
+La terza funzione della lista, \funcd{unsetenv}, serve a cancellare una
+variabile dall'ambiente, il suo prototipo è:
\begin{functions}
\headdecl{stdlib.h}
\funcdecl{void unsetenv(const char *name)} Rimuove la variabile di ambiente
\param{name}.
\end{functions}
-\noindent questa funzione elimina ogni occorrenza della variabile specificata;
-se essa non esiste non succede nulla. Non è prevista (dato che la funzione è
+
+\noindent la funzione elimina ogni occorrenza della variabile specificata; se la
+variabile non esiste non succede nulla. Non è prevista (dato che la funzione è
\ctyp{void}) nessuna segnalazione di errore.
Per modificare o aggiungere una variabile di ambiente si possono usare sia
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
-\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 \direct{const} dal prototipo.} \param{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 a
-questa funzione una variabile automatica (per evitare i problemi esposti in
-sez.~\ref{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
-carattere \texttt{'='}) 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 un'allocazione
-fatta in precedenza da un'altra \func{putenv}. Questo perché il vettore delle
-variabili di ambiente iniziale, creato dalla chiamata ad \func{exec} (vedi
-sez.~\ref{sec:proc_exec}) è piazzato al di sopra dello \itindex{stack} stack,
-(vedi fig.~\ref{fig:proc_mem_layout}) e non nello \itindex{heap} \textit{heap}
-e non può essere deallocato. Inoltre la memoria associata alle variabili di
-ambiente eliminate non viene liberata.
-
-L'ultima funzione è \funcd{clearenv}, che viene usata per cancellare
-completamente tutto l'ambiente; il suo prototipo è:
+\param{string}.
+
+Si tenga presente che, seguendo lo standard SUSv2, le \acr{glibc} successive
+alla versione 2.1.2 aggiungono \param{string} alla lista delle variabili di
+ambiente;\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 \direct{const} dal prototipo.} pertanto ogni
+cambiamento alla stringa in questione si riflette automaticamente
+sull'ambiente, e quindi si deve evitare di passare a questa funzione una
+variabile automatica (per evitare i problemi esposti in
+sez.~\ref{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 carattere \texttt{'='}) allora questa viene
+cancellata dall'ambiente.
+
+Infine quando chiamata a \func{putenv} comporta la necessità di creare una
+nuova versione del vettore \var{environ} questo sarà allocato automaticamente,
+ma la versione corrente sarà deallocata solo se anch'essa è risultante da
+un'allocazione fatta in precedenza da un'altra \func{putenv}. Questo avviene
+perché il vettore delle variabili di ambiente iniziale, creato dalla chiamata
+ad \func{exec} (vedi sez.~\ref{sec:proc_exec}) è piazzato nella memoria al di
+sopra dello \itindex{stack} stack, (vedi fig.~\ref{fig:proc_mem_layout}) e non
+nello \itindex{heap} \textit{heap} e quindi non può essere deallocato.
+Inoltre la memoria associata alle variabili di ambiente eliminate non viene
+liberata.
+
+L'ultima funzione per la gestione dell'ambiente è \funcd{clearenv}, che viene
+usata per cancellare completamente tutto l'ambiente; il suo prototipo è:
\begin{functions}
\headdecl{stdlib.h}
alla cancellazione di tutto l'ambiente per costruirne una versione
``\textsl{sicura}'' da zero.
+\subsection{La localizzazione}
+\label{sec:proc_localization}
+
+Abbiamo accennato in sez.~\ref{sec:proc_environ} come la variabile di ambiente
+\texttt{LANG} sia usata per indicare ai processi il valore della cosiddetta
+\textsl{localizzazione}. Si tratta di una funzionalità fornita dalle librerie
+di sistema\footnote{prenderemo in esame soltanto il caso delle \acr{glibc}.}
+che consente di gestire in maniera automatica sia la lingua in cui vengono
+stampati i vari messaggi (come i messaggi associati agli errori che vedremo in
+sez.~\ref{sec:sys_strerror}) che le convenzioni usate nei vari paesi per una
+serie di aspetti come il formato dell'ora, quello delle date, gli ordinamenti
+alfabetici, le espressioni della valute, ecc.
+
+La localizzazione di un programma si può selezionare con la
+
+
+In realtà perché un programma sia effettivamente localizzato non è sufficiente
+
+% TODO trattare, quando ci sarà tempo, setlocale ed il resto
+
+
+%\subsection{Opzioni in formato esteso}
+%\label{sec:proc_opt_extended}
+
+%Oltre alla modalità ordinaria di gestione delle opzioni trattata in
+%sez.~\ref{sec:proc_opt_handling} le \acr{glibc} forniscono una modalità
+%alternativa costituita dalle cosiddette \textit{long-options}, che consente di
+%esprimere le opzioni in una forma più descrittiva che nel caso più generale è
+%qualcosa del tipo di ``\texttt{-{}-option-name=parameter}''.
+
+%(NdA: questa parte verrà inserita in seguito).
+
+% TODO opzioni in formato esteso
\section{Problematiche di programmazione generica}
\label{sec:proc_gen_prog}
realizzato a livello delle librerie standard del C che provvedono gli
strumenti adeguati. L'uso di una \textit{variadic function} prevede quindi
tre punti:
-\begin{itemize}
+\begin{itemize*}
\item \textsl{Dichiarare} la funzione come \textit{variadic} usando un
prototipo che contenga una \textit{ellipsis}.
\item \textsl{Definire} la funzione come \textit{variadic} usando la stessa
gestione di un numero variabile di argomenti.
\item \textsl{Invocare} la funzione specificando prima gli argomenti fissi, ed
a seguire quelli addizionali.
-\end{itemize}
+\end{itemize*}
Lo standard ISO C prevede che una \index{variadic} \textit{variadic function}
abbia sempre almeno un argomento fisso; prima di effettuare la dichiarazione
sequenziale; essi verranno estratti dallo \itindex{stack} \textit{stack}
secondo l'ordine in cui sono stati scritti. Per fare questo in \file{stdarg.h}
sono definite delle apposite macro; la procedura da seguire è la seguente:
-\begin{enumerate}
+\begin{enumerate*}
\item Inizializzare un puntatore alla lista degli argomenti di tipo
\macro{va\_list} attraverso la macro \macro{va\_start}.
\item Accedere ai vari argomenti opzionali con chiamate successive alla macro
il secondo e così via.
\item Dichiarare la conclusione dell'estrazione degli argomenti invocando la
macro \macro{va\_end}.
-\end{enumerate}
+\end{enumerate*}
In generale è perfettamente legittimo richiedere meno argomenti di quelli che
potrebbero essere stati effettivamente forniti, e nella esecuzione delle
\macro{va\_arg} ci si può fermare in qualunque momento ed i restanti argomenti
immediate è quella di specificare il numero degli argomenti opzionali come uno
degli argomenti fissi. Una variazione di questo metodo è l'uso di un argomento
per specificare anche il tipo degli argomenti (come fa la stringa di formato
-per \func{printf}).
+per \func{printf}).
Una modalità diversa, che può essere applicata solo quando il tipo degli
argomenti lo rende possibile, è quella che prevede di usare un valore speciale
% LocalWords: SUCCESS FAILURE void atexit stream fclose unistd descriptor init
% LocalWords: SIGCHLD wait function glibc SunOS arg argp execve fig high kb Mb
% LocalWords: memory alpha swap table printf Unit MMU paging fault SIGSEGV BSS
-% LocalWords: multitasking segmentation text segment NULL Block Started Symbol
+% LocalWords: multitasking text segment NULL Block Started Symbol
% LocalWords: heap stack calling convention size malloc calloc realloc nmemb
% LocalWords: ENOMEM ptr uClib cfree error leak smartpointers hook Dmalloc brk
% LocalWords: Gray Watson Electric Fence Bruce Perens sbrk longjmp SUSv BSD ap
% LocalWords: clearenv libc value overwrite string reference result argument
% LocalWords: socket variadic ellipsis header stdarg execl self promoting last
% LocalWords: float double short register type dest src extern setjmp jmp buf
-% LocalWords: env return if while sottoprocesso Di
+% LocalWords: env return if while Di page cdecl
+% LocalWords: environment
%%% Local Variables:
%%% mode: latex