(che in seguito incontreremo a più riprese), è mostrato in
fig.~\ref{fig:proc_task_struct}.
-\begin{figure}[htb]
- \centering
- \includegraphics[width=14cm]{img/task_struct}
+\begin{figure}[!htb]
+ \centering \includegraphics[width=14cm]{img/task_struct}
\caption{Schema semplificato dell'architettura delle strutture usate dal
kernel nella gestione dei processi.}
\label{fig:proc_task_struct}
La funzione \funcd{fork} è la funzione fondamentale della gestione dei
processi: come si è detto tradizionalmente l'unico modo di creare un nuovo
processo era attraverso l'uso di questa funzione,\footnote{in realtà oggi la
- system call usata più comunemente da Linux per creare nuovi processi è
- \func{clone} (vedi \ref{sec:process_clone}) , anche perché a partire dalle
- \acr{glibc} 2.3.3 non viene più usata la system call originale, ma la stessa
+ \textit{system call} usata da Linux per creare nuovi processi è \func{clone}
+ (vedi \ref{sec:process_clone}), anche perché a partire dalle \acr{glibc}
+ 2.3.3 non viene più usata la \textit{system call} originale, ma la stessa
\func{fork} viene implementata tramite \func{clone}, cosa che consente una
migliore interazione coi \textit{thread}.} essa quindi riveste un ruolo
centrale tutte le volte che si devono scrivere programmi che usano il
\func{getppid}, vedi sez.~\ref{sec:proc_pid}) per cui si usa il valore nullo,
che non è il \acr{pid} di nessun processo.
-\begin{figure}[!htb]
+\begin{figure}[!htbp]
\footnotesize \centering
- \begin{minipage}[c]{15cm}
+ \begin{minipage}[c]{\codesamplewidth}
\includecodesample{listati/ForkTest.c}
\end{minipage}
\normalsize
Dato che Linux supporta il \itindex{copy~on~write} \textit{copy on write} la
perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
-funzione, che resta un caso speciale della system call \func{clone} (che
-tratteremo in dettaglio in sez.~\ref{sec:process_clone}) è deprecato; per
+funzione, che resta un caso speciale della \textit{system call} \func{clone}
+(che tratteremo in dettaglio in sez.~\ref{sec:process_clone}) è deprecato; per
questo eviteremo di trattarla ulteriormente.
parte in tab.~\ref{tab:proc_waitpid_options} che possono essere combinati fra
loro con un OR aritmetico. Nella seconda parte della stessa tabella si sono
riportati anche alcuni valori non standard specifici di Linux, che consentono
-un controllo più dettagliato per i processi creati con la system call generica
-\func{clone} (vedi sez.~\ref{sec:process_clone}) usati principalmente per la
-gestione della terminazione dei \itindex{thread} \textit{thread} (vedi
+un controllo più dettagliato per i processi creati con la \textit{system call}
+generica \func{clone} (vedi sez.~\ref{sec:process_clone}) usati principalmente
+per la gestione della terminazione dei \itindex{thread} \textit{thread} (vedi
sez.~\ref{sec:thread_xxx}).
\begin{table}[!htb]
\const{WCONTINUED}& Ritorna anche quando un processo figlio che era stato
fermato ha ripreso l'esecuzione.\footnotemark \\
\hline
- \const{\_\_WCLONE}& Attende solo per i figli creati con \func{clone},
- vale a dire processi che non emettono nessun segnale
- o emettono un segnale diverso da \const{SIGCHL} alla
+ \const{\_\_WCLONE}& Attende solo per i figli creati con \func{clone}
+ (vedi sez.~\ref{sec:process_clone}), vale a dire
+ processi che non emettono nessun segnale
+ o emettono un segnale diverso da \const{SIGCHLD} alla
terminazione. \\
\const{\_\_WALL} & Attende per qualunque processo figlio. \\
\const{\_\_WNOTHREAD}& Non attende per i figli di altri \textit{thread}
indicato dall'argomento \param{path}, che viene interpretato come il
\itindex{pathname} \textit{pathname} del programma.
-\begin{figure}[htb]
- \centering
- \includegraphics[width=12cm]{img/exec_rel}
+\begin{figure}[!htb]
+ \centering \includegraphics[width=12cm]{img/exec_rel}
\caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.}
\label{fig:proc_exec_relat}
\end{figure}
debba essere assegnato all'interno di un intervallo fra un massimo ed un
minimo che nel caso di Linux sono rispettivamente 1 e 99.
-\begin{figure}[!bht]
+\begin{figure}[!htbp]
\footnotesize \centering
- \begin{minipage}[c]{15cm}
+ \begin{minipage}[c]{\textwidth}
\includestruct{listati/sched_param.c}
\end{minipage}
\normalsize
utilizzo non avrà alcun effetto.} Dato che non esiste una interfaccia
diretta nelle \acr{glibc} per queste due funzioni occorrerà invocarle tramite
la funzione \func{syscall} (come illustrato in
-sez.~\ref{sec:intro_syscall}). Le due funzioni sono \funcd{ioprio\_get} ed
+sez.~\ref{sec:proc_syscall}). Le due funzioni sono \funcd{ioprio\_get} ed
\funcd{ioprio\_set}; i rispettivi prototipi sono:
\begin{functions}
\headdecl{linux/ioprio.h}
attengono alla gestione ordinaria dei processi e delle loro proprietà più
comuni. Tratteremo qui alcune \textit{system call} dedicate alla gestione di
funzionalità dei processi molto specifiche ed avanzate, il cui uso è in genere
-piuttosto ridotto. Trattandosi di problematiche relativamente complesse, che
-spesso presuppongono la conoscenza di altri argomenti trattati più avanti
-nella guida, si può saltare questa lezione ad una prima lettura, tornando su
+piuttosto ridotto. Trattandosi di problematiche abbastanza complesse, che
+spesso presuppongono la conoscenza di altri argomenti trattati nel seguito
+della guida, si può saltare questa sezione in una prima lettura, tornando su
di essa in un secondo tempo.
\subsection{La system call \func{clone}}
\label{sec:process_clone}
-Da fare
+La funzione tradizionale con cui creare un nuovo processo in un sistema
+Unix-like, come illustrato in sez.~\ref{sec:proc_fork}, è \func{fork}, ma con
+l'introduzione del supporto del kernel per i \textit{thread} (vedi
+cap.~\ref{cha:threads}), si è avuta la necessità di una interfaccia che
+consentisse un maggiore controllo sulla modalità con cui vengono creati nuovi
+processi, che poi è stata utilizzata anche per fornire supporto per le
+tecnologie di virtualizzazione dei processi (i cosiddetti \textit{container}).
+
+Per questo l'interfaccia per la creazione di un nuovo processo è stata
+delegata ad una nuova \textit{system call}, \func{sys\_clone}, che consente di
+reimplementare anche la tradizionale \func{fork}. In realtà in questo caso più
+che di nuovi processi si può parlare della creazioni di nuovi
+``\textit{task}'' del kernel che possono assumere la veste sia di un processo
+classico come quelli trattati finora, che di un \textit{thread}, come quelli
+che vedremo in sez.~\ref{sec:linux_thread}, in cui la memoria viene condivisa
+fra il processo chiamante ed il nuovo processo creato. Per evitare confusione
+fra \textit{thread} e processi ordinari, abbiamo deciso di usare la
+nomenclatura \textit{task} per indicare la unità di esecuzione generica messa
+a disposizione del kernel che \texttt{sys\_clone} permette di creare.
+
+Oltre a questo la funzione consente, ad uso delle nuove funzionalità di
+virtualizzazione dei processi, di creare nuovi \textit{namespace} per una
+serie di proprietà generali dei processi (come l'elenco dei PID, l'albero dei
+file, dei \textit{mount point}, della rete, ecc.), che consentono di creare
+gruppi di processi che vivono in una sorta di spazio separato dagli altri, che
+costituisce poi quello che viene chiamato un \textit{container}.
+
+La \textit{system call} richiede soltanto due argomenti: il
+primo, \param{flags}, consente di controllare le modalità di creazione del
+nuovo \textit{task}, il secondo, \param{child\_stack}, imposta l'indirizzo
+dello \itindex{stack} \textit{stack} per il nuovo \textit{task}, e deve essere
+indicato quando si intende creare un \textit{thread}. L'esecuzione del
+programma creato da \func{sys\_clone} riprende, come per \func{fork}, da
+dopo l'esecuzione della stessa.
+
+La necessità di avere uno \itindex{stack} \textit{stack} alternativo c'è solo
+quando si intende creare un \textit{thread}, in tal caso infatti il nuovo
+\textit{task} vede esattamente la stessa memoria del \textit{task}
+``\textsl{padre}'',\footnote{in questo caso per padre si intende semplicemente
+ il \textit{task} che ha eseguito \func{sys\_clone} rispetto al \textit{task}
+ da essa creato, senza nessuna delle implicazioni che il concetto ha per i
+ processi.} e nella sua esecuzione alla prima chiamata di una funzione
+andrebbe a scrivere sullo \textit{stack} usato anche dal padre (si ricordi
+quanto visto in sez.~\ref{sec:proc_mem_layout} riguardo all'uso dello
+\textit{stack}).
+
+Per evitare di doversi garantire contro la evidente possibilità di
+\itindex{race~condition} \textit{race condition} che questa situazione
+comporta (vedi sez.~\ref{sec:proc_race_cond} per una spiegazione della
+problematica) è necessario che il chiamante allochi preventivamente un'area di
+memoria. In genere lo si fa con una \func{malloc} che allochi un buffer che
+la funzione imposterà come \textit{stack} del nuovo processo, avendo
+ovviamente cura di non utilizzarlo direttamente nel processo chiamante. In
+questo modo i due \textit{task} avranno degli \textit{stack} indipendenti e
+non si dovranno affrontare problematiche di \itindex{race~condition}
+\textit{race condition}. Si tenga presente inoltre che in molte architetture
+di processore lo \textit{stack} cresce verso il basso, pertanto in tal caso
+non si dovrà specificare per \param{child\_stack} il puntatore restituito da
+\func{malloc}, ma un puntatore alla fine del buffer da essa allocato.
+
+Dato che tutto ciò è necessario solo per i \textit{thread} che condividono la
+memoria, la \textit{system call}, a differenza della funzione di libreria che
+vedremo a breve, consente anche di passare per \param{child\_stack} il valore
+\val{NULL}, che non imposta un nuovo \textit{stack}. Se infatti si crea un
+processo, questo ottiene un suo nuovo spazio degli indirizzi,\footnote{è
+ sottinteso cioè che non si stia usando il flag \const{CLONE\_VM}.} ed in
+questo caso si applica la semantica del \itindex{copy-on-write} \textit{copy
+ on write} illustrata in sez.~\ref{sec:proc_fork}, per cui le pagine dello
+\textit{stack} verranno automaticamente copiate come le altre e il nuovo
+processo avrà un suo \textit{stack} totalmente indipendente da quello del
+padre.
+
+Dato che l'uso principale della nuova \textit{system call} è quello relativo
+alla creazione dei \textit{thread}, le \acr{glibc} definiscono una funzione di
+libreria con una sintassi diversa, orientata a questo scopo, e la
+\textit{system call} resta accessibile solo se invocata esplicitamente come
+visto in sez.~\ref{sec:proc_syscall}.\footnote{ed inoltre per questa
+ \textit{system call} non è disponibile la chiamata veloce con
+ \texttt{vsyscall}.} La funzione di libreria si chiama semplicemente
+\funcd{clone} ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/sched.h}
+
+ \funcdecl{int clone(int (*fn)(void *), void *child\_stack, int
+ flags, void *arg, ... \\
+ /* pid\_t *ptid, struct user\_desc *tls, pid\_t *ctid */)}
+
+ Crea un nuovo processo o \textit{thread} eseguendo la funzione \param{fn}.
+
+ \bodydesc{La funzione ritorna al chiamante il \textit{Thread ID} assegnato
+ al nuovo processo in caso di successo e $-1$ in caso di errore, nel qual
+ caso \var{errno} può assumere i valori:
+ \begin{errlist}
+ \item[\errcode{EAGAIN}] sono già in esecuzione troppi processi.
+ \item[\errcode{EINVAL}] si è usata una combinazione non valida di flag o
+ un valore nullo per \param{child\_stack}.
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare una nuova
+ \struct{task\_struct} o per copiare le parti del contesto del chiamante
+ necessarie al nuovo \textit{task}.
+ \item[\errcode{EPERM}] non si hanno i privilegi di amministratore
+ richiesti dai flag indicati.
+ \end{errlist}
+ }
+\end{functions}
+
+La funzione prende come primo argomento il puntatore alla funzione che verrà
+messa in esecuzione nel nuovo processo, che può avere un unico argomento di
+tipo puntatore a \ctyp{void}, il cui valore viene passato dal terzo
+argomento \param{arg}; per quanto il precedente prototipo possa intimidire
+nella sua espressione, in realtà l'uso è molto semplice basterà definire una
+qualunque funzione \param{fn} del tipo indicato, e \code{fn(arg)} sarà
+eseguita in un nuovo processo.
+
+Il nuovo processo resterà in esecuzione fintanto che la funzione \param{fn}
+non ritorna, o esegue \func{exit} o viene terminata da un segnale. Il valore
+di ritorno della funzione (o quello specificato con \func{exit}) verrà
+utilizzato come stato di uscita della funzione.
+
+I tre argomenti \param{ptid}, \param{tls} e \param{ctid} sono opzionali e sono
+presenti solo a partire dal kernel 2.6.
+
+Il comportamento di \func{clone}, che si riflette sulle caratteristiche del
+nuovo processo da essa creato, è controllato dall'argomento \param{flags},
+
+\begin{basedescript}{\desclabelstyle{\pushlabel}}
+
+\item[\const{CLONE\_CHILD\_CLEARTID}]
+\item[\const{CLONE\_CHILD\_SETTID}]
+\item[\const{CLONE\_FILES}]
+\item[\const{CLONE\_FS}]
+\item[\const{CLONE\_IO}]
+\item[\const{CLONE\_NEWIPC}]
+\item[\const{CLONE\_NEWNET}]
+\item[\const{CLONE\_NEWNS}]
+\item[\const{CLONE\_NEWPID}]
+\item[\const{CLONE\_NEWUTS}]
+\item[\const{CLONE\_PARENT}]
+\item[\const{CLONE\_PARENT\_SETTID}]
+\item[\const{CLONE\_PID}]
+\item[\const{CLONE\_PTRACE}]
+\item[\const{CLONE\_SETTLS}]
+\item[\const{CLONE\_SIGHAND}]
+\item[\const{CLONE\_STOPPED}]
+\item[\const{CLONE\_SYSVSEM}]
+\item[\const{CLONE\_THREAD}]
+\item[\const{CLONE\_UNTRACED}]
+\item[\const{CLONE\_VFORK}]
+\item[\const{CLONE\_VM}]
+\end{basedescript}
+
\subsection{La funzione \func{prctl}}
\label{sec:process_prctl}
fornisce una interfaccia generica per tutte le operazioni specialistiche. La
funzione è \funcd{prctl} ed il suo prototipo è:\footnote{la funzione non è
standardizzata ed è specifica di Linux, anche se ne esiste una analoga in
- IRIX, è stata introdotta con il kernel 2.1.57.}
+ IRIX; è stata introdotta con il kernel 2.1.57.}
\begin{functions}
\headdecl{sys/prctl.h}
Da fare
+% TODO: trattare PTRACE_SEIZE, aggiunta con il kernel 3.1
+
+
\subsection{L'accesso alle porte di I/O}
\label{sec:process_io_port}
% LocalWords: SIGKILL static RLIMIT preemption PREEMPT VOLUNTARY IDLE RTPRIO
% LocalWords: completely fair compat uniform CFQ queuing elevator dev cfq RT
% LocalWords: documentation block syscall ioprio IPRIO CLASS class best effort
-% LocalWords: refresh semop dnotify MADV DONTFORK prctl WCLONE SIGCHL WALL big
-% LocalWords: WNOTHREAD DUMPABLE KEEPCAPS IRIX CAPBSET endianess endian
-% LocalWords: little PPC PowerPC FPEMU NOPRINT SIGFPE FPEXC point FP SW
+% LocalWords: refresh semop dnotify MADV DONTFORK prctl WCLONE WALL big
+% LocalWords: WNOTHREAD DUMPABLE KEEPCAPS IRIX CAPBSET endianess endian flags
+% LocalWords: little PPC PowerPC FPEMU NOPRINT SIGFPE FPEXC point FP SW malloc
% LocalWords: exception EXC ENABLE OVF overflow UND underflow RES INV DISABLED
-% LocalWords: NONRECOV ASYNC KEEP securebits NAME NUL PDEATHSIG SECCOMP
-% LocalWords: secure computing sigreturn TIMING STATISTICAL TSC MCE
+% LocalWords: NONRECOV ASYNC KEEP securebits NAME NUL PDEATHSIG SECCOMP VM
+% LocalWords: secure computing sigreturn TIMING STATISTICAL TSC MCE conditions
% LocalWords: timestamp Stamp SIGSEGV UNALIGN SIGBUS MCEERR AO failure early
%%% Local Variables: