%% process.tex
%%
-%% Copyright (C) 2000-2018 by Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2019 by 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",
chiusura invocando direttamente la funzione \func{exit}. Queste due modalità
sono assolutamente equivalenti, dato che \func{exit} viene chiamata in maniera
trasparente anche quando \code{main} ritorna, passandogli come argomento il
-valore di ritorno.
+valore indicato da \instruction{return}.
La funzione \funcd{exit}, che è completamente generale, essendo definita dallo
standard ANSI C, è quella che deve essere invocata per una terminazione
\itindbeg{exit~status}
-Il valore dell'argomento \param{status} o il valore di ritorno di \code{main},
+Il valore dell'argomento \param{status} o il valore di ritorno di \code{main}
costituisce quello che viene chiamato lo \textsl{stato di uscita}
(l'\textit{exit status}) del processo. In generale si usa questo valore per
fornire al processo padre (come vedremo in sez.~\ref{sec:proc_wait}) delle
Anche se l'argomento \param{status} (ed il valore di ritorno di \code{main})
sono numeri interi di tipo \ctyp{int}, si deve tener presente che il valore
-dello stato di uscita viene comunque troncato ad 8 bit,
-per cui deve essere sempre compreso fra 0 e 255. Si tenga presente che se si
-raggiunge la fine della funzione \code{main} senza ritornare esplicitamente si
-ha un valore di uscita indefinito, è pertanto consigliabile di concludere
-sempre in maniera esplicita detta funzione.
-
-Non esiste un valore significato intrinseco della stato di uscita, ma una
-convenzione in uso pressoché universale è quella di restituire 0 in caso di
-successo e 1 in caso di fallimento. Una eccezione a questa convenzione è per i
-programmi che effettuano dei confronti (come \cmd{diff}), che usano 0 per
-indicare la corrispondenza, 1 per indicare la non corrispondenza e 2 per
-indicare l'incapacità di effettuare il confronto. Un'altra convenzione riserva
-i valori da 128 a 256 per usi speciali: ad esempio 128 viene usato per
-indicare l'incapacità di eseguire un altro programma in un
-sottoprocesso. Benché le convenzioni citate non siano seguite universalmente è
-una buona idea tenerle presenti ed adottarle a seconda dei casi.
+dello stato di uscita viene comunque troncato ad 8 bit, per cui deve essere
+sempre compreso fra 0 e 255. Si tenga presente che se si raggiunge la fine
+della funzione \code{main} senza ritornare esplicitamente si ha un valore di
+uscita indefinito, è pertanto consigliabile di concludere sempre in maniera
+esplicita detta funzione.
+
+Non esiste un significato intrinseco della stato di uscita, ma una convenzione
+in uso pressoché universale è quella di restituire 0 in caso di successo e 1
+in caso di fallimento. Una eccezione a questa convenzione è per i programmi
+che effettuano dei confronti (come \cmd{diff}), che usano 0 per indicare la
+corrispondenza, 1 per indicare la non corrispondenza e 2 per indicare
+l'incapacità di effettuare il confronto. Un'altra convenzione riserva i valori
+da 128 a 256 per usi speciali: ad esempio 128 viene usato per indicare
+l'incapacità di eseguire un altro programma in un sottoprocesso. Benché le
+convenzioni citate non siano seguite universalmente è una buona idea tenerle
+presenti ed adottarle a seconda dei casi.
Si tenga presente inoltre che non è una buona idea usare eventuali codici di
errore restituiti nella variabile \var{errno} (vedi sez.~\ref{sec:sys_errors})
Una forma alternativa per effettuare una terminazione esplicita di un
programma è quella di chiamare direttamente la \textit{system call}
\funcd{\_exit},\footnote{la stessa è definita anche come \funcd{\_Exit} in
- \headfile{stdlib.h}, inoltre a partire dalle \acr{glibc} 2.3 usando questa
+ \headfile{stdlib.h}, inoltre a partire dalla \acr{glibc} 2.3 usando questa
funzione viene invocata \func{exit\_group} che termina tutti i
\textit{thread} del processo e non solo quello corrente (fintanto che non si
usano i \textit{thread}\unavref{, vedi sez.~\ref{cha:threads},} questo non
sez.~\ref{sec:files_std_interface}). Infine fa sì che ogni figlio del processo
sia adottato da \cmd{init} (vedi sez.~\ref{sec:proc_termination}), manda un
segnale \signal{SIGCHLD} al processo padre (vedi
-sez.~\ref{sec:sig_job_control}) e ritorna lo stato di uscita specificato
-in \param{status} che può essere raccolto usando la funzione \func{wait} (vedi
+sez.~\ref{sec:sig_job_control}) e salva lo stato di uscita specificato in
+\param{status} che può essere raccolto usando la funzione \func{wait} (vedi
sez.~\ref{sec:proc_wait}).
Si tenga presente infine che oltre alla conclusione ``\textsl{normale}''
\label{sec:proc_atexit}
Un'esigenza comune che si incontra è quella di dover effettuare una serie di
-operazioni di pulizia (ad esempio salvare dei dati, ripristinare delle
-impostazioni, eliminare dei file temporanei, ecc.) prima della conclusione di
-un programma. In genere queste operazioni vengono fatte in un'apposita sezione
-del programma, ma quando si realizza una libreria diventa antipatico dover
-richiedere una chiamata esplicita ad una funzione di pulizia al programmatore
-che la utilizza.
+operazioni di pulizia prima della conclusione di un programma, ad esempio
+salvare dei dati, ripristinare delle impostazioni, eliminare dei file
+temporanei, ecc. In genere queste operazioni vengono fatte in un'apposita
+sezione del programma, ma quando si realizza una libreria diventa antipatico
+dover richiedere una chiamata esplicita ad una funzione di pulizia al
+programmatore che la utilizza.
È invece molto meno soggetto ad errori, e completamente trasparente
all'utente, avere la possibilità di fare effettuare automaticamente la
deve prendere argomenti e non deve ritornare niente. In sostanza deve la
funzione di pulizia dovrà essere definita come \code{void function(void)}.
-Un'estensione di \func{atexit} è la funzione \funcd{on\_exit}, che le
-\acr{glibc} includono per compatibilità con SunOS ma che non è detto sia
-definita su altri sistemi,\footnote{non essendo prevista dallo standard POSIX
- è in genere preferibile evitarne l'uso.} il suo prototipo è:
+Un'estensione di \func{atexit} è la funzione \funcd{on\_exit}, che la
+\acr{glibc} include per compatibilità con SunOS ma che non è detto sia
+definita su altri sistemi,\footnote{la funzione è disponibile dalla
+ \acr{glibc} 2.19 definendo la macro \macro{\_DEFAULT\_SOURCE}, mentre in
+ precedenza erano necessarie \macro{\_BSD\_SOURCE} o \macro{\_SVID\_SOURCE};
+ non essendo prevista dallo standard POSIX è in generale preferibile evitarne
+ l'uso.} il suo prototipo è:
\begin{funcproto}{
\fhead{stdlib.h}
\begin{figure}[htb]
\centering
-% \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{\textsf{kernel}}};
+ \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{\textsf{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{execve}};
+ % \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{execve}};
- \filldraw[fill=black!15,rounded corners] (1.5,4) rectangle (4,5);
- \draw (2.75,4.5) node {\texttt{main}};
+ % \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}};
+ % \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}};
+ % \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 [<->, 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 (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[->] (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]{\textsf{exit handler}};
- \draw (10,5.5) node (exithandler2) [rectangle,fill=black!15,rounded corners, draw]{\textsf{exit handler}};
- \draw (10,3.5) node (stream) [rectangle,fill=black!15,rounded corners, draw]{\textsf{chiusura stream}};
+ % \draw (10,4.5) node (exithandler1) [rectangle,fill=black!15,rounded corners, draw]{\textsf{exit handler}};
+ % \draw (10,5.5) node (exithandler2) [rectangle,fill=black!15,rounded corners, draw]{\textsf{exit handler}};
+ % \draw (10,3.5) node (stream) [rectangle,fill=black!15,rounded corners, draw]{\textsf{chiusura stream}};
- \draw[<->, dashed] (exithandler1) -- (exit);
- \draw[<->, dashed] (exithandler2) -- (exit);
- \draw[<->, dashed] (stream) -- (exit);
- \end{tikzpicture}
+ % \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}
\itindend{page~fault}
-Normalmente questo è il prezzo da pagare per avere un multitasking reale, ed
-in genere il sistema è molto efficiente in questo lavoro; quando però ci siano
-esigenze specifiche di prestazioni è possibile usare delle funzioni che
-permettono di bloccare il meccanismo della paginazione e mantenere fisse delle
-pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}).
+Normalmente questo è il prezzo da pagare per avere un \textit{multitasking}
+reale, ed in genere il sistema è molto efficiente in questo lavoro; quando
+però ci siano esigenze specifiche di prestazioni è possibile usare delle
+funzioni che permettono di bloccare il meccanismo della paginazione e
+mantenere fisse delle pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}).
\index{paginazione|)}
\index{memoria~virtuale|)}
\begin{figure}[htb]
\centering
-% \includegraphics[height=12cm]{img/memory_layout}
- \begin{tikzpicture}
- \draw (0,0) rectangle (4,1);
- \draw (2,0.5) node {\textit{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 {\textit{heap}};
- \draw (2,8.5) node {\textit{stack}};
- \draw [->] (2,6) -- (2,6.5);
- \draw [->] (2,8) -- (2,7.5);
- \draw (0,9) rectangle (4,10);
- \draw (2,9.5) node {\textit{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}
+ \includegraphics[height=10cm]{img/memory_layout}
+ % \begin{tikzpicture}
+ % \draw (0,0) rectangle (4,1);
+ % \draw (2,0.5) node {\textit{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 {\textit{heap}};
+ % \draw (2,8.5) node {\textit{stack}};
+ % \draw [->] (2,6) -- (2,6.5);
+ % \draw [->] (2,8) -- (2,7.5);
+ % \draw (0,9) rectangle (4,10);
+ % \draw (2,9.5) node {\textit{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}
In genere si usano \func{malloc} e \func{calloc} per allocare dinamicamente
un'area di memoria.\footnote{queste funzioni presentano un comportamento
- diverso fra le \acr{glibc} e le \acr{uClib} quando il valore di \param{size}
+ diverso fra la \acr{glibc} e la \acr{uClib} quando il valore di \param{size}
è nullo. Nel primo caso viene comunque restituito un puntatore valido,
anche se non è chiaro a cosa esso possa fare riferimento, nel secondo caso
viene restituito \val{NULL}. Il comportamento è analogo con
Questa funzione vuole come argomento \var{ptr} il puntatore restituito da una
precedente chiamata ad una qualunque delle funzioni di allocazione che non sia
-già stato liberato da un'altra chiamata a \func{free}. Se il valore
-di \param{ptr} è \val{NULL} la funzione non fa niente, mentre se l'area di
-memoria era già stata liberata da un precedente chiamata il comportamento
+già stato liberato da un'altra chiamata a \func{free}. Se il valore di
+\param{ptr} è \val{NULL} la funzione non fa niente, mentre se l'area di
+memoria era già stata liberata da una precedente chiamata il comportamento
della funzione è dichiarato indefinito, ma in genere comporta la corruzione
dei dati di gestione dell'allocazione, che può dar luogo a problemi gravi, ad
esempio un \textit{segmentation fault} in una successiva chiamata di una di
modificare il puntatore nello \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
-\textit{segment violation} la prima volta che cercherà di accedere alla
+\textit{segment violation} la prima volta che si cerchi di accedere alla
memoria non effettivamente disponibile.
\index{segmento!dati|(}
\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 è:
+ \macro{\_SVID\_SOURCE} o \macro{\_DEFAULT\_SOURCE}.} il suo prototipo è:
\begin{funcproto}{
\fhead{unistd.h}
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
+pagine attualmente residenti in memoria saranno indicate da un valore non
nullo del byte corrispondente.
Dato che lo stato della memoria di un processo può cambiare continuamente, il
{Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EINVAL}] \param{len} non è un valore positivo.
+ \item[\errcode{EAGAIN}] una parte o tutto l'intervallo richiesto non può
+ essere bloccato per una mancanza temporanea di risorse.
+ \item[\errcode{EINVAL}] \param{len} non è un valore positivo o la somma con
+ \param{addr} causa un overflow.
\item[\errcode{ENOMEM}] alcuni indirizzi dell’intervallo specificato non
- corrispondono allo spazio di indirizzi del processo o si è superato il
- limite di \const{RLIMIT\_MEMLOCK} per un processo non privilegiato (solo
- per kernel a partire dal 2.6.9).
+ corrispondono allo spazio di indirizzi del processo o con \func{mlock} si
+ è superato il limite di \const{RLIMIT\_MEMLOCK} per un processo non
+ privilegiato (solo per kernel a partire dal 2.6.9) o si è superato il
+ limite di regioni di memoria con attributi diversi.
\item[\errcode{EPERM}] il processo non è privilegiato (per kernel precedenti
il 2.6.9) o si ha un limite nullo per \const{RLIMIT\_MEMLOCK} e
il processo non è privilegiato (per kernel a partire dal 2.6.9).
Le due funzioni permettono rispettivamente di bloccare e sbloccare la
paginazione per l'intervallo di memoria iniziante all'indirizzo \param{addr} e
-lungo \param{len} byte. Tutte le pagine che contengono una parte
-dell'intervallo bloccato sono mantenute in RAM per tutta la durata del
-blocco. Con kernel diversi da Linux si può ottenere un errore di
-\errcode{EINVAL} se \param{addr} non è un multiplo della dimensione delle
-pagine di memoria, pertanto se si ha a cuore la portabilità si deve avere cura
-di allinearne correttamente il valore.
-
-% TODO trattare mlock2, introdotta con il kernel 4.4 (vedi
-% http://lwn.net/Articles/650538/)
+lungo \param{len} byte. Al ritorno di \func{mlock} tutte le pagine che
+contengono una parte dell'intervallo bloccato sono garantite essere in RAM e
+vi verranno mantenute per tutta la durata del blocco. Con kernel diversi da
+Linux si può ottenere un errore di \errcode{EINVAL} se \param{addr} non è un
+multiplo della dimensione delle pagine di memoria, pertanto se si ha a cuore
+la portabilità si deve avere cura di allinearne correttamente il valore. Il
+blocco viene rimosso chiamando \func{munlock}.
Altre due funzioni di sistema, \funcd{mlockall} e \funcd{munlockall},
consentono di bloccare genericamente la paginazione per l'intero spazio di
L'argomento \param{flags} di \func{mlockall} permette di controllarne il
comportamento; esso deve essere specificato come maschera binaria dei valori
-espressi dalle costanti riportate in tab.~\ref{tab:mlockall_flags}.
+espressi dalle costanti riportate in tab.~\ref{tab:mlockall_flags}.
\begin{table}[htb]
\footnotesize
spazio di indirizzi del processo.\\
\constd{MCL\_FUTURE} & blocca tutte le pagine che verranno mappate nello
spazio di indirizzi del processo.\\
+ \constd{MCL\_ONFAULT}& esegue il blocco delle pagine selezionate solo
+ quando vengono utilizzate (dal kernel 4.4).\\
\hline
\end{tabular}
\caption{Valori e significato dell'argomento \param{flags} della funzione
Con \func{mlockall} si possono bloccare tutte le pagine mappate nello spazio
di indirizzi del processo, sia che comprendano il segmento di testo, di dati,
lo \textit{stack}, lo \textit{heap} e pure le funzioni di libreria chiamate, i
-file mappati in memoria, i dati del kernel mappati in user space, la memoria
-condivisa. L'uso dell'argomento \param{flags} permette di selezionare con
-maggior finezza le pagine da bloccare, ad esempio usando \const{MCL\_FUTURE}
-ci si può limitare a tutte le pagine allocate a partire dalla chiamata della
-funzione.
-
-In ogni caso un processo \textit{real-time} che deve entrare in una sezione
-critica (vedi sez.~\ref{sec:proc_race_cond}) deve provvedere a riservare
-memoria sufficiente prima dell'ingresso, per scongiurare l'occorrenza di un
-eventuale \textit{page fault} causato dal meccanismo di \textit{copy on
- write}. Infatti se nella sezione critica si va ad utilizzare memoria che
-non è ancora stata riportata in RAM si potrebbe avere un \textit{page fault}
-durante l'esecuzione della stessa, con conseguente rallentamento
-(probabilmente inaccettabile) dei tempi di esecuzione.
-
-In genere si ovvia a questa problematica chiamando una funzione che ha
-allocato una quantità sufficientemente ampia di variabili automatiche, in modo
-che esse vengano mappate in RAM dallo \textit{stack}, dopo di che, per essere
-sicuri che esse siano state effettivamente portate in memoria, ci si scrive
-sopra.
+file mappati in memoria, i dati del kernel mappati in \textit{user space}, la
+memoria condivisa. L'uso dell'argomento \param{flags} permette di selezionare
+con maggior finezza le pagine da bloccare, ad esempio usando
+\const{MCL\_FUTURE} ci si può limitare a tutte le pagine allocate a partire
+dalla chiamata della funzione, mentre \const{MCL\_CURRENT} blocca tutte quelle
+correntemente mappate. L'uso di \func{munlockall} invece sblocca sempre tutte
+le pagine di memoria correntemente mappate nello spazio di indirizzi del
+programma.
+
+A partire dal kernel 4.4 alla funzione \func{mlockall} è stato aggiunto un
+altro flag, \const{MCL\_ONFAULT}, che può essere abbinato a entrambi gli altri
+due flag, e consente di modificare il comportamento della funzione per
+ottenere migliori prestazioni.
+
+Il problema che si presenta infatti è che eseguire un \textit{memory lock} per
+un intervallo ampio di memoria richiede che questa venga comunque allocata in
+RAM, con altrettanti \textit{page fault} che ne assicurino la presenza; questo
+vale per tutto l'intervallo e può avere un notevole costo in termini di
+prestazioni, anche quando poi, nell'esecuzione del programma, venisse usata
+solo una piccola parte dello stesso. L'uso di \const{MCL\_ONFAULT} previene il
+\textit{page faulting} immediato di tutto l'intervallo, le pagine
+dell'intervallo verranno bloccate, ma solo quando un \textit{page fault}
+dovuto all'accesso ne richiede l'allocazione effettiva in RAM.
+
+Questo stesso comportamento non è ottenibile con \func{mlock}, che non dispone
+di un argomento \param{flag} che consenta di richiederlo, per questo sempre
+con il kernel 4.4 è stata aggiunta una ulteriore funzione di sistema,
+\funcd{mlock2}, il cui prototipo è:
+
+\begin{funcproto}{
+ \fhead{sys/mman.h}
+ \fdecl{int mlock2(const void *addr, size\_t len, int flags)}
+ \fdesc{Blocca la paginazione su un intervallo di memoria.}
+}
+{Le funzione ritornano $0$ in caso di successo e $-1$ in caso di errore, nel
+ qual caso \var{errno} assume gli stessi valori di \func{mlock} con
+ l'aggiunta id un possibile \errcode{EINVAL} anche se si è indicato un valore
+ errato di \param{flags}.}
+\end{funcproto}
+
+% NOTA: per mlock2, introdotta con il kernel 4.4 (vedi
+% http://lwn.net/Articles/650538/)
+
+Indicando un valore nullo per \param{flags} il comportamento della funzione è
+identico a quello di \func{mlock}, l'unico altro valore possibile è
+\constd{MLOCK\_ONFAULT} che ha lo stesso effetto sull'allocazione delle pagine
+in RAM già descritto per \const{MCL\_ONFAULT}.
+
+Si tenga presente che un processo \textit{real-time} che intende usare il
+\textit{memory locking} con \func{mlockall} per prevenire l'avvenire di un
+eventuale \textit{page fault} ed il conseguente rallentamento (probabilmente
+inaccettabile) dei tempi di esecuzione, deve comunque avere delle accortezze.
+In particolare si deve assicurare di aver preventivamente bloccato una
+quantità di spazio nello \textit{stack} sufficiente a garantire l'esecuzione
+di tutte le funzioni che hanno i requisiti di criticità sui tempi. Infatti,
+anche usando \const{MCL\_FUTURE}, in caso di allocazione di una nuova pagina
+nello \textit{stack} durante l'esecuzione di una funzione (precedentemente non
+usata e quindi non bloccata) si potrebbe avere un \textit{page fault}.
+
+In genere si ovvia a questa problematica chiamando inizialmente una funzione
+che definisca una quantità sufficientemente ampia di variabili automatiche
+(che si ricordi vengono allocate nello \textit{stack}) e ci scriva, in modo da
+esser sicuri che le corrispondenti pagine vengano mappate nello spazio di
+indirizzi del processo, per poi bloccarle. La scrittura è necessaria perché il
+kernel usa il meccanismo di \textit{copy on write} (vedi
+sez.~\ref{sec:proc_fork}) e le pagine potrebbero non essere allocate
+immediatamente.
\itindend{memory~locking}
\index{memoria~virtuale|)}
funzione specifica.
Tradizionalmente per rispondere a questa esigenza sono state create due
-funzioni diverse, \funcd{memalign} e \funcd{valloc}, oggi obsolete; i
-rispettivi prototipi sono:
+funzioni diverse, \funcd{memalign} e \funcd{valloc}, oggi obsolete, cui si
+aggiunge \funcd{pvalloc} come estensione GNU, anch'essa obsoleta; i rispettivi
+prototipi sono:
\begin{funcproto}{
\fhead{malloc.h}
\fdecl{void *memalign(size\_t boundary, size\_t size)}
\fdesc{Alloca un blocco di memoria allineato ad un multiplo
di \param{boundary}.}
+\fdecl{void *pvalloc(size\_t size)}
+\fdesc{Alloca un blocco di memoria allineato alla dimensione di una pagina di
+ memoria.}
}
{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}
\end{funcproto}
Le funzioni restituiscono il puntatore al buffer di memoria allocata di
-dimensioni pari a \param{size}, 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 dalla \acr{glibc} la
-memoria allocata con queste funzioni deve essere liberata con \func{free},
-cosa che non è detto accada con altre implementazioni.
+dimensioni pari a \param{size}, che per \func{memalign} sarà un multiplo di
+\param{boundary} mentre per \func{valloc} un multiplo della dimensione di una
+pagina di memoria; lo stesso vale per \func{pvalloc} che però arrotonda
+automaticamente la dimensione dell'allocazione al primo multiplo di una
+pagina. Nel caso della versione fornita dalla \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 e nessuna delle due
compare in POSIX.1, inoltre ci sono indicazioni discordi sui file che ne
contengono la definizione;\footnote{secondo SUSv2 \func{valloc} è definita in
- \headfile{stdlib.h}, mentre sia le \acr{glibc} che le precedenti \acr{libc4}
+ \headfile{stdlib.h}, mentre sia la \acr{glibc} che le precedenti \acr{libc4}
e \acr{libc5} la dichiarano in \headfile{malloc.h}, lo stesso vale per
\func{memalign} che in alcuni sistemi è dichiarata in \headfile{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 è:
+nuova \funcd{posix\_memalign}, che è stata standardizzata in POSIX.1d e
+disponibile dalla \acr{glibc} 2.1.91; il suo prototipo è:
\begin{funcproto}{
\fhead{stdlib.h}
caso di successo e \val{NULL} in caso di errore, nel qual caso \var{errno}
assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EINVAL}] \param{alignment} non è potenza di due e multiplo
+ \item[\errcode{EINVAL}] \param{alignment} non è potenza di due o un multiplo
di \code{sizeof(void *)}.
\item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'allocazione.
\end{errlist}}
due funzioni precedenti, ma a loro differenza restituisce direttamente come
valore di ritorno il codice di errore. Come per le precedenti la memoria
allocata con \func{posix\_memalign} deve essere disallocata con \func{free},
-che in questo caso però è quanto richiesto dallo standard. Si tenga presente
-infine che nessuna di queste funzioni inizializza il buffer di memoria
-allocato, il loro comportamento cioè è analogo, allineamento a parte, a quello
-di \func{malloc}.
+che in questo caso però è quanto richiesto dallo standard.
+
+Dalla versione 2.16 della \acr{glibc} è stata aggiunta anche la funzione
+\funcd{aligned\_alloc}, prevista dallo standard C11 (e disponibile definendo
+\const{\_ISOC11\_SOURCE}), il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{malloc.h}
+\fdecl{void *aligned\_alloc(size\_t alignment, size\_t size)}
+\fdesc{Alloca un blocco di memoria allineato ad un multiplo
+ di \param{alignment}.}
+}
+{La funzione ha gli stessi valori di ritorno e codici di errore di
+ \func{memalign}.}
+\end{funcproto}
+
+La funzione è identica a \func{memalign} ma richiede che \param{size} sia un
+multiplo di \param{alignment}. Infine si tenga presente infine che nessuna di
+queste funzioni inizializza il buffer di memoria allocato, il loro
+comportamento cioè è analogo, allineamento a parte, a quello di \func{malloc}.
Un secondo caso in cui risulta estremamente utile poter avere un maggior
controllo delle modalità di allocazione della memoria è quello in cui cercano
\fdecl{int mcheck(void (*abortfn) (enum mcheck\_status status))}
\fdesc{Attiva i controlli di consistenza delle allocazioni di memoria.}
}
-{La funzione ritorna $0$ in caso di successo e $-1$ per un errorre;
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore;
\var{errno} non viene impostata.}
\end{funcproto}
\begin{figure}[htb]
\centering
-% \includegraphics[width=13cm]{img/argv_argc}
-% \includegraphics[width=13cm]{img/argv_argc}
- \begin{tikzpicture}[>=stealth]
- \draw (0.5,2.5) rectangle (3.5,3);
- \draw (2,2.75) node {\texttt{argc = 5}};
- \draw (5,2.5) rectangle (8,3);
- \draw (6.5,2.75) node {\texttt{argv[0]}};
- \draw [->] (8,2.75) -- (9,2.75);
- \draw (9,2.75) node [anchor=west] {\texttt{"touch"}};
- \draw (5,2) rectangle (8,2.5);
- \draw (6.5,2.25) node {\texttt{argv[1]}};
- \draw [->] (8,2.25) -- (9,2.25);
- \draw (9,2.25) node [anchor=west] {\texttt{"-r"}};
- \draw (5,1.5) rectangle (8,2);
- \draw (6.5,1.75) node {\texttt{argv[2]}};
- \draw [->] (8,1.75) -- (9,1.75);
- \draw (9,1.75) node [anchor=west] {\texttt{"riferimento.txt"}};
- \draw (5,1.0) rectangle (8,1.5);
- \draw (6.5,1.25) node {\texttt{argv[3]}};
- \draw [->] (8,1.25) -- (9,1.25);
- \draw (9,1.25) node [anchor=west] {\texttt{"-m"}};
- \draw (5,0.5) rectangle (8,1.0);
- \draw (6.5,0.75) node {\texttt{argv[4]}};
- \draw [->] (8,0.75) -- (9,0.75);
- \draw (9,0.75) node [anchor=west] {\texttt{"questofile.txt"}};
- \draw (4.25,3.5) node{\texttt{"touch -r riferimento.txt -m questofile.txt"}};
-
- \end{tikzpicture}
+ \includegraphics[width=13cm]{img/argv_argc}
+ % \begin{tikzpicture}[>=stealth]
+ % \draw (0.5,2.5) rectangle (3.5,3);
+ % \draw (2,2.75) node {\texttt{argc = 5}};
+ % \draw (5,2.5) rectangle (8,3);
+ % \draw (6.5,2.75) node {\texttt{argv[0]}};
+ % \draw [->] (8,2.75) -- (9,2.75);
+ % \draw (9,2.75) node [anchor=west] {\texttt{"touch"}};
+ % \draw (5,2) rectangle (8,2.5);
+ % \draw (6.5,2.25) node {\texttt{argv[1]}};
+ % \draw [->] (8,2.25) -- (9,2.25);
+ % \draw (9,2.25) node [anchor=west] {\texttt{"-r"}};
+ % \draw (5,1.5) rectangle (8,2);
+ % \draw (6.5,1.75) node {\texttt{argv[2]}};
+ % \draw [->] (8,1.75) -- (9,1.75);
+ % \draw (9,1.75) node [anchor=west] {\texttt{"riferimento.txt"}};
+ % \draw (5,1.0) rectangle (8,1.5);
+ % \draw (6.5,1.25) node {\texttt{argv[3]}};
+ % \draw [->] (8,1.25) -- (9,1.25);
+ % \draw (9,1.25) node [anchor=west] {\texttt{"-m"}};
+ % \draw (5,0.5) rectangle (8,1.0);
+ % \draw (6.5,0.75) node {\texttt{argv[4]}};
+ % \draw [->] (8,0.75) -- (9,0.75);
+ % \draw (9,0.75) node [anchor=west] {\texttt{"questofile.txt"}};
+ % \draw (4.25,3.5) node{\texttt{"touch -r riferimento.txt -m questofile.txt"}};
+ % \end{tikzpicture}
\caption{Esempio dei valori di \param{argv} e \param{argc} generati nella
scansione di una riga di comando.}
\label{fig:proc_argv_argc}
carattere ``\texttt{-}'' e che non sia un singolo ``\texttt{-}'' o un
``\texttt{-{}-}'' viene considerato un'opzione. In genere le opzioni sono
costituite da una lettera singola (preceduta dal carattere ``\texttt{-}'') e
-possono avere o no un parametro associato. Un esempio tipico può essere quello
-mostrato in fig.~\ref{fig:proc_argv_argc}. In quel caso le opzioni sono
-\cmd{-r} e \cmd{-m} e la prima vuole un parametro mentre la seconda no
+possono avere o no un parametro associato.
+
+Un esempio tipico può essere quello mostrato in
+fig.~\ref{fig:proc_argv_argc}. In quel caso le opzioni sono \cmd{-r} e
+\cmd{-m} e la prima vuole un parametro mentre la seconda no
(\cmd{questofile.txt} è un argomento del programma, non un parametro di
\cmd{-m}).
``\texttt{-{}-}'' la scansione viene considerata conclusa, anche se vi sono
altri elementi di \param{argv} che cominciano con il carattere ``\texttt{-}''.
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{\codesamplewidth}
- \includecodesample{listati/option_code.c}
- \end{minipage}
- \normalsize
- \caption{Esempio di codice per la gestione delle opzioni.}
- \label{fig:proc_options_code}
-\end{figure}
-
Quando \func{getopt} trova un'opzione fra quelle indicate in \param{optstring}
essa ritorna il valore numerico del carattere, in questo modo si possono
eseguire azioni specifiche usando uno \instruction{switch}; la funzione
\item \var{int optopt} contiene il carattere dell'opzione non riconosciuta.
\end{itemize*}
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/option_code.c}
+ \end{minipage}
+ \normalsize
+ \caption{Esempio di codice per la gestione delle opzioni.}
+ \label{fig:proc_options_code}
+\end{figure}
+
In fig.~\ref{fig:proc_options_code} si è mostrata la sezione del programma
\file{fork\_test.c}, che useremo nel prossimo capitolo per effettuare dei test
sulla creazione dei processi, deputata alla decodifica delle opzioni a riga di
fig.~\ref{fig:proc_envirno_list}.
\begin{figure}[htb]
\centering
-% \includegraphics[width=15 cm]{img/environ_var}
- \begin{tikzpicture}[>=stealth]
- \draw (2,3.5) node {\textsf{Environment pointer}};
- \draw (6,3.5) node {\textsf{Environment list}};
- \draw (10.5,3.5) node {\textsf{Environment string}};
- \draw (0.5,2.5) rectangle (3.5,3);
- \draw (2,2.75) node {\texttt{environ}};
- \draw [->] (3.5,2.75) -- (4.5,2.75);
- \draw (4.5,2.5) rectangle (7.5,3);
- \draw (6,2.75) node {\texttt{environ[0]}};
- \draw (4.5,2) rectangle (7.5,2.5);
- \draw (6,2.25) node {\texttt{environ[1]}};
- \draw (4.5,1.5) rectangle (7.5,2);
- \draw (4.5,1) rectangle (7.5,1.5);
- \draw (4.5,0.5) rectangle (7.5,1);
- \draw (4.5,0) rectangle (7.5,0.5);
- \draw (6,0.25) node {\texttt{NULL}};
- \draw [->] (7.5,2.75) -- (8.5,2.75);
- \draw (8.5,2.75) node[right] {\texttt{HOME=/home/piccardi}};
- \draw [->] (7.5,2.25) -- (8.5,2.25);
- \draw (8.5,2.25) node[right] {\texttt{PATH=:/bin:/usr/bin}};
- \draw [->] (7.5,1.75) -- (8.5,1.75);
- \draw (8.5,1.75) node[right] {\texttt{SHELL=/bin/bash}};
- \draw [->] (7.5,1.25) -- (8.5,1.25);
- \draw (8.5,1.25) node[right] {\texttt{EDITOR=emacs}};
- \draw [->] (7.5,0.75) -- (8.5,0.75);
- \draw (8.5,0.75) node[right] {\texttt{OSTYPE=linux-gnu}};
- \end{tikzpicture}
+ \includegraphics[width=13cm]{img/environ_var}
+ % \begin{tikzpicture}[>=stealth]
+ % \draw (2,3.5) node {\textsf{Environment pointer}};
+ % \draw (6,3.5) node {\textsf{Environment list}};
+ % \draw (10.5,3.5) node {\textsf{Environment string}};
+ % \draw (0.5,2.5) rectangle (3.5,3);
+ % \draw (2,2.75) node {\texttt{environ}};
+ % \draw [->] (3.5,2.75) -- (4.5,2.75);
+ % \draw (4.5,2.5) rectangle (7.5,3);
+ % \draw (6,2.75) node {\texttt{environ[0]}};
+ % \draw (4.5,2) rectangle (7.5,2.5);
+ % \draw (6,2.25) node {\texttt{environ[1]}};
+ % \draw (4.5,1.5) rectangle (7.5,2);
+ % \draw (4.5,1) rectangle (7.5,1.5);
+ % \draw (4.5,0.5) rectangle (7.5,1);
+ % \draw (4.5,0) rectangle (7.5,0.5);
+ % \draw (6,0.25) node {\texttt{NULL}};
+ % \draw [->] (7.5,2.75) -- (8.5,2.75);
+ % \draw (8.5,2.75) node[right] {\texttt{HOME=/home/piccardi}};
+ % \draw [->] (7.5,2.25) -- (8.5,2.25);
+ % \draw (8.5,2.25) node[right] {\texttt{PATH=:/bin:/usr/bin}};
+ % \draw [->] (7.5,1.75) -- (8.5,1.75);
+ % \draw (8.5,1.75) node[right] {\texttt{SHELL=/bin/bash}};
+ % \draw [->] (7.5,1.25) -- (8.5,1.25);
+ % \draw (8.5,1.25) node[right] {\texttt{EDITOR=emacs}};
+ % \draw [->] (7.5,0.75) -- (8.5,0.75);
+ % \draw (8.5,0.75) node[right] {\texttt{OSTYPE=linux-gnu}};
+ % \end{tikzpicture}
\caption{Esempio di lista delle variabili di ambiente.}
\label{fig:proc_envirno_list}
\end{figure}
Oltre a questa funzione di lettura, che è l'unica definita dallo standard ANSI
C, nell'evoluzione dei sistemi Unix ne sono state proposte altre, da
-utilizzare per impostare, modificare e per cancellare le variabili di
+utilizzare per impostare, modificare e cancellare le variabili di
ambiente. Uno schema delle funzioni previste nei vari standard e disponibili
in Linux è riportato in tab.~\ref{tab:proc_env_func}. Tutte le funzioni sono
state comunque inserite nello standard POSIX.1-2001, ad eccetto di
vecchie \acr{libc4} e \acr{libc5}; nella \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,
+ standard il comportamento è stato modificato a partire dalla 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_var_passing}). Benché non sia richiesto dallo standard
+sez.~\ref{sec:proc_var_passing}). Benché non sia richiesto dallo standard,
nelle versioni della \acr{glibc} a partire dalla 2.1 la funzione è rientrante
(vedi sez.~\ref{sec:proc_reentrant}).
%\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à
+%sez.~\ref{sec:proc_opt_handling} la \acr{glibc} fornisce 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}''.
delle problematiche generali che possono emergere nella programmazione con
questo linguaggio e di quali precauzioni o accorgimenti occorre prendere per
risolverle. Queste problematiche non sono specifiche di sistemi unix-like o
-multitasking, ma avendo trattato in questo capitolo il comportamento dei
-processi visti come entità a sé stanti, le riportiamo qui.
+\textit{multitasking}, ma avendo trattato in questo capitolo il comportamento
+dei processi visti come entità a sé stanti, le riportiamo qui.
\subsection{Il passaggio di variabili e valori di ritorno nelle funzioni}
successive chiamate a \macro{va\_arg} non funzioneranno. Nel caso del
\cmd{gcc} l'uso di \macro{va\_end} può risultare inutile, ma è comunque
necessario usarla per chiarezza del codice, per compatibilità con diverse
-implementazioni e per eventuali eventuali modifiche future a questo
-comportamento.
+implementazioni e per eventuali modifiche future a questo comportamento.
Riassumendo la procedura da seguire per effettuare l'estrazione degli
argomenti di una funzione \textit{variadic} è la seguente:
\item come espressione a sé stante.
\end{itemize*}
-In generale, dato che l'unica differenza fra la chiamata diretta e quella
-ottenuta nell'uscita con un \func{longjmp} è costituita dal valore di ritorno
-di \func{setjmp}, pertanto quest'ultima viene usualmente chiamata all'interno
-di un una istruzione \instr{if} che permetta di distinguere i due casi.
+In generale, dato che l'unica differenza fra il risultato di una chiamata
+diretta di \func{setjmp} e quello ottenuto nell'uscita con un \func{longjmp} è
+costituita dal valore di ritorno della funzione, quest'ultima viene usualmente
+chiamata all'interno di un una istruzione \instr{if} che permetta di
+distinguere i due casi.
Uno dei punti critici dei salti non-locali è quello del valore delle
variabili, ed in particolare quello delle variabili automatiche della funzione
\itindbeg{endianness}
Un altro dei problemi di programmazione che può dar luogo ad effetti
-imprevisti è quello relativo alla cosiddetta \textit{endianness}. Questa è una
-caratteristica generale dell'architettura hardware di un computer che dipende
-dal fatto che la rappresentazione di un numero binario può essere fatta in due
-modi, chiamati rispettivamente \textit{big endian} e \textit{little endian} a
-seconda di come i singoli bit vengono aggregati per formare le variabili
-intere (ed in genere in diretta corrispondenza a come sono poi in realtà
-cablati sui bus interni del computer).
+imprevisti è quello relativo alla cosiddetta \textit{endianness}. Questa è
+una caratteristica generale dell'architettura hardware di un computer che
+dipende dal fatto che la rappresentazione di un numero binario può essere
+fatta in due modi, chiamati rispettivamente \textit{big endian} e
+\textit{little endian}, a seconda di come i singoli bit vengono aggregati per
+formare le variabili intere (ed in genere in diretta corrispondenza a come
+sono poi in realtà cablati sui bus interni del computer).
\begin{figure}[!htb]
\centering \includegraphics[height=3cm]{img/endianness}
In generale non ci si deve preoccupare della \textit{endianness} all'interno
di un programma fintanto che questo non deve generare o manipolare dei dati
-che sono scambiati con altre macchine, ad esempio tramite via rete o tramite
-dei file binari. Nel primo caso la scelta è già stata fatta nella
-standardizzazione dei protocolli, che hanno adottato il \textit{big endian}
-(che viene detto anche per questo \textit{network order} e vedremo in
-sez.~\ref{sec:sock_func_ord} le funzioni di conversione che devono essere
-usate.
+che sono scambiati con altre macchine, ad esempio via rete o tramite dei file
+binari. Nel primo caso la scelta è già stata fatta nella standardizzazione dei
+protocolli, che hanno adottato il \textit{big endian} (che viene detto anche
+per questo \textit{network order}); vedremo in sez.~\ref{sec:sock_func_ord} le
+funzioni di conversione che devono essere usate.
Nel secondo caso occorre sapere quale \textit{endianness} è stata usata nei
dati memorizzati sul file e tenerne conto nella rilettura e nella
% LocalWords: capability MEMLOCK limits getpagesize RLIMIT munlock sys const
% LocalWords: addr len EINVAL EPERM mlockall munlockall flags l'OR CURRENT IFS
% LocalWords: argc argv parsing questofile txt getopt optstring switch optarg
-% LocalWords: optind opterr optopt POSIXLY CORRECT long options NdA
+% LocalWords: optind opterr optopt POSIXLY CORRECT long options NdA group
% LocalWords: option parameter list environ PATH HOME XPG tab LOGNAME LANG PWD
% LocalWords: TERM PAGER TMPDIR getenv name SVr setenv unsetenv putenv opz gcc
% LocalWords: clearenv libc value overwrite string reference result argument
% LocalWords: is to LC SIG str mem wcs assert ctype dirent fcntl signal stdio
% LocalWords: times library utmp syscall number Filesystem Hierarchy pathname
% LocalWords: context assembler sysconf fork Dinamic huge segmentation program
-% LocalWords: break store Using
+% LocalWords: break store using intptr ssize overflow ONFAULT faulting alloc
+% LocalWords: scheduler pvalloc aligned ISOC ABCDEF
%%% Local Variables:
%%% mode: latex