X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=process.tex;h=307ab489358e78614b1f114eebe1a79588ff9014;hb=c9c149db16c39efdfa53bde804b7a189dd923eef;hp=4eb8d725c1005f6dc68c161e9e0b56f709b3ed66;hpb=1add1cb54c1754ed030033b994a68c6678d7d275;p=gapil.git diff --git a/process.tex b/process.tex index 4eb8d72..307ab48 100644 --- a/process.tex +++ b/process.tex @@ -1,6 +1,6 @@ %% process.tex %% -%% Copyright (C) 2000-2012 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2015 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", @@ -310,6 +310,8 @@ sono scritte direttamente in \textit{assembler}. % http://davisdoesdownunder.blogspot.com/2011/02/linux-syscall-vsyscall-and-vdso-oh-my.html % http://www.win.tue.nl/~aeb/linux/lk/lk-4.html % +% Altro materiale al riguardo http://lwn.net/Articles/615809/ +% http://man7.org/linux/man-pages/man7/vdso.7.html Inoltre alcune \textit{system call} sono state modificate nel corso degli anni con lo sviluppo del kernel per aggiungere ad esempio funzionalità in forma di @@ -482,7 +484,7 @@ registrare un certo numero di funzioni che verranno eseguite all'uscita dal programma,\footnote{nel caso di \func{atexit} lo standard POSIX.1-2001 richiede che siano registrabili almeno \const{ATEXIT\_MAX} funzioni (il valore può essere ottenuto con \func{sysconf}, vedi - sez.~\ref{sec:sys_sysconf}).} sia per la chiamata ad \func{exit} che per il + sez.~\ref{sec:sys_limits}).} sia per la chiamata ad \func{exit} che per il ritorno di \code{main}. La prima funzione che si può utilizzare a tal fine è \funcd{atexit}, il cui prototipo è: @@ -636,16 +638,17 @@ programma in esecuzione, e le varie funzioni utilizzabili per la sua gestione. \subsection{I concetti generali} \label{sec:proc_mem_gen} +\index{memoria~virtuale|(} + Ci sono vari modi in cui i sistemi operativi organizzano la memoria, ed i dettagli di basso livello dipendono spesso in maniera diretta dall'architettura dell'hardware, ma quello più tipico, usato dai sistemi -unix-like come Linux è la cosiddetta \index{memoria~virtuale} \textsl{memoria - virtuale} che consiste nell'assegnare ad ogni processo uno spazio virtuale -di indirizzamento lineare, in cui gli indirizzi vanno da zero ad un qualche -valore massimo.\footnote{nel caso di Linux fino al kernel 2.2 detto massimo - era, per macchine a 32bit, di 2Gb. Con il kernel 2.4 ed il supporto per la - \textit{high-memory} il limite è stato esteso anche per macchine a 32 bit.} - +unix-like come Linux è la cosiddetta \textsl{memoria virtuale} che consiste +nell'assegnare ad ogni processo uno spazio virtuale di indirizzamento lineare, +in cui gli indirizzi vanno da zero ad un qualche valore massimo.\footnote{nel + caso di Linux fino al kernel 2.2 detto massimo era, per macchine a 32bit, di + 2Gb. Con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite + è stato esteso anche per macchine a 32 bit.} Come accennato nel cap.~\ref{cha:intro_unix} questo spazio di indirizzi è virtuale e non corrisponde all'effettiva posizione dei dati nella RAM del @@ -656,13 +659,13 @@ necessariamente adiacenti. Per la gestione da parte del kernel la memoria viene divisa in pagine di dimensione fissa. Inizialmente queste pagine erano di 4kb sulle macchine a 32 bit e di 8kb sulle alpha. Con le versioni più recenti del kernel è possibile -anche utilizzare pagine di dimensioni maggiori (di 4Mb, dette \textit{huge - page}), per sistemi con grandi quantitativi di memoria in cui l'uso di -pagine troppo piccole comporta una perdita di prestazioni. In alcuni sistemi -la costante \const{PAGE\_SIZE}, definita in \headfile{limits.h}, indica la -dimensione di una pagina in byte, con Linux questo non avviene e per ottenere -questa dimensione si deve ricorrere alla funzione \func{getpagesize} (vedi -sez.~\ref{sec:sys_memory_res}). +anche utilizzare pagine di dimensioni maggiori (di 4Mb, dette +\itindex{huge~page} \textit{huge page}), per sistemi con grandi quantitativi +di memoria in cui l'uso di pagine troppo piccole comporta una perdita di +prestazioni. In alcuni sistemi la costante \const{PAGE\_SIZE}, definita in +\headfile{limits.h}, indica la dimensione di una pagina in byte, con Linux +questo non avviene e per ottenere questa dimensione si deve ricorrere alla +funzione \func{getpagesize} (vedi sez.~\ref{sec:sys_memory_res}). Ciascuna pagina di memoria nello spazio di indirizzi virtuale è associata ad un supporto che può essere una pagina di memoria reale o ad un dispositivo di @@ -681,17 +684,17 @@ della funzione \func{printf} starà su una sola pagina di memoria reale che farà da supporto a tutte le pagine di memoria virtuale di tutti i processi che hanno detta funzione nel loro codice. -La corrispondenza fra le pagine della \index{memoria~virtuale} memoria -virtuale di un processo e quelle della memoria fisica della macchina viene -gestita in maniera trasparente dal kernel.\footnote{in genere con l'ausilio - dell'hardware di gestione della memoria (la \textit{Memory Management Unit} - del processore), con i kernel della serie 2.6 è comunque diventato possibile - utilizzare Linux anche su architetture che non dispongono di una MMU.} -Poiché in genere la memoria fisica è solo una piccola frazione della memoria -virtuale, è necessario un meccanismo che permetta di trasferire le pagine che -servono dal supporto su cui si trovano in memoria, eliminando quelle che non -servono. Questo meccanismo è detto \index{paginazione} \textsl{paginazione} -(o \textit{paging}), ed è uno dei compiti principali del kernel. +La corrispondenza fra le pagine della memoria virtuale di un processo e quelle +della memoria fisica della macchina viene gestita in maniera trasparente dal +kernel.\footnote{in genere con l'ausilio dell'hardware di gestione della + memoria (la \textit{Memory Management Unit} del processore), con i kernel + della serie 2.6 è comunque diventato possibile utilizzare Linux anche su + architetture che non dispongono di una MMU.} Poiché in genere la memoria +fisica è solo una piccola frazione della memoria virtuale, è necessario un +meccanismo che permetta di trasferire le pagine che servono dal supporto su +cui si trovano in memoria, eliminando quelle che non servono. Questo +meccanismo è detto \index{paginazione} \textsl{paginazione} (o +\textit{paging}), ed è uno dei compiti principali del kernel. Quando un processo cerca di accedere ad una pagina che non è nella memoria reale, avviene quello che viene chiamato un \itindex{page~fault} \textit{page @@ -714,6 +717,7 @@ esigenze specifiche di prestazioni è possibile usare delle funzioni che permettono di bloccare il meccanismo della \index{paginazione} paginazione e mantenere fisse delle pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}). +\index{memoria~virtuale|)} \subsection{La struttura della memoria di un processo} \label{sec:proc_mem_layout} @@ -728,16 +732,16 @@ un'associazione nella memoria virtuale, il kernel risponde al relativo \itindex{page~fault} \textit{page fault} mandando un segnale \signal{SIGSEGV} al processo, che normalmente ne causa la terminazione immediata. -È pertanto importante capire come viene strutturata \index{memoria~virtuale} -la memoria virtuale di un processo. Essa viene divisa in \textsl{segmenti}, -cioè un insieme contiguo di indirizzi virtuali ai quali il processo può -accedere. Solitamente un programma C viene suddiviso nei seguenti segmenti: +È pertanto importante capire come viene strutturata la memoria virtuale di un +processo. Essa viene divisa in \textsl{segmenti}, cioè un insieme contiguo di +indirizzi virtuali ai quali il processo può accedere. Solitamente un +programma C viene suddiviso nei seguenti segmenti: \begin{enumerate*} \item Il \index{segmento!testo} segmento di testo o \textit{text segment}. Contiene il codice del programma, delle funzioni di librerie da esso utilizzate, e le costanti. Normalmente viene condiviso fra tutti i processi che eseguono lo stesso programma e nel caso delle librerie anche da processi - che eseguono altri programmi. + che eseguono altri programmi. Quando l'architettura hardware lo supporta viene marcato in sola lettura per evitare sovrascritture accidentali (o maliziose) che ne modifichino le @@ -1616,20 +1620,20 @@ tipologia di errore riscontrata. \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{MCHECK\_OK} & riportato a \func{mprobe} se nessuna + \const{MCHECK\_OK} & Riportato a \func{mprobe} se nessuna inconsistenza è presente.\\ - \const{MCHECK\_DISABLED}& riportato a \func{mprobe} se si è chiamata + \const{MCHECK\_DISABLED}& Riportato a \func{mprobe} se si è chiamata \func{mcheck} dopo aver già usato \func{malloc}.\\ - \const{MCHECK\_HEAD} & i dati immediatamente precedenti il buffer sono + \const{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.\\ - \const{MCHECK\_TAIL} & i dati immediatamente seguenti il buffer sono + \const{MCHECK\_TAIL} & I dati immediatamente seguenti il buffer sono stati modificati, succede quando si va scrivere oltre la dimensione corretta del buffer.\\ - \const{MCHECK\_FREE} & il buffer è già stato disallocato.\\ + \const{MCHECK\_FREE} & Il buffer è già stato disallocato.\\ \hline \end{tabular} \caption{Valori dello stato dell'allocazione di memoria ottenibili dalla @@ -1831,8 +1835,9 @@ possibili si è poi provveduto ad un'azione opportuna, ad esempio per le tre opzioni che prevedono un parametro si è effettuata la decodifica del medesimo, il cui indirizzo è contenuto nella variabile \var{optarg}), avvalorando la relativa variabile (\texttt{\small 12-14}, \texttt{\small 15-17} e -\texttt{\small 18-20}). Completato il ciclo troveremo in \var{optind} l'indice -in \code{argv[]} del primo degli argomenti rimanenti nella linea di comando. +\texttt{\small 18-20}). Completato il ciclo troveremo in \var{optind} +l'indice in \code{argv[]} del primo degli argomenti rimanenti nella linea di +comando. Normalmente \func{getopt} compie una permutazione degli elementi di \param{argv} cosicché alla fine della scansione gli elementi che non sono @@ -1966,22 +1971,22 @@ queste ed ulteriori variabili si può ottenere con il comando \cmd{man 7 & \textbf{Linux} & \textbf{Descrizione} \\ \hline \hline - \texttt{USER} &$\bullet$&$\bullet$&$\bullet$& Nome utente\\ - \texttt{LOGNAME}&$\bullet$&$\bullet$&$\bullet$& Nome di login\\ + \texttt{USER} &$\bullet$&$\bullet$&$\bullet$& Nome utente.\\ + \texttt{LOGNAME}&$\bullet$&$\bullet$&$\bullet$& Nome di login.\\ \texttt{HOME} &$\bullet$&$\bullet$&$\bullet$& Directory base - dell'utente\\ - \texttt{LANG} &$\bullet$&$\bullet$&$\bullet$& Localizzazione\\ + dell'utente.\\ + \texttt{LANG} &$\bullet$&$\bullet$&$\bullet$& Localizzazione.\\ \texttt{PATH} &$\bullet$&$\bullet$&$\bullet$& Elenco delle directory - dei programmi\\ - \texttt{PWD} &$\bullet$&$\bullet$&$\bullet$& Directory corrente\\ - \texttt{SHELL} &$\bullet$&$\bullet$&$\bullet$& Shell in uso\\ - \texttt{TERM} &$\bullet$&$\bullet$&$\bullet$& Tipo di terminale\\ + dei programmi.\\ + \texttt{PWD} &$\bullet$&$\bullet$&$\bullet$& Directory corrente.\\ + \texttt{SHELL} &$\bullet$&$\bullet$&$\bullet$& Shell in uso.\\ + \texttt{TERM} &$\bullet$&$\bullet$&$\bullet$& Tipo di terminale.\\ \texttt{PAGER} &$\bullet$&$\bullet$&$\bullet$& Programma per vedere i - testi\\ - \texttt{EDITOR} &$\bullet$&$\bullet$&$\bullet$& Editor preferito\\ - \texttt{BROWSER}&$\bullet$&$\bullet$&$\bullet$& Browser preferito\\ + testi.\\ + \texttt{EDITOR} &$\bullet$&$\bullet$&$\bullet$& Editor preferito.\\ + \texttt{BROWSER}&$\bullet$&$\bullet$&$\bullet$& Browser preferito.\\ \texttt{TMPDIR} &$\bullet$&$\bullet$&$\bullet$& Directory dei file - temporanei\\ + temporanei.\\ \hline \end{tabular} \caption{Esempi delle variabili di ambiente più comuni definite da vari @@ -2205,6 +2210,10 @@ versione ``\textsl{sicura}'' da zero. % TODO opzioni in formato esteso +% TODO trattare il vettore ausiliario e getauxval (vedi +% http://lwn.net/Articles/519085/) + + \section{Problematiche di programmazione generica} \label{sec:proc_gen_prog} @@ -2694,30 +2703,26 @@ una variabile per poi ristamparne il contenuto leggendolo un byte alla volta. Il codice di detto programma, \file{endtest.c}, è nei sorgenti allegati, allora se lo eseguiamo su un normale PC compatibile, che è \textit{little endian} otterremo qualcosa del tipo: -\begin{Command} -[piccardi@gont sources]$ ./endtest -\end{Command} -%$ -\begin{Terminal} +\begin{Console} +[piccardi@gont sources]$ \textbf{./endtest} Using value ABCDEF01 val[0]= 1 val[1]=EF val[2]=CD val[3]=AB -\end{Terminal} +\end{Console} +%$ mentre su un vecchio Macintosh con PowerPC, che è \textit{big endian} avremo qualcosa del tipo: -\begin{Command} -piccardi@anarres:~/gapil/sources$ ./endtest -\end{Command} -%$ -\begin{Terminal} +\begin{Console} +piccardi@anarres:~/gapil/sources$ \textbf{./endtest} Using value ABCDEF01 val[0]=AB val[1]=CD val[2]=EF val[3]= 1 -\end{Terminal} +\end{Console} +%$ L'attenzione alla \textit{endianness} nella programmazione è importante, perché se si fanno assunzioni relative alla propria architettura non è detto che @@ -2801,7 +2806,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