sono mantenuti sono: \var{ru\_utime}, \var{ru\_stime}, \var{ru\_minflt},
\var{ru\_majflt}, e \var{ru\_nswap}.
-\subsection{Le \textit{race condition}}
-\label{sec:proc_race_cond}
-
-Si definisce una \textit{race condition} il caso in cui diversi processi
-stanno cercando di fare qualcosa con una risorsa comune ed il risultato finale
-viene a dipendere dall'ordine di esecuzione dei medesimi. Ovviamente dato che
-l'ordine di esecuzione di un processo, senza appositi meccanismi di
-sincronizzazione, non è assolutamente prevedibile, queste situazioni sono
-fonti di errori molto subdoli, che possono verificarsi solo in condizioni
-particolari e quindi difficilmente riproducibili.
-
-
\subsection{Le funzioni \texttt{exec}}
\label{sec:proc_exec}
Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata
famiglia di funzioni) che possono essere usate per questo compito, che in
realtà (come mostrato in \figref{fig:proc_exec_relat}), costituiscono un
-front-end a \func{execve}. Il prototipo di quest'utiltima è:
+front-end a \func{execve}. Il prototipo di quest'ultima è:
\begin{prototype}{unistd.h}
{int execve(const char * filename, char * const argv [], char * const envp[])}
\end{prototype}
Le altre funzioni della famiglia servono per fornire all'utente una serie
-possibile di diverse interfacce per la creazione di un nuovo processo.
+possibile di diverse interfacce per la creazione di un nuovo processo. I loro
+prototipi sono:
+
+\begin{functions}
+\headdecl{unistd.h}
+\funcdecl{int execl(const char *path, const char *arg, ...)}
+\funcdecl{int execv(const char *path, char *const argv[])}
+\funcdecl{int execle(const char *path, const char *arg, ..., char
+* const envp[])}
+\funcdecl{int execlp(const char *file, const char *arg, ...)}
+\funcdecl{int execvp(const char *file, char *const argv[])}
+
+Sostituiscono l'immagine corrente del processo con quella indicata nel primo
+argomento. I parametri successivi consentono di specificare gli argomenti a
+linea di comando e l'ambiente ricevuti dal nuovo processo.
+
+Queste funzioni ritornano solo in caso di errore, restituendo -1; nel qual
+caso \var{errno} andrà ad assumere i valori visti in precedenza per
+\func{execve}.
+\end{functions}
+
+Per capire meglio le differenze fra le funzioni della famiglia si può fare
+riferimento allo specchietto riportato in \ntab. La prima differenza riguarda
+le modalità di passaggio dei parametri che poi andranno a costituire gli
+argomenti a linea di comando (cioè i valori di \var{argv} e \var{argc} visti
+dalla funzione \func{main} del programma chiamato).
+Queste modalità sono due e sono riassunte dagli mnenonici \func{v} e \func{l}
+che stanno rispettivamente per \textit{vector} e \textit{list}. Nel primo caso
+gli argomenti sono passati tramite il vettore di puntatori \var{argv[]} a
+stringhe terminate con zero che costituiranno gli argomenti a riga di comando,
+questo vettore \emph{deve} essere terminato da un puntatore nullo.
-Con \func{exec} si chiude il cerchio delle funzioni su cui si basa il
-controllo dei processi in unix: con \func{fork} si crea un nuovo processo, con
-\func{exec} si avvia un nuovo programma, con \func{exit} e \func{wait} si
-effettua e si gestisce la conclusione dei programmi.
+Nel secondo caso le stringhe degli argomenti sono passate alla funzione come
+lista di puntatori, nella forma:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ char * arg0, char * arg1, ..., char * argn, NULL
+\end{lstlisting}
+che deve essere terminata da un puntatore nullo. In entrambi i casi vale la
+convenzione che il primo argomento (\var{arg0} o \var{argv[0]}) viene usato
+per indicare il nome del file che contiene il programma che verrà eseguito.
+
+
+\begin{table}[!htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|c|c|c||c|c|c|}
+ \hline
+ \multicolumn{1}{|c|}{\textbf{Caratteristiche}} &
+ \multicolumn{6}{|c|}{\textbf{Funzioni}} \\
+ \hline
+ &\func{execl\ }&\func{execlp}&\func{execle}
+ &\func{execv\ }& \func{execvp}& \func{execve} \\
+ \hline
+ \hline
+ argomenti a lista &$\bullet$&$\bullet$&$\bullet$&&& \\
+ argomenti a vettore &&&&$\bullet$&$\bullet$&$\bullet$\\
+ \hline
+ filename completo &&$\bullet$&&&$\bullet$& \\
+ ricerca su \var{PATH}&$\bullet$&&$\bullet$&$\bullet$&&$\bullet$ \\
+ \hline
+ ambiente a vettore &&&$\bullet$&&&$\bullet$ \\
+ uso di \var{environ} &$\bullet$&$\bullet$&&$\bullet$&$\bullet$& \\
+ \hline
+ \end{tabular}
+ \caption{Confronto delle caratteristiche delle varie funzioni della
+ famiglia \func{exec}.}
+ \label{tab:proc_exec_scheme}
+\end{table}
+
+La seconda differenza fra le funzioni riguarda le modalità con cui si
+specifica il programma che si vuole eseguire. Con lo mnemonico \func{p} si
+indicano le due funzioni che necessitano del \textit{pathname} assoluto del
+programma come valore del parametro \var{path}. Le altre quattro funzioni
+invece usano come parametro \var{file} un nome che viene cercato
+automaticamente fra i file presenti nella lista di directory specificate dalla
+variabile di ambiente \var{PATH}.
+
+
+La terza differenza è .
+
+
+
+Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è
+basato il controllo dei processi in unix: con \func{fork} si crea un nuovo
+processo, con \func{exec} si avvia un nuovo programma, con \func{exit} e
+\func{wait} si effettua e si gestisce la conclusione dei programmi. Tutte le
+altre funzioni sono ausiliarie e servono la lettura e il settaggio dei vari
+parametri connessi ai processi.
\section{Il controllo di accesso}
\acr{gid}), e vengono usati sia per il controllo di accesso ai file che per la
gestione dei privilegi associati ai processi stessi.
\begin{table}[htb]
+ \footnotesize
\centering
\begin{tabular}[c]{|c|l|p{8cm}|}
\hline
\subsection{Le funzioni \texttt{seteuid} e \texttt{setegid}}
\label{sec:proc_seteuid}
+
+\subsection{Le \textit{race condition}}
+\label{sec:proc_race_cond}
+
+Si definisce una \textit{race condition} il caso in cui diversi processi
+stanno cercando di fare qualcosa con una risorsa comune ed il risultato finale
+viene a dipendere dall'ordine di esecuzione dei medesimi. Ovviamente dato che
+l'ordine di esecuzione di un processo, senza appositi meccanismi di
+sincronizzazione, non è assolutamente prevedibile, queste situazioni sono
+fonti di errori molto subdoli, che possono verificarsi solo in condizioni
+particolari e quindi difficilmente riproducibili.
+
+
per lo stesso motivo \textit{big endian}.
La \textit{endianess} di un computer dipende essenzialmente dalla architettura
-hardware usata; Intel e Digital usano il little endian, Motorola, IBM, Sun
-(sostanzialmente tutti gli altri) usano il big endian. Il formato della rete è
-anch'esso big endian, quello del bus PCI è little endian, quello del bus VME è
-big endian.
+hardware usata; Intel e Digital usano il \textit{little endian}, Motorola,
+IBM, Sun (sostanzialmente tutti gli altri) usano il \textit{big endian}. Il
+formato della rete è anch'esso \textit{big endian}, altri esempi sono quello
+del bus PC, che è \textit{little endian}, o quello del bus VME che è
+\textit{big endian}.
Esistono poi anche dei processori che possono scegliere il tipo di formato
-all'avvio e alcuni, come il PowerPC o l'Intel i860, possono pure passare da un
-tipo di ordinamento all'altro con una specifica istruzione; in ogni caso in
-Linux l'ordinamento è definito dall'architettura e anche se questi cambiamenti
-sono possibili anche dopo che il sistema è avviato, non vengono mai eseguiti.
+all'avvio e alcuni che, come il PowerPC o l'Intel i860, possono pure passare
+da un tipo di ordinamento all'altro con una specifica istruzione. In ogni caso
+in Linux l'ordinamento è definito dall'architettura e dopo l'avvio del sistema
+resta sempre lo stesso, anche quando il processore permetterebbe di eseguire
+questi cambiamenti.
\subsection{Le funzioni per il riordinamento}
\label{sec:sock_func_ord}
Converte l'intero a 16 bit \var{netshort} dal formato della rete a quello
della macchina.
\end{prototype}
-I nomi sono assegnati usando la lettera $n$ come mnemonico per indicare
-l'ordinamento usato sulla rete (da \textit{network order}) e la lettera $h$
-come mnemonico per l'ordinamento usato sulla macchina locale (da \textit{host
- order}), mentre le lettere $s$ e $l$ stanno ad indicare i tipi di dato
-(\type{long} o \type{short}, riportati anche dai prototipi).
+I nomi sono assegnati usando la lettera \func{n} come mnemonico per indicare
+l'ordinamento usato sulla rete (da \textit{network order}) e la lettera
+\func{h} come mnemonico per l'ordinamento usato sulla macchina locale (da
+\textit{host order}), mentre le lettere \func{s} e \func{l} stanno ad indicare
+i tipi di dato (\type{long} o \type{short}, riportati anche dai prototipi).
-Usando queste funzioni si ha la conversione automatica (nel caso pure la
-macchina sia in big endian queste funzioni sono definite come macro che non
-fanno nulla); esse vanno sempre utilizzate per assicurare la portabilità del
-codice su tutte le architetture.
+Usando queste funzioni si ha la conversione automatica: nel caso in cui la
+macchina che si sta usando abbia una architettura \textit{big endian} queste
+funzioni sono definite come macro che non fanno nulla. Per questo motivo vanno
+sempre utilizzate, anche quando potrebbero non essere necessarie, in modo da
+assicurare la portabilità del codice su tutte le architetture.
\subsection{Le funzioni \func{inet\_aton}, \func{inet\_addr} e
indirizzi IPv4 da una stringa in cui il numero di IP è espresso secondo la
cosiddetta notazione \textit{dotted-decimal}, (cioè nella forma
\texttt{192.160.0.1}) al formato binario (direttamente in \textit{network
- order}) e viceversa; in questo caso si usa la lettera $a$ come mnemonico per
-indicare la stringa. Dette funzioni sono:
+ order}) e viceversa; in questo caso si usa la lettera \func{a} come
+mnemonico per indicare la stringa. Dette funzioni sono:
\begin{prototype}{arpa/inet.h}
- {int inet\_aton(const char *src, struct in\_addr *dest)} Converte la stringa
- puntata da \var{src} nell'indirizzo binario da memorizzare all'indirizzo
- puntato da \var{dest}, restituendo 0 in caso di successo e 1 in caso di
- fallimento (è espressa in questa forma in modo da poterla usare direttamente
- con il puntatore usato per passare la struttura degli indirizzi). Se usata
- con \var{dest} inizializzato a \macro{NULL} effettua la validazione
- dell'indirizzo.
+ {int inet\_aton(const char *src, struct in\_addr *dest)}
+ Converte la stringa puntata da \var{src} nell'indirizzo binario da
+ memorizzare all'indirizzo puntato da \var{dest}, restituendo 0 in caso di
+ successo e 1 in caso di fallimento (è espressa in questa forma in modo da
+ poterla usare direttamente con il puntatore usato per passare la struttura
+ degli indirizzi). Se usata con \var{dest} inizializzato a \macro{NULL}
+ effettua la validazione dell'indirizzo.
\end{prototype}
\begin{prototype}{arpa/inet.h}{in\_addr\_t inet\_addr(const char *strptr)}
Restituisce l'indirizzo a 32 bit in network order a partire dalla stringa
generalmente deprecata in favore della precedente.
\end{prototype}
\begin{prototype}{arpa/inet.h}{char *inet\_ntoa(struct in\_addr addrptr)}
- Converte il valore a 32 bit dell'indirizzo (espresso in network order)
- restituendo il puntatore alla stringa che contiene l'espressione in formato
- dotted decimal. Si deve tenere presente che la stringa risiede in memoria
- statica, per cui questa funzione non è rientrante.
+ Converte il valore a 32 bit dell'indirizzo (espresso in \textit{network
+ order}) restituendo il puntatore alla stringa che contiene l'espressione
+ in formato dotted decimal. Si deve tenere presente che la stringa risiede in
+ memoria statica, per cui questa funzione non è rientrante.
\end{prototype}
Le tre funzioni precedenti sono limitate solo ad indirizzi IPv4, per questo
motivo è preferibile usare le due nuove funzioni \func{inet\_pton} e
\func{inet\_ntop} che possono convertire anche gli indirizzi IPv6. Anche in
-questo caso le lettere $n$ e $p$ sono degli mnemonici per ricordare il tipo di
-conversione effettuata e stanno per \textit{presentation} e \textit{numeric}.
+questo caso le lettere \func{n} e \func{p} sono degli mnemonici per ricordare
+il tipo di conversione effettuata e stanno per \textit{presentation} e
+\textit{numeric}.
% \begin{figure}[htb]
% \centering
return (count - nleft);
}
\end{lstlisting}
- \caption{Funzione \texttt{SockRead}, legge $n$ bytes da un socket }
+ \caption{Funzione \func{SockRead}, legge \var{count} bytes da un socket }
\label{fig:sock_SockRead_code}
\end{figure}
Per questo motivo seguendo l'esempio di W. R. Stevens si sono definite due
-funzioni \texttt{SockRead} e \texttt{SockWrite} che eseguono la lettura da un
+funzioni \func{SockRead} e \func{SockWrite} che eseguono la lettura da un
socket tenendo conto di questa caratteristica, ed in grado di ritornare dopo
avere letto o scritto esattamente il numero di bytes specificato; il sorgente
è riportato in \curfig\ e \nfig\ ed è disponibile fra i sorgenti allegati alla
-guida nei files \texttt{SockRead.c} e \texttt{SockWrite.c}.
+guida nei files \file{SockRead.c} e \file{SockWrite.c}.
\begin{figure}[htb]
\centering
return (count);
}
\end{lstlisting}
- \caption{Funzione \texttt{SockWrite}, scrive $n$ bytes su un socket }
+ \caption{Funzione \func{SockWrite}, scrive \var{count} bytes su un socket }
\label{fig:sock_SockWrite_code}
\end{figure}
Come si può notare le funzioni ripetono la lettura/scrittura in un ciclo fino
all'esaurimento del numero di bytes richiesti, in caso di errore viene
-controllato se questo è \texttt{EINTR} (cioè un'interruzione della system call
+controllato se questo è \macro{EINTR} (cioè un'interruzione della system call
dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
-l'errore viene ritornato interrompendo il ciclo.
+l'errore viene ritornato interrompendo il ciclo.
-Nel caso della lettura se il numero di bytes letti è zero significa che è
+Nel caso della lettura, se il numero di bytes letti è zero, significa che si è
arrivati alla fine del file e pertanto si ritorna senza aver concluso la
-lettura di tutti i bytes richiesti.
+lettura di tutti i bytes richiesti.