portato, per i kernel della serie 2.6,\footnote{per alcune motivazioni di
questa scelta si può fare riferimento a quanto illustrato da Linus Torvalds
in \href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}
- {\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}.}
+ {\textsf{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}.}
alla decisione di consentire l'uso della funzione soltanto quando il file da
cui si legge supporta le operazioni di \textit{memory mapping} (vale a dire
non è un socket) e quello su cui si scrive è un socket; in tutti gli altri
stata la reinterpretazione che ne è stata fatta nell'implementazione su
Linux realizzata da Jens Anxboe, concetti che sono esposti sinteticamente
dallo stesso Linus Torvalds in \href{http://kerneltrap.org/node/6505}
- {\texttt{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una
+ {\textsf{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una
funzione che consente di fare in maniera del tutto generica delle operazioni
di trasferimento di dati fra un file e un buffer gestito interamente in kernel
space. In questo caso il cuore della funzione (e delle affini \func{vmsplice}
realizza le \textit{pipe} come un insieme di puntatori\footnote{per essere
precisi si tratta di un semplice buffer circolare, un buon articolo sul tema
si trova su \href{http://lwn.net/Articles/118750/}
- {\texttt{http://lwn.net/Articles/118750/}}.} alle pagine di memoria interna
+ {\textsf{http://lwn.net/Articles/118750/}}.} alle pagine di memoria interna
che contengono i dati, per questo una volta che i dati sono presenti nella
memoria del kernel tutto quello che viene fatto è creare i suddetti puntatori
ed aumentare il numero di referenze; questo significa che anche con \func{tee}
Quando un processo ha concluso il suo compito o ha incontrato un errore non
risolvibile esso può essere terminato con la funzione \func{exit} (si veda
quanto discusso in sez.~\ref{sec:proc_conclusion}). La vita del processo però
-termina solo quando la notifica della sua conclusione viene ricevuta dal
-processo padre, a quel punto tutte le risorse allocate nel sistema ad esso
-associate vengono rilasciate.
+termina completamente solo quando la notifica della sua conclusione viene
+ricevuta dal processo padre, a quel punto tutte le risorse allocate nel
+sistema ad esso associate vengono rilasciate.
Avere due processi che eseguono esattamente lo stesso codice non è molto
utile, normalmente si genera un secondo processo per affidargli l'esecuzione
senza specificare attese (come si può notare in (\texttt{\small 17--19}) i
valori predefiniti specificano di non attendere), otterremo come output sul
terminale:
-
\footnotesize
\begin{verbatim}
[piccardi@selidor sources]$ export LD_LIBRARY_PATH=./; ./forktest 3
\normalsize
Esaminiamo questo risultato: una prima conclusione che si può trarre è che non
-si può dire quale processo fra il padre ed il figlio venga eseguito per
-primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
- \itindex{scheduler} \textit{scheduler} di Ingo Molnar che esegue sempre per
- primo il figlio; per mantenere la portabilità è opportuno non fare comunque
- affidamento su questo comportamento.} dopo la chiamata a \func{fork};
-dall'esempio si può notare infatti come nei primi due cicli sia stato eseguito
-per primo il padre (con la stampa del \acr{pid} del nuovo processo) per poi
-passare all'esecuzione del figlio (completata con i due avvisi di esecuzione
-ed uscita), e tornare all'esecuzione del padre (con la stampa del passaggio al
-ciclo successivo), mentre la terza volta è stato prima eseguito il figlio
-(fino alla conclusione) e poi il padre.
+si può dire quale processo fra il padre ed il figlio venga eseguito per primo
+dopo la chiamata a \func{fork}; dall'esempio si può notare infatti come nei
+primi due cicli sia stato eseguito per primo il padre (con la stampa del
+\acr{pid} del nuovo processo) per poi passare all'esecuzione del figlio
+(completata con i due avvisi di esecuzione ed uscita), e tornare
+all'esecuzione del padre (con la stampa del passaggio al ciclo successivo),
+mentre la terza volta è stato prima eseguito il figlio (fino alla conclusione)
+e poi il padre.
In generale l'ordine di esecuzione dipenderà, oltre che dall'algoritmo di
\itindex{scheduler} scheduling usato dal kernel, dalla particolare situazione
rischio di incorrere nelle cosiddette \itindex{race~condition} \textit{race
condition} (vedi sez.~\ref{sec:proc_race_cond}).
+In realtà a partire dal kernel 2.5.2-pre10 il nuovo \itindex{scheduler}
+\textit{scheduler} di Ingo Molnar esegue sempre per primo il
+figlio;\footnote{i risultati precedenti sono stati ottenuti su un kernel della
+ serie 2.4.} questa è una ottimizzazione che serve a evitare che il padre,
+effettuando per primo una operazione di scrittura in memoria, attivi il
+meccanismo del \itindex{copy~on~write} \textit{copy on write}. Questa
+operazione infatti potrebbe risultare del tutto inutile qualora il figlio
+fosse stato creato solo per eseguire una \func{exec}, in tal caso infatti si
+invocherebbe un'altro proramma scartando completamente lo spazio degli
+indirizzi, rendendo superflua la copia della memoria modificata dal padre.
+
+Eseguendo sempre per primo il figlio la \func{exec} verrebbe effettuata subito
+avendo così la certezza che il \itindex{copy~on~write} \textit{copy on write}
+viene utilizzato solo quando necessario. Quanto detto in precedenza vale
+allora soltanto per i kernel fino al 2.4, per mantenere la portabilità è però
+opportuno non fare affidamento su questo comportamento, che non si riscontra
+in altri Unix e nelle versioni del kernel precendenti a quella indicata.
+
Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
processi completamente separati, le modifiche delle variabili nei processi
figli (come l'incremento di \var{i} in \texttt{\small 31}) sono visibili solo
quello dell'interazione dei vari processi con i file; per illustrarlo meglio
proviamo a redirigere su un file l'output del nostro programma di test, quello
che otterremo è:
-
\footnotesize
\begin{verbatim}
[piccardi@selidor sources]$ ./forktest 3 > output
quanto c'è nel buffer delle funzioni di I/O, comprese le linee scritte dal
padre fino allora. Così quando il buffer viene scritto su disco all'uscita del
figlio, troveremo nel file anche tutto quello che il processo padre aveva
-scritto prima della sua creazione. E alla fine del file (dato che in questo
+scritto prima della sua creazione. E alla fine del file (dato che in questo
caso il padre esce per ultimo) troveremo anche l'output completo del padre.
L'esempio ci mostra un altro aspetto fondamentale dell'interazione con i file,
terminato (si potrebbe avere cioè quello che si chiama un processo
\textsl{orfano}).
+% TODO verificare il reparenting
+
Questa complicazione viene superata facendo in modo che il processo orfano
venga \textsl{adottato} da \cmd{init}. Come già accennato quando un processo
termina, il kernel controlla se è il padre di altri processi in esecuzione: in
cui riportare il suo stato di terminazione. Come verifica di questo
comportamento possiamo eseguire il nostro programma \cmd{forktest} imponendo a
ciascun processo figlio due secondi di attesa prima di uscire, il risultato è:
-
\footnotesize
\begin{verbatim}
[piccardi@selidor sources]$ ./forktest -c2 3
\const{CLD\_STOPPED}, \const{CLD\_CONTINUED} (vedi tab.~\ref{xxx_si_code}).
\end{basedescript}
-%TODO mettere riferimento alla tabella giusta
+%TODO mettere riferimento alla tabella giusta (vedere man credentials e man
+% waitid)
Infine Linux, seguendo un'estensione di BSD, supporta altre due funzioni per
la lettura dello stato di terminazione di un processo, analoghe alle
sez.~\ref{sec:sys_resource_use}) per ottenere le risorse di sistema usate da un
processo; la sua definizione è riportata in fig.~\ref{fig:sys_rusage_struct}.
-\subsection{Le funzioni \func{exec}}
+\subsection{La funzione \func{exec} e le funzioni di esecuzione dei programmi}
\label{sec:proc_exec}
Abbiamo già detto che una delle modalità principali con cui si utilizzano i
lunga restituisce un errore di \const{ENAMETOOLONG}, una comparazione dei
vari comportamenti si trova su
\href{http://www.in-ulm.de/~mascheck/various/shebang/}
- {\texttt{http://www.in-ulm.de/\tild mascheck/various/shebang/}}.}
+ {\textsf{http://www.in-ulm.de/\tild mascheck/various/shebang/}}.}
Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è
basata la gestione dei processi in Unix: con \func{fork} si crea un nuovo
benché l'infrastruttura per crearla sia presente (vedi anche
sez.~\ref{sec:file_xattr}) finora non è disponibile nessuna realizzazione
delle specifiche POSIX.1e, esistono però dei patch di sicurezza del kernel,
- come LIDS (vedi \href{http://www.lids.org}{\texttt{http://www.lids.org/})}
+ come LIDS (vedi \href{http://www.lids.org}{\textsf{http://www.lids.org/})}
che realizzano qualcosa di simile.}
vengono gestiti questi processi dipende dalla politica di scheduling che si è
scelta; lo standard ne prevede due:
\begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}}
-\item[\textit{FIFO}] \textit{First In First Out}. Il processo viene eseguito
+\item[\textsf{FIFO}] \textit{First In First Out}. Il processo viene eseguito
fintanto che non cede volontariamente la CPU (con \func{sched\_yield}), si
blocca, finisce o viene interrotto da un processo a priorità più alta. Se il
processo viene interrotto da uno a priorità più alta esso resterà in cima
più alta diverranno inattivi. Se invece lo si blocca volontariamente sarà
posto in coda alla lista (ed altri processi con la stessa priorità potranno
essere eseguiti).
-\item[\textit{RR}] \textit{Round Robin}. Il comportamento è del tutto analogo
+\item[\textsf{RR}] \textit{Round Robin}. Il comportamento è del tutto analogo
a quello precedente, con la sola differenza che ciascun processo viene
eseguito al massimo per un certo periodo di tempo (la cosiddetta
\textit{time slice}) dopo di che viene automaticamente posto in fondo alla
La prima funzione di questa interfaccia è \funcd{getaddrinfo},\footnote{la
funzione è definita, insieme a \func{getnameinfo} che vedremo più avanti,
- nell'\href{http://www.ietf.org/rfc/rfc2553.txt} {RFC~2553}.} che combina le
+ nell'\href{http://www.ietf.org/rfc/rfc2553.txt}{RFC~2553}.} che combina le
funzionalità delle precedenti \func{getipnodebyname}, \func{getipnodebyaddr},
\func{getservbyname} e \func{getservbyport}, consentendo di ottenere
contemporaneamente sia la risoluzione di un indirizzo simbolico che del nome
reno& -- &Algoritmo tradizionale, usato in caso di assenza degli altri.\\
\texttt{bic} &\texttt{TCP\_CONG\_BIC} &
\href{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}
- {\texttt{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}}.\\
+ {\textsf{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}}.\\
\texttt{cubic} &\texttt{TCP\_CONG\_CUBIC} &
\href{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}
- {\texttt{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}}.\\
+ {\textsf{http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/index.htm}}.\\
\texttt{highspeed}&\texttt{TCP\_CONG\_HSTCP} &
\href{http://www.icir.org/floyd/hstcp.html}
- {\texttt{http://www.icir.org/floyd/hstcp.html}}.\\
+ {\textsf{http://www.icir.org/floyd/hstcp.html}}.\\
\texttt{htcp} &\texttt{TCP\_CONG\_HTCP} &
\href{http://www.hamilton.ie/net/htcp/}
- {\texttt{http://www.hamilton.ie/net/htcp/}}.\\
+ {\textsf{http://www.hamilton.ie/net/htcp/}}.\\
\texttt{hybla} &\texttt{TCP\_CONG\_HYBLA} &
\href{http://www.danielinux.net/projects.html}
- {\texttt{http://www.danielinux.net/projects.html}}.\\
+ {\textsf{http://www.danielinux.net/projects.html}}.\\
\texttt{scalable}&\texttt{TCP\_CONG\_SCALABLE}&
\href{http://www.deneholme.net/tom/scalable/}
- {\texttt{http://www.deneholme.net/tom/scalable/}}.\\
+ {\textsf{http://www.deneholme.net/tom/scalable/}}.\\
\texttt{vegas} &\texttt{TCP\_CONG\_VEGAS} &
\href{http://www.cs.arizona.edu/protocols/}
- {\texttt{http://www.cs.arizona.edu/protocols/}}.\\
+ {\textsf{http://www.cs.arizona.edu/protocols/}}.\\
\texttt{westwood}&\texttt{TCP\_CONG\_WESTWOOD}&
\href{http://www.cs.ucla.edu/NRL/hpi/tcpw/}
- {\texttt{http://www.cs.ucla.edu/NRL/hpi/tcpw/}}.\\
+ {\textsf{http://www.cs.ucla.edu/NRL/hpi/tcpw/}}.\\
% \texttt{}&\texttt{}& .\\
\hline
\end{tabular}