Correzioni e aggiunte molteplici, scritta setjmp e longjmp in process,
authorSimone Piccardi <piccardi@gnulinux.it>
Fri, 26 Apr 2002 21:25:12 +0000 (21:25 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Fri, 26 Apr 2002 21:25:12 +0000 (21:25 +0000)
nuova sezione in system, completate sigsetjmp e siglongjmp in signal

filestd.tex
process.tex
signal.tex
system.tex

index cc3e1fd..5f51dad 100644 (file)
@@ -474,7 +474,7 @@ In genere si usano queste funzioni quando si devono trasferire su file
 blocchi di dati binari in maniera compatta e veloce; un primo caso di uso
 tipico è quello in cui si salva un vettore (o un certo numero dei suoi
 elementi) con una chiamata del tipo:
-\footnotesize
+%\footnotesize
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
 int WriteVect(FILE *stream, double *vec, size_t nelem) 
 {
@@ -486,12 +486,12 @@ int WriteVect(FILE *stream, double *vec, size_t nelem)
     return nread;
 }
 \end{lstlisting}
-\normalsize
+%\normalsize
 in questo caso devono essere specificate le dimensioni di ciascun
 elemento ed il numero di quelli che si vogliono scrivere. Un secondo
 caso è invece quello in cui si vuole trasferire su file una struttura;
 si avrà allora una chiamata tipo:
-\footnotesize
+%\footnotesize
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
 struct histogram {
     int nbins; 
@@ -507,7 +507,7 @@ int WriteStruct(FILE *stream, struct histogram *histo, size_t nelem)
     return nread;
 }
 \end{lstlisting}
-\normalsize
+%\normalsize
 in cui si specifica la dimensione dell'intera struttura ed un solo
 elemento. 
 
index d23e54f..a5695b7 100644 (file)
@@ -1213,7 +1213,6 @@ informazioni a riguardo dei risultati vengono passate alla routine chiamante
 attraverso il valore di ritorno.  È buona norma seguire questa pratica anche
 nella programmazione normale.
 
-
 Talvolta però è necessario che la funzione possa restituire indietro alla
 funzione chiamante un valore relativo ad uno dei suoi parametri.  Per far
 questo si usa il cosiddetto \textit{value result argument}, si passa cioè,
@@ -1363,7 +1362,6 @@ argomenti opzionali, questi verranno sempre promossi, pertanto nella ricezione
 dei medesimi occorrerà tenerne conto (ad esempio un \ctyp{char} verrà visto da
 \macro{va\_arg} come \ctyp{int}).
 
-
 Uno dei problemi che si devono affrontare con le funzioni con un numero
 variabile di argomenti è che non esiste un modo generico che permetta di
 stabilire quanti sono i parametri passati effettivamente in una chiamata.
@@ -1397,6 +1395,7 @@ anche dalla funzione chiamante queste devono essere allocate esplicitamente, o
 in maniera statica (usando variabili di tipo \ctyp{static} o \ctyp{extern}), o
 dinamicamente con una delle funzioni della famiglia \func{malloc}.
 
+
 \subsection{Il controllo di flusso non locale}
 \label{sec:proc_longjmp}
 
@@ -1405,46 +1404,119 @@ varie istruzioni del linguaggio C; fra queste la pi
 \code{goto}, che viene deprecato in favore dei costrutti della programmazione
 strutturata, che rendono il codice più leggibile e mantenibile . Esiste però
 un caso in cui l'uso di questa istruzione porta all'implementazione più
-efficiente e chiara anche dal punto di vista della struttura del programma,
+efficiente e chiara anche dal punto di vista della struttura del programma:
 quello dell'uscita in caso di errore.
 
 Il C però non consente di effettuare un salto ad una label definita in
-un'altra funzione, per cui se l'errore avviene in funzioni profondamente
-annidate occorre usare quello che viene chiamato un salto \textsl{non-locale};
-questo viene fatto usando salvando il contesto dello stack nel punto in cui si
-vuole tornare in caso di errore, e ripristinandolo quando l'occorrenza capita.
-
-La funzione che permette di salvare il contesto dello stack è \func{setjmp},
-il cui prototipo è:
-
+un'altra funzione, per cui se l'errore avviene in una funzione e la sua
+gestione ordinaria è in un'altra occorre usare quello che viene chiamato un
+\textsl{salto non-locale}.  Il caso classico in cui si ha questa necessità,
+citato sia da \cite{APUE} che da da \cite{glibc}, è quello di un programma nel
+ccui corpo principale in cui viene letto un input del quale viene eseguita
+attraverso una serie di funzioni di analisi una scansione dei contenuti da cui
+ottenere le indicazioni per l'esecuzione di opportune operazioni.
+
+Dato che l'analisi può risultare molto complessa, ed opportunamente suddivisa
+in fasi diverse, la rilevazione di un errore nell'input può accadere
+all'interno di funzioni profondamente annidate l'una nell'altra. In questo
+caso si dovrebbe per ciascuna fase dover gestire tutta la casistica del
+passaggio all'indietro di tutti gli errori rilevabili dalle funzioni usate
+nelle fasi successive, mentre sarebbe molto più comodo poter tornare
+direttamente al ciclo di lettura principale, scartando l'input come
+errato.\footnote{a meno che, come precisa \cite{glibc}, alla chiusura di
+  ciascuna fase non siano associate operazioni di pulizia specifiche (come
+  deallocazioni, chiusure di file, ecc.), che non potrebbero essere eseguite
+  con un salto non-locale.}
+
+Tutto ciò può essere realizzato salvando il contesto dello stack nel punto in
+cui si vuole tornare in caso di errore, e ripristinandolo quando l'occorrenza
+capita. La funzione che permette di salvare il contesto dello stack è
+\func{setjmp}, il cui prototipo è:
 \begin{functions}
   \headdecl{setjmp.h}
   \funcdecl{void setjmp(jmp\_buf env)}
   
   Salva il contesto dello stack in \param{env} per un successivo uso da parte
-  di \func{longjmp}. Il contesto viene invalidato se la routine che ha
-  chiamato \func{setjmp} ritorna.
-  
+  di \func{longjmp}. 
+
   \bodydesc{La funzione ritorna zero quando è chiamata direttamente e un
     valore diverso da zero quando ritorna da una chiamata di \func{longjmp}
     che usa il contesto salvato in precedenza.}
 \end{functions}
 
-
-Per poter effettuare un salto non locale si usa la funzione \func{longjmp}; il
-suo prototipo è:
+Quando si esegue la funzione il contesto viene salvato in appositi oggetti (di
+tipo \type{jmp\_buf}), passati come primo argomento alla funzione, in genere
+questi vengono definiti come variabili globali in modo da poter essere visti
+in tutte le funzioni del programma.
+
+Quando viene eseguita direttamente la funzione ritorna sempre zero, un valore
+diverso da zero viene restituito solo quando il ritorno è dovuto ad una
+chiamata di \func{longjmp} in un'altra parte del programa. Si tenga conto che
+il contesto salvato in \param{env} viene invalidato se la routine che ha
+chiamato \func{setjmp} ritorna, nel qual caso l'uso di \func{longjmp} può
+comportare conseguenze imprevedibili (e di norma fatali per il processo).
+  
+Come accennato per effettuare un salto non-locale ad un punto precedentemente
+stabilito con \func{setjmp} si usa la funzione \func{longjmp}; il suo
+prototipo è:
 \begin{functions}
   \headdecl{setjmp.h}
   \funcdecl{void longjmp(jmp\_buf env, int val)}
   
-  Ripristina il contesto dello stack salvato dall'ultima chiamata di
-  \func{setjmp} con l'argomento \param{env}. Il programma prosegue dal ritorno
-  di \func{setjmp} con un valore \param{val}. Il valore di \param{val} deve
-  essere diverso da zero, se viene specificato 0 sarà usato 1 al suo posto.
-
+  Ripristina il contesto dello stack salvato nell'ultima chiamata di
+  \func{setjmp} con l'argomento \param{env}.
+  
   \bodydesc{La funzione non ritorna.}
 \end{functions}
 
+Dopo l'esecuzione della funzione programma prosegue dal codice successivo al
+ritorno della \func{setjmp} con cui si era salvato \param{env}, che restituirà
+il valore \param{val} invece di zero.  Il valore di \param{val} specificato
+nella chiamata deve essere diverso da zero, se si è specificato 0 sarà
+comunque restituito 1 al suo posto.
+
+In sostanza un \func{longjmp} è analogo ad un \code{return}, solo che invece
+di ritornare alla riga succesiva della funzione chiamante, il programma
+ritorna alla posizione della relativa \func{setjmp}, ed il ritorno può essere
+effettuato anche attraverso diversi livelli di funzioni annidate.
+
+L'implementazione di queste funzioni comporta alcune restrizioni dato che esse
+interagiscono direttamente con la gestione dello stack ed il funzionamento del
+compilatore stesso. In particolare \func{setjmp} è implementata con una macro,
+pertanto non si può cercare di ottenerne l'indirizzo, ed inoltre delle
+chiamate a questa funzione sono sicure solo in uno dei seguenti casi:
+\begin{itemize}
+\item come espressione di controllo in un comando condizionale, di selezione
+  o di iterazione (come \code{if}, \code{switch} o \code{while}).
+\item come operando per un operatore di uguaglianza o confronto in una
+  espressione di controllo di un comando condizionale, di selezione o di
+  iterazione.
+\item come operando per l'operatore di negazione (\code{!}) in una espressione
+  di controllo di un comando condizionale, di selezione o di iterazione.
+\item come espressione a sé stante.
+\end{itemize}
+
+In generale, dato che l'unica differenza fra la chiamata diretta e quella
+ottenuta da un \func{longjmp}, è il valore di ritorno di \func{setjmp}, essa è
+usualmente chiamata all'interno di un comando \code{if}. 
+
+Uno dei punti critici dei salti non-locali è quello del valore delle
+variabili, ed in particolare quello delle variabili automatiche della funzione
+a cui si ritorna. In generale le variabili globali e statiche mantengono i
+valori che avevano al momento della chiamata di \func{longjmp}, ma quelli
+delle variabili automatiche (o di quelle dichiarate \code{register}) sono in
+genere indeterminati.
+
+Quello che succede infatti è che i valori delle variabili che sono tenute in
+memoria manterranno il valore avuto al momento della chiamata di
+\func{longjmp}, mentre quelli tenuti nei registri del processore (che nella
+chiamata ad un'altra funzioni vengono salvati nel contesto nello stack)
+torneranno al valore avuto al momento della chiamata di \func{setjmp}; per
+questo quando si vuole avere un comportamento coerente si può bloccare
+l'ottimizzazione che porta le variabili nei registri dichiarandole tutte come
+\code{volatile}.
+
+
 
 %%% Local Variables: 
 %%% mode: latex
index 703d876..adbec4d 100644 (file)
@@ -2254,6 +2254,50 @@ avviene per lo stack ordinario dei processi, non si accresce automaticamente
 Si ricordi infine che una chiamata ad una funzione della famiglia
 \func{exec} cancella ogni stack alternativo.
 
+Abbiamo visto in \secref{fig:sig_sleep_incomplete} come si possa usare
+\func{longjmp} per uscire da un manipolatore rientrando direttamente nel corpo
+del programma; sappiamo però che nell'esecuzione di un manipolatore il segnale
+che l'ha invocato viene bloccato, e abbiamo detto che possiamo ulteriormente
+modificarlo con \func{sigprocmask}. 
+
+Resta quindi il problema di cosa succede alla maschera dei segnali quando si
+esce da un manipolatore usando questa funzione. Il comportamento dipende
+dall'implementazione; in particolare BSD ripristina la maschera dei segnali
+precedente l'invocazione, come per un normale ritorno, mentre SYSV no. Lo
+standard POSIX.1 non specifica questo comportamento per \func{setjmp} e
+\func{longjmp}, ed il comportamento delle \acr{glibc} dipende da quale delle
+caratteristiche si sono abilitate con le macro viste in
+\secref{sec:intro_gcc_glibc_std}. 
+
+Lo standard POSIX però prevede anche la presenza di altre due funzioni
+\func{sigsetjmp} e \func{siglongjmp}, che permettono di decidere quale dei due
+comportamenti il programma deve assumere; i loro prototipi sono:
+\begin{functions}
+  \headdecl{setjmp.h} 
+  
+  \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto
+  dello stack per un salto non locale.
+  \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto non
+  locale su un precedente contesto.
+
+  \bodydesc{Le due funzioni sono identiche alle analoghe \func{setjmp} e
+    \func{longjmp} di \secref{sec:proc_longjmp}, ma consentono di specificare
+    il comportamento sul ripristino o meno della maschera dei segnali.}
+\end{functions}
+
+Le due funzioni prendono come primo argomento la variabile su cui viene
+salvato il contesto dello stack per permettere il salto non locale; nel caso
+specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} come per le
+analoghe di \secref{sec:proc_longjmp} in quanto in questo caso viene salvata
+anche la maschera dei segnali.
+
+Nel caso di \func{sigsetjmp} se si specifica un valore di \param{savesigs}
+diverso da zero la maschera dei valori sarà salvata in \param{env} e
+ripristinata in un successivo \func{siglongjmp}; quest'ultima funzione, a
+parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a
+\func{longjmp}.
+
 
 
 
index 63b46f6..4482834 100644 (file)
@@ -350,7 +350,7 @@ sostituendolo a \code{\_POSIX\_} per le macro definite dagli gli altri due.
 
 In generale si dovrebbe fare uso di \func{sysconf} solo quando la relativa
 macro non è definita, quindi con un codice analogo al seguente:
-\footnotesize
+%\footnotesize
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
 get_child_max(void)
 {
@@ -365,7 +365,7 @@ get_child_max(void)
     return val;
 }
 \end{lstlisting}
-\normalsize 
+%\normalsize 
 ma in realtà in Linux queste macro sono comunque definite e indicando un
 limite generico, per cui è sempre meglio usare i valori restituiti da
 quest'ultima.
@@ -488,20 +488,9 @@ suo prototipo 
 
 La funzione, che viene usata dal comando \cmd{uname}, restituisce le
 informazioni richieste nella struttura \param{info}; anche questa struttura è
-definita in \file{sys/utsname.h} come:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct utsname {
-    char sysname[_UTSNAME_LENGTH];
-    char nodename[_UTSNAME_LENGTH];
-    char release[_UTSNAME_LENGTH];
-    char version[_UTSNAME_LENGTH];
-    char machine[_UTSNAME_LENGTH];
-#ifdef _GNU_SOURCE
-    char domainname[_UTSNAME_DOMAIN_LENGTH];
-#endif
-};
-\end{lstlisting}
-e le informazioni memorizzate nei suoi membri indicano rispettivamente:
+definita in \file{sys/utsname.h}, secondo quanto mostrato in
+\secref{fig:sys_utsname}, e le informazioni memorizzate nei suoi membri
+indicano rispettivamente:
 \begin{itemize*}
 \item il nome del sistema operativo;
 \item il nome della release del kernel;
@@ -510,8 +499,41 @@ e le informazioni memorizzate nei suoi membri indicano rispettivamente:
 \item il nome della stazione;
 \item il nome del domino.
 \end{itemize*}
-(l'ultima informazione è stata aggiunta di recente e non è prevista dallo
-standard POSIX). 
+l'ultima informazione è stata aggiunta di recente e non è prevista dallo
+standard POSIX, essa è accessibile, come mostrato in \figref{fig:sig_stack_t},
+solo definendo \macro{\_GNU\_SOURCE}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+  \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct utsname {
+    char sysname[];
+    char nodename[];
+    char release[];
+    char version[];
+    char machine[];
+#ifdef _GNU_SOURCE
+    char domainname[];
+#endif
+};
+  \end{lstlisting}
+  \end{minipage}
+  \normalsize 
+  \caption{La struttura \var{utsname}.} 
+  \label{fig:sys_utsname}
+\end{figure}
+
+In generale si tenga presente che le dimensioni delle stringe di una
+\var{utsname} non è specificata, e che esse sono sempre terminate con
+\macro{NULL}; il manuale delle \acr{glibc} indica due diverse dimensioni,
+\macro{\_UTSNAME\_LENGTH} per i campi standard e
+\macro{\_UTSNAME\_DOMAIN\_LENGTH} per quello specifico per il nome di dominio;
+altri sistemi usano nomi diversi come \macro{SYS\_NMLN} or \macro{\_SYS\_NMLN}
+or \macro{UTSLEN} che possono avere valori diversi; nel caso di Linux
+\func{uname} corrisponde in realtà a 3 system call diverse, le prime due usano
+delle lunghezze delle stringhe di 9 e 65 byte; la terza 65, restituisce anche
+l'ultimo campo con una lunghezza di 257 byte.
 
 
 \section{Opzioni e configurazione del sistema}
@@ -623,10 +645,20 @@ nomi dei file corrispondenti, e questo ha il grande vantaggio di rendere
 accessibili i vari parametri a qualunque comando di shell e di permettere la
 navigazione dell'albero dei valori.
 
-Alcune delle corrispondenze con i valori di \func{sysctl} sono riportate nei
-commenti in \file{linux/sysctl.h}, la informazione disponibile in
-\file{/proc/sys} è riportata inoltre nella documentazione inclusa nei sorgenti
-del kernel, nella directory \file{Documentation/sysctl}.
+Alcune delle corrispondenze dei file presentin \file{/proc/sys} con i valori
+di \func{sysctl} sono riportate nei commenti del codice che può essere trovato
+in \file{linux/sysctl.h},\footnote{indicando un file di definizioni si fa
+  riferimento alla directory standard dei file di include, che in ogni
+  distribuzione che si rispetti è \file{/usr/include}.} la informazione
+disponibile in \file{/proc/sys} è riportata inoltre nella documentazione
+inclusa nei sorgenti del kernel, nella directory \file{Documentation/sysctl}.
+
+Ma oltre alle informazioni ottenibili da \func{sysctl} dentro \file{proc} 
+sono disponibili moltissime altre informazioni, fra cui ad esempio anche
+quelle fornite da \func{uname} (vedi \secref{sec:sys_config}) che sono
+mantenute nei file \file{ostype}, \file{hostname}, \file{osrelease},
+\file{version} e \file{domainname} di \file{/proc/kernel/}.
+
 
 
 \subsection{La gestione delle proprietà dei filesystem}
@@ -719,6 +751,7 @@ vanno settati con un OR aritmetico della costante \macro{MS\_MGC\_VAL} con i
 valori riportati in \ntab.
 
 \begin{table}[htb]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|l|r|l|}
     \hline
@@ -816,12 +849,15 @@ Altre due funzioni specifiche di Linux,\footnote{esse si trovano anche su BSD,
 informazioni riguardo al filesystem su cui si trova un certo file, sono
 \func{statfs} e \func{fstatfs}, i cui prototipi sono:
 \begin{functions}
-  \headdecl{sys/vfs.h} \funcdecl{int statfs(const char *path, struct statfs
-    *buf)} \funcdecl{int fstatfs(int fd, struct statfs *buf)} Restituisce in
-  \param{buf} le informazioni relative al filesystem su cui è posto il file
-  specificato.
+  \headdecl{sys/vfs.h} 
+  \funcdecl{int statfs(const char *path, struct statfs *buf)} 
+
+  \funcdecl{int fstatfs(int fd, struct statfs *buf)} 
   
-  \bodydesc{Li funzioni restituiscono 0 in caso di successo e -1 in caso di
+  Restituisce in \param{buf} le informazioni relative al filesystem su cui è
+  posto il file specificato.
+  
+  \bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di
     errore, nel qual caso \var{errno} viene settato ai valori:
   \begin{errlist}
   \item[\macro{ENOSYS}] il filesystem su cui si trova il file specificato non
@@ -834,8 +870,17 @@ informazioni riguardo al filesystem su cui si trova un certo file, sono
 
 Queste funzioni permettono di ottenere una serie di informazioni generali
 riguardo al filesystem su cui si trova il file specificato; queste vengono
-restituite una struttura \param{buf} definita come:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+restituite una struttura \param{buf} di tipo \type{statfs} definita come in
+\ref{fig:sys_statfs}, ed i campi che sono indefiniti per il filesystem in
+esame sono settati a zero.  I valori del campo \var{f\_type} sono definiti per
+i vari filesystem nei relativi file di header dei sorgenti del kernel da
+costanti del tipo \macro{XXX\_SUPER\_MAGIC}, dove \macro{XXX} in genere è il
+nome del filesystem stesso.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+  \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
     struct statfs {
        long    f_type;     /* tipo di filesystem */
        long    f_bsize;    /* dimensione ottimale dei blocchi di I/O */
@@ -849,11 +894,12 @@ restituite una struttura \param{buf} definita come:
        long    f_spare[6]; /* riservati per uso futuro */
     };
 \end{lstlisting}
-ed i campi che sono indefiniti per il filesystem in esame sono settati a zero.
-I valori del campo \var{f\_type} sono definiti per i vari filesystem nei
-relativi file di header dei sorgenti del kernel da costanti del tipo
-\macro{XXX\_SUPER\_MAGIC}, dove \macro{XXX} in genere è il nome del filesystem
-stesso.
+  \end{minipage}
+  \normalsize 
+  \caption{La struttura \var{statfs}.} 
+  \label{fig:sys_statfs}
+\end{figure}
+
 
 Le \acr{glibc} provvedono infine una serie di funzioni per la gestione dei due
 file standard \file{/etc/fstab} e \file{/etc/mtab}, che convenzionalmente sono
@@ -881,12 +927,78 @@ tenuta tutta nei due file di testo \file{/etc/passwd} ed \file{/etc/group};
 oggi la maggior parte delle distribuzioni di Linux usa la libreria PAM (sigla
 che sta \textit{Pluggable Authentication Method}) che permette di separare
 completamente i meccanismi di gestione degli utenti (autenticazione,
-riconoscimeto, ecc.) dal
+riconoscimento, ecc.) dalle modalità in cui i relativi dati vengono mantenuti.
 
+In questo paragrafo ci limiteremo comunque alle funzioni classiche per la
+lettura delle informazioni relative a utenti e gruppi previste dallo standard
+POSIX.1, che fanno riferimento a quanto memorizzato nei due file appena
+citati, il cui formato è descritto dalle relative pagine del manuale (cioè
+\cmd{man 5 passwd} e \cmd{man 5 group}).
 
+Per leggere le informazioni relative ad un utente si possono usare due
+funzioni, \func{getpwuid} e \func{getpwnam}, i cui prototipi sono:
+\begin{functions}
+  \headdecl{pwd.h} 
+  \headdecl{sys/types.h} 
+  \funcdecl{struct passwd *getpwuid(uid\_t uid)} 
+  
+  \funcdecl{struct passwd *getpwnam(const char *name)} 
 
-Lo standard POSIX.1 definisce una serie di funzioni
+  Restituiscono le informazioni relative alll'utente specificato.
+  
+  \bodydesc{Le funzioni ritornano il puntatore alla struttura contenente le
+    informazioni in caso di successo e \macro{NULL} in caso di errore, nel
+    qual caso \var{errno} viene settata ad \macro{ENOMEM}.}
+\end{functions}
 
+Le due funzioni forniscono le informazioni memorizzate nel database degli
+utenti (che nelle versioni più recenti possono essere ottenute attraverso PAM)
+relative all'utente specificato attraverso il suo \acr{uid} o il nome di
+login, restituendo un puntatore ad una struttura di tipo \type{passwd}, (la
+cui definizione è riportata in \figref{fig:sys_passwd_struct}), allocata
+staticamente.
+
+\begin{figure}[!htb]
+  \footnotesize
+  \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct passwd {
+    char    *pw_name;       /* user name */
+    char    *pw_passwd;     /* user password */
+    uid_t   pw_uid;         /* user id */
+    gid_t   pw_gid;         /* group id */
+    char    *pw_gecos;      /* real name */
+    char    *pw_dir;        /* home directory */
+    char    *pw_shell;      /* shell program */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{passwd} contenente le informazioni relative ad un
+    utente del sistema.}
+  \label{fig:sys_passwd_struct}
+\end{figure}
+
+
+\begin{figure}[!htb]
+  \footnotesize
+  \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct group {
+    char    *gr_name;        /* group name */
+    char    *gr_passwd;      /* group password */
+    gid_t   gr_gid;          /* group id */
+    char    **gr_mem;        /* group members */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{passwd} contenente le informazioni relative ad un
+    utente del sistema.}
+  \label{fig:sys_passwd_struct}
+\end{figure}
 
 
 \section{Limitazione ed uso delle risorse}
@@ -894,8 +1006,8 @@ Lo standard POSIX.1 definisce una serie di funzioni
 
 In questa sezione esamineremo le funzioni che permettono di esaminare e
 controllare come le varie risorse del sistema (CPU, memoria, ecc.) vengono
-utilizzate dai processi, e le modalità con cui è possibile imporre dei limiti
-sul loro utilizzo.
+utilizzate dai singoli processi, e le modalità con cui è possibile imporre dei
+limiti sul loro utilizzo.
 
 
 
@@ -904,7 +1016,6 @@ sul loro utilizzo.
 
 
 
-
 \subsection{Limiti sulle risorse}
 \label{sec:sys_resource_limit}
 
@@ -922,7 +1033,7 @@ sul loro utilizzo.
   \footnotesize
   \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
 struct rusage {
      struct timeval ru_utime; /* user time used */
      struct timeval ru_stime; /* system time used */