From c53a9c94d93ca614b786db4f49176a4659e453e8 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Mon, 7 Oct 2013 07:41:52 +0000 Subject: [PATCH] Materiale vario su IPC e piccole correzioni, invertiti i capitoli su IPC e gestione avanzata dei file. --- gapil.tex | 2 +- ipc.tex | 269 ++++++++++++++++++++++++++++------------------------ process.tex | 2 +- 3 files changed, 148 insertions(+), 125 deletions(-) diff --git a/gapil.tex b/gapil.tex index 6f6bff9..56be07c 100644 --- a/gapil.tex +++ b/gapil.tex @@ -180,8 +180,8 @@ hyperfootnotes=false]{hyperref} \include{system} \include{signal} \include{session} -\include{ipc} \include{fileadv} +\include{ipc} \include{thread} % Commentare sotto se si genera la prima parte diff --git a/ipc.tex b/ipc.tex index 69c6760..520793d 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1,4 +1,4 @@ -<%% ipc.tex +%% ipc.tex %% %% Copyright (C) 2000-2013 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free @@ -2791,13 +2791,16 @@ si ha a cuore la portabilità. Questi comandi aggiuntivi sono: sez.~\ref{sec:sys_resource_limit}). \item[\const{SHM\_UNLOCK}] Disabilita il \itindex{memory~locking} \textit{memory locking} sul segmento di memoria condivisa. Fino al kernel - 2.6.9 solo l'amministratore poteva utilizzare questo comando. + 2.6.9 solo l'amministratore poteva utilizzare questo comando in + corrispondenza di un segmento da lui bloccato. \end{basedescript} -I primi tre comandi sono gli stessi già visti anche per le code di messaggi e -gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche -previste da Linux, che permettono di abilitare e disabilitare il meccanismo -della \index{memoria~virtuale} memoria virtuale per il segmento. +A questi due, come per \func{msgctl} e \func{semctl}, si aggiungono tre +ulteriori valori, \const{IPC\_INFO}, \const{MSG\_STAT} e \const{MSG\_INFO}, +introdotti ad uso del programma \cmd{ipcs} per ottenere le informazioni +generali relative alle risorse usate dai segmenti di memoria condivisa. Dato +che potranno essere modificati o rimossi in favore dell'uso di \texttt{/proc}, +non devono essere usati e non li tratteremo. L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT} e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura @@ -2810,25 +2813,29 @@ l'interfaccia prevede due funzioni, \funcd{shmat} e \func{shmdt}. La prima di queste serve ad agganciare un segmento al processo chiamante, in modo che quest'ultimo possa inserirlo nel suo spazio di indirizzi per potervi accedere; il suo prototipo è: -\begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/shm.h} - - \funcdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)} - Aggancia al processo un segmento di memoria condivisa. - - \bodydesc{La funzione restituisce l'indirizzo del segmento in caso di - successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà i - valori: - \begin{errlist} + +\begin{funcproto}{ +\fhead{sys/types.h} +\fhead{sys/shm.h} +\fdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)} + +\fdesc{Aggancia un segmento di memoria condivisa al processo chiamante.} +} + +{La funzione ritorna l'indirizzo del segmento in caso di successo e $-1$ (in + un cast a \type{void *}) per un errore, nel qual caso \var{errno} assumerà + uno dei valori: + \begin{errlist} \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al segmento nella modalità richiesta. \item[\errcode{EINVAL}] si è specificato un identificatore invalido per \param{shmid}, o un indirizzo non allineato sul confine di una pagina - per \param{shmaddr}. - \end{errlist} - ed inoltre \errval{ENOMEM}.} -\end{functions} + per \param{shmaddr} o il valore \val{NULL} indicando \const{SHM\_REMAP}. + \end{errlist} + ed inoltre \errval{ENOMEM} nel suo significato generico. + +} +\end{funcproto} La funzione inserisce un segmento di memoria condivisa all'interno dello spazio di indirizzi del processo, in modo che questo possa accedervi @@ -2852,13 +2859,14 @@ L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{lo standard come il valore di ritorno della funzione; in Linux è stato così con le \acr{libc4} e le \acr{libc5}, con il passaggio alla \acr{glibc} il tipo di \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di - ritorno un \ctyp{void *}.} deve essere associato il segmento, se il valore -specificato è \val{NULL} è il sistema a scegliere opportunamente un'area di -memoria libera (questo è il modo più portabile e sicuro di usare la funzione). -Altrimenti il kernel aggancia il segmento all'indirizzo specificato da -\param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il -limite di una pagina, cioè se è un multiplo esatto del parametro di sistema -\const{SHMLBA}, che in Linux è sempre uguale \const{PAGE\_SIZE}. + ritorno un \ctyp{void *} seguendo POSIX.1-2001.} deve essere associato il +segmento, se il valore specificato è \val{NULL} è il sistema a scegliere +opportunamente un'area di memoria libera (questo è il modo più portabile e +sicuro di usare la funzione). Altrimenti il kernel aggancia il segmento +all'indirizzo specificato da \param{shmaddr}; questo però può avvenire solo se +l'indirizzo coincide con il limite di una pagina, cioè se è un multiplo esatto +del parametro di sistema \const{SHMLBA}, che in Linux è sempre uguale +\const{PAGE\_SIZE}. Si tenga presente però che quando si usa \val{NULL} come valore di \param{shmaddr}, l'indirizzo restituito da \func{shmat} può cambiare da @@ -2867,15 +2875,17 @@ anche degli indirizzi, si deve avere cura di usare valori relativi (in genere riferiti all'indirizzo di partenza del segmento). L'argomento \param{shmflg} permette di cambiare il comportamento della -funzione; esso va specificato come maschera binaria, i bit utilizzati sono -solo due e sono identificati dalle costanti \const{SHM\_RND} e -\const{SHM\_RDONLY}, che vanno combinate con un OR aritmetico. Specificando -\const{SHM\_RND} si evita che \func{shmat} ritorni un errore quando -\param{shmaddr} non è allineato ai confini di una pagina. Si può quindi usare -un valore qualunque per \param{shmaddr}, e il segmento verrà comunque -agganciato, ma al più vicino multiplo di \const{SHMLBA} (il nome della +funzione; esso va specificato come maschera binaria, i bit utilizzati al +momento sono sono tre e sono identificati dalle costanti \const{SHM\_RND}, +\const{SHM\_RDONLY} e \const{SHM\_REMAP} che vanno combinate con un OR +aritmetico. + +Specificando \const{SHM\_RND} si evita che \func{shmat} ritorni un errore +quando \param{shmaddr} non è allineato ai confini di una pagina. Si può quindi +usare un valore qualunque per \param{shmaddr}, e il segmento verrà comunque +agganciato, ma al più vicino multiplo di \const{SHMLBA}; il nome della costante sta infatti per \textit{rounded}, e serve per specificare un -indirizzo come arrotondamento, in Linux è equivalente a \const{PAGE\_SIZE}). +indirizzo come arrotondamento. L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal @@ -2886,16 +2896,24 @@ di agganciare il segmento con l'accesso in lettura e scrittura (ed il processo deve aver questi permessi in \var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in sola scrittura. -In caso di successo la funzione aggiorna anche i seguenti campi di -\struct{shmid\_ds}: -\begin{itemize*} +Infine \const{SHM\_REMAP} è una estensione specifica di Linux (quindi non +portabile) che indica che la mappatura del segmento deve rimpiazzare ogni +precedente mappatura esistente nell'intervallo iniziante +all'indirizzo \param{shmaddr} e di dimensione pari alla lunghezza del +segmento. In condizioni normali questo tipo di richiesta fallirebbe con un +errore di \errval{EINVAL}. Ovviamente usando \const{SHM\_REMAP} +l'argomento \param{shmaddr} non può essere nullo. + +In caso di successo la funzione \func{shmat} aggiorna anche i seguenti campi +della struttura \struct{shmid\_ds}: +\begin{itemize} \item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene impostato al tempo corrente. \item il \ids{PID} \var{shm\_lpid} dell'ultimo processo che ha operato sul segmento viene impostato a quello del processo corrente. \item il numero \var{shm\_nattch} di processi agganciati al segmento viene aumentato di uno. -\end{itemize*} +\end{itemize} Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa agganciato ad un processo viene ereditato da un figlio attraverso una @@ -2909,18 +2927,21 @@ attraverso una \func{exit}. Una volta che un segmento di memoria condivisa non serve più, si può sganciarlo esplicitamente dal processo usando l'altra funzione dell'interfaccia, \funcd{shmdt}, il cui prototipo è: -\begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/shm.h} - \funcdecl{int shmdt(const void *shmaddr)} - Sgancia dal processo un segmento di memoria condivisa. - - \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di - errore, la funzione fallisce solo quando non c'è un segmento agganciato - all'indirizzo \param{shmaddr}, con \var{errno} che assume il valore - \errval{EINVAL}.} -\end{functions} +\begin{funcproto}{ +\fhead{sys/types.h} +\fhead{sys/shm.h} +\fdecl{int shmdt(const void *shmaddr)} + +\fdesc{Sgancia dal processo un segmento di memoria condivisa.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, la funzione + fallisce solo quando non c'è un segmento agganciato + all'indirizzo \param{shmaddr}, con \var{errno} che assume il valore + \errval{EINVAL}. +} +\end{funcproto} La funzione sgancia dallo spazio degli indirizzi del processo un segmento di memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr} @@ -3056,13 +3077,14 @@ si esegue (\texttt{\small 24--26}) su di esso una \func{chdir}, uscendo immediatamente in caso di errore. Questa funzione serve anche per impostare la \index{directory~di~lavoro} directory di lavoro del programma nella directory da tenere sotto controllo, in vista del successivo uso della -funzione \func{daemon}.\footnote{si noti come si è potuta fare questa scelta, - nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il - particolare scopo del programma, che necessita comunque di restare - all'interno di una directory.} Infine (\texttt{\small 27--29}) si installano -i gestori per i vari segnali di terminazione che, avendo a che fare con un -programma che deve essere eseguito come server, sono il solo strumento -disponibile per concluderne l'esecuzione. +funzione \func{daemon}. Si noti come si è potuta fare questa scelta, +nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il +particolare scopo del programma, che necessita comunque di restare all'interno +di una directory. + +Infine (\texttt{\small 27--29}) si installano i gestori per i vari segnali di +terminazione che, avendo a che fare con un programma che deve essere eseguito +come server, sono il solo strumento disponibile per concluderne l'esecuzione. Il passo successivo (\texttt{\small 30--39}) è quello di creare gli oggetti di intercomunicazione necessari. Si inizia costruendo (\texttt{\small 30}) la @@ -3098,16 +3120,18 @@ Il primo passo (\texttt{\small 41}) è eseguire \func{daemon} per proseguire con l'esecuzione in background come si conviene ad un programma demone; si noti che si è mantenuta, usando un valore non nullo del primo argomento, la \index{directory~di~lavoro} directory di lavoro corrente. Una volta che il -programma è andato in background l'esecuzione prosegue (\texttt{\small - 42--48}) all'interno di un ciclo infinito: si inizia (\texttt{\small 43}) -bloccando il mutex con \func{MutexLock} per poter accedere alla memoria -condivisa (la funzione si bloccherà automaticamente se qualche client sta -leggendo), poi (\texttt{\small 44}) si cancellano i valori precedentemente -immagazzinati nella memoria condivisa con \func{memset}, e si esegue -(\texttt{\small 45}) un nuovo calcolo degli stessi utilizzando la funzione -\myfunc{dir\_scan}; infine (\texttt{\small 46}) si sblocca il mutex con -\func{MutexUnlock}, e si attende (\texttt{\small 47}) per il periodo di tempo -specificato a riga di comando con l'opzione \code{-p} con una \func{sleep}. +programma è andato in background l'esecuzione prosegue all'interno di un ciclo +infinito (\texttt{\small 42--48}). + +Si inizia (\texttt{\small 43}) bloccando il mutex con \func{MutexLock} per +poter accedere alla memoria condivisa (la funzione si bloccherà +automaticamente se qualche client sta leggendo), poi (\texttt{\small 44}) si +cancellano i valori precedentemente immagazzinati nella memoria condivisa con +\func{memset}, e si esegue (\texttt{\small 45}) un nuovo calcolo degli stessi +utilizzando la funzione \myfunc{dir\_scan}; infine (\texttt{\small 46}) si +sblocca il mutex con \func{MutexUnlock}, e si attende (\texttt{\small 47}) per +il periodo di tempo specificato a riga di comando con l'opzione \code{-p} +usando una \func{sleep}. Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si sia usata ancora una volta la funzione \myfunc{dir\_scan}, già utilizzata (e @@ -3176,15 +3200,15 @@ il mutex, prima di uscire. Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando le funzioni di libreria occorre definire opportunamente \code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con: -\begin{Verbatim} -[piccardi@gont sources]$ ./dirmonitor ./ -\end{Verbatim} +\begin{Console} +[piccardi@gont sources]$ \textbf{./dirmonitor ./} +\end{Console} %$ ed avendo usato \func{daemon} il comando ritornerà immediatamente. Una volta che il server è in esecuzione, possiamo passare ad invocare il client per verificarne i risultati, in tal caso otterremo: -\begin{Verbatim} -[piccardi@gont sources]$ ./readmon +\begin{Console} +[piccardi@gont sources]$ \textbf{./readmon} Ci sono 68 file dati Ci sono 3 directory Ci sono 0 link @@ -3193,14 +3217,14 @@ Ci sono 0 socket Ci sono 0 device a caratteri Ci sono 0 device a blocchi Totale 71 file, per 489831 byte -\end{Verbatim} +\end{Console} %$ ed un rapido calcolo (ad esempio con \code{ls -a | wc} per contare i file) ci permette di verificare che il totale dei file è giusto. Un controllo con \cmd{ipcs} ci permette inoltre di verificare la presenza di un segmento di memoria condivisa e di un semaforo: -\begin{Verbatim} -[piccardi@gont sources]$ ipcs +\begin{Console} +[piccardi@gont sources]$ \textbf{ipcs} ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0xffffffff 54067205 piccardi 666 4096 1 @@ -3211,14 +3235,14 @@ key semid owner perms nsems ------ Message Queues -------- key msqid owner perms used-bytes messages -\end{Verbatim} +\end{Console} %$ Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova}, potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o l'eventuale altro intervallo impostato per la rilettura dei dati) avremo: -\begin{Verbatim} -[piccardi@gont sources]$ ./readmon +\begin{Console} +[piccardi@gont sources]$ \textbf{./readmon} Ci sono 69 file dati Ci sono 3 directory Ci sono 0 link @@ -3227,21 +3251,21 @@ Ci sono 0 socket Ci sono 0 device a caratteri Ci sono 0 device a blocchi Totale 72 file, per 489887 byte -\end{Verbatim} +\end{Console} %$ A questo punto possiamo far uscire il server inviandogli un segnale di \signal{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto ripetendo la lettura, otterremo un errore: -\begin{Verbatim} -[piccardi@gont sources]$ ./readmon +\begin{Console} +[piccardi@gont sources]$ \textbf{./readmon} Cannot find shared memory: No such file or directory -\end{Verbatim} +\end{Console} %$ e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione visti in precedenza sono stati regolarmente cancellati: -\begin{Verbatim} -[piccardi@gont sources]$ ipcs +\begin{Console} +[piccardi@gont sources]$ \textbf{ipcs} ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status @@ -3250,7 +3274,7 @@ key semid owner perms nsems ------ Message Queues -------- key msqid owner perms used-bytes messages -\end{Verbatim} +\end{Console} %$ @@ -3301,7 +3325,7 @@ diversa con un uso combinato della memoria condivisa e dei meccanismi di sincronizzazione, per cui alla fine l'uso delle code di messaggi classiche è relativamente poco diffuso. -% TODO: trattare qui, se non ssis trova posto migliore, copy_from_process e +% TODO: trattare qui, se non si trova posto migliore, copy_from_process e % copy_to_process, introdotte con il kernel 3.2. Vedi % http://lwn.net/Articles/405346/ e % http://ozlabs.org/~cyeoh/cma/process_vm_readv.txt @@ -3321,19 +3345,19 @@ necessità di un contatore come i semafori, si possono utilizzare metodi alternativi. La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare -dei \textsl{file di lock} (per i quali esiste anche una opportuna directory, -\file{/var/lock}, nel filesystem standard). Per questo si usa la -caratteristica della funzione \func{open} (illustrata in -sez.~\ref{sec:file_open_close}) che prevede\footnote{questo è quanto dettato dallo - standard POSIX.1, ciò non toglie che in alcune implementazioni questa - tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si - è comunque soggetti alla possibilità di una \itindex{race~condition} - \textit{race condition}.} che essa ritorni un errore quando usata con i -flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la creazione di un -\textsl{file di lock} può essere eseguita atomicamente, il processo che crea -il file con successo si può considerare come titolare del lock (e della -risorsa ad esso associata) mentre il rilascio si può eseguire con una chiamata -ad \func{unlink}. +dei \textsl{file di lock} (per i quali è stata anche riservata una opportuna +directory, \file{/var/lock}, nella standardizzazione del \textit{Filesystem + Hyerarchy Standard}). Per questo si usa la caratteristica della funzione +\func{open} (illustrata in sez.~\ref{sec:file_open_close}) che +prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non + toglie che in alcune implementazioni questa tecnica possa non funzionare; in + particolare per Linux, nel caso di NFS, si è comunque soggetti alla + possibilità di una \itindex{race~condition} \textit{race condition}.} che +essa ritorni un errore quando usata con i flag di \const{O\_CREAT} e +\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può +essere eseguita atomicamente, il processo che crea il file con successo si può +considerare come titolare del lock (e della risorsa ad esso associata) mentre +il rilascio si può eseguire con una chiamata ad \func{unlink}. Un esempio dell'uso di questa funzione è mostrato dalle funzioni \func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock} @@ -3496,10 +3520,10 @@ nessun inconveniente. \label{sec:ipc_mmap_anonymous} \itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono -\textsl{correlati}\footnote{se cioè hanno almeno un progenitore comune.} l'uso -delle \textit{pipe} può costituire una valida alternativa alle code di -messaggi; nella stessa situazione si può evitare l'uso di una memoria -condivisa facendo ricorso al cosiddetto \textit{memory mapping} anonimo. +\textsl{correlati}, se cioè hanno almeno un progenitore comune, l'uso delle +\textit{pipe} può costituire una valida alternativa alle code di messaggi; +nella stessa situazione si può evitare l'uso di una memoria condivisa facendo +ricorso al cosiddetto \textit{memory mapping} anonimo. In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il contenuto di un file nella memoria di un processo, e che, quando viene usato @@ -3572,28 +3596,27 @@ richiesto è che: \end{itemize*} Data la assoluta genericità delle specifiche, il comportamento delle funzioni -è subordinato in maniera quasi completa alla relativa -implementazione.\footnote{tanto che Stevens in \cite{UNP2} cita questo caso - come un esempio della maniera standard usata dallo standard POSIX per - consentire implementazioni non standardizzabili.} Nel caso di Linux, sia per -quanto riguarda la memoria condivisa ed i semafori, che per quanto riguarda le -code di messaggi, tutto viene creato usando come radici delle opportune -directory (rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i -dettagli si faccia riferimento a sez.~\ref{sec:ipc_posix_shm}, -sez.~\ref{sec:ipc_posix_sem} e sez.~\ref{sec:ipc_posix_mq}) ed i nomi -specificati nelle relative funzioni sono considerati come un -\itindsub{pathname}{assoluto} \textit{pathname} assoluto (comprendente -eventuali sottodirectory) rispetto a queste radici. +è subordinato in maniera quasi completa alla relativa implementazione, tanto +che Stevens in \cite{UNP2} cita questo caso come un esempio della maniera +standard usata dallo standard POSIX per consentire implementazioni non +standardizzabili. Nel caso di Linux, sia per quanto riguarda la memoria +condivisa ed i semafori, che per quanto riguarda le code di messaggi, tutto +viene creato usando come radici delle opportune directory (rispettivamente +\file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si faccia riferimento a +sez.~\ref{sec:ipc_posix_shm}, sez.~\ref{sec:ipc_posix_sem} e +sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni +sono considerati come un \itindsub{pathname}{assoluto} \textit{pathname} +assoluto (comprendente eventuali sottodirectory) rispetto a queste radici. Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti nell'albero dei file, e possono essere maneggiati con le usuali funzioni e -comandi di accesso ai file,\footnote{questo è vero nel caso di Linux, che usa - una implementazione che lo consente, non è detto che altrettanto valga per - altri kernel; in particolare, come si può facilmente verificare con uno - \cmd{strace}, sia per la memoria condivisa che per le code di messaggi le - system call utilizzate da Linux sono le stesse di quelle dei file, essendo - detti oggetti realizzati come tali in appositi filesystem.} che funzionano -come su dei file normali. +comandi di accesso ai file, che funzionano come su dei file normali; questo +però è vero nel caso di Linux, che usa una implementazione che lo consente, +non è detto che altrettanto valga per altri kernel. In particolare, come si +può facilmente verificare con uno \cmd{strace}, sia per la memoria condivisa +che per le code di messaggi le system call utilizzate da Linux sono le stesse +di quelle dei file, essendo detti oggetti realizzati come tali in appositi +filesystem. In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai permessi dei file, ed il controllo di accesso segue esattamente la stessa diff --git a/process.tex b/process.tex index 994c2f6..5d03314 100644 --- a/process.tex +++ b/process.tex @@ -2802,7 +2802,7 @@ basterà scegliere una volta per tutte quale usare e attenersi alla scelta. % 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 ForkTest POSIXLY CORRECT long options NdA +% LocalWords: optind opterr optopt POSIXLY CORRECT long options NdA % 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 -- 2.30.2