capacità multitasking di un sistema Unix per eseguire in contemporanea più
processi, pur potendo accedere, di solito, ad un solo terminale,\footnote{con
X e con i terminali virtuali tutto questo non è più vero, dato che si può
- accedere a molti terminali in contemporanea, ma il sistema è nato prima
- dell'esistenza di tutto ciò.} avendo cioè un solo punto in cui si può avere
-accesso all'input ed all'output degli stessi.
+ accedere a molti terminali in contemporanea da una singola postazione di
+ lavoro, ma il sistema è nato prima dell'esistenza di tutto ciò.} avendo cioè
+un solo punto in cui si può avere accesso all'input ed all'output degli
+stessi.
\subsection{Una panoramica introduttiva}
driver per i terminali abilitato al \textit{job control} che quella dei
relativi segnali illustrati in \secref{sec:sig_job_control}.
-In un sistema che supporta il \textit{job control} una volta completato il
-login (che esamineremo in dettaglio in \secref{sec:sess_login}), l'utente avrà
-a disposizione una shell dalla quale eseguire i comandi e potrà iniziare
-quella che viene chiamata una \textsl{sessione}, che riunisce (vedi
-\secref{sec:sess_proc_group}) tutti i processi eseguiti all'interno dello
-stesso login.
-
-Siccome la shell è collegata ad un solo terminale (che viene usualmente
-chiamato \textsl{terminale di controllo}) un solo comando alla volta (quello
-che viene detto in \textit{foreground}), potrà scrivere e leggere dal
-terminale. La shell però può eseguire anche più comandi in contemporanea,
-mandandoli in \textit{background} (aggiungendo una \cmd{\&} alla fine del
-comando), nel qual caso essi saranno eseguiti senza essere collegati al
-terminale.
+In un sistema che supporta il \textit{job control}, una volta completato il
+login, l'utente avrà a disposizione una shell dalla quale eseguire i comandi e
+potrà iniziare quella che viene chiamata una \textsl{sessione}, che riunisce
+(vedi \secref{sec:sess_proc_group}) tutti i processi eseguiti all'interno
+dello stesso login (esamineremo tutto il processo in dettaglio in
+\secref{sec:sess_login}).
+
+Siccome la shell è collegata ad un solo terminale, che viene usualmente
+chiamato \textsl{terminale di controllo}, (vedi \secref{sec:sess_ctrl_term})
+un solo comando alla volta (quello che viene detto in \textit{foreground}),
+potrà scrivere e leggere dal terminale. La shell però può eseguire anche più
+comandi in contemporanea, mandandoli in \textit{background} (aggiungendo una
+\cmd{\&} alla fine del comando), nel qual caso essi saranno eseguiti senza
+essere collegati al terminale.
Si noti come si sia parlato di comandi e non di programmi o processi; fra le
funzionalità della shell infatti c'è anche quella di consentire di concatenare
Per questo l'esecuzione di un comando può originare più di un processo; quindi
nella gestione del job control non si può far riferimento ai singoli processi.
Per questo il kernel prevede la possibilità di raggruppare più processi in un
-\textit{process group} (detto anche \textsl{raggruppamento}, vedi
+\textit{process group} (detto anche \textsl{raggruppamento di processi}, vedi
\secref{sec:sess_proc_group}) e la shell farà sì che tutti i processi che
originano da una riga di comando appartengano allo stesso \textit{process
group}, in modo che le varie funzioni di controllo, ed i segnali inviati dal
processi che possono accedere al terminale, e più \textit{process group} in
\textit{background}, che non possono accedervi. Il job control prevede che
quando un processo appartenente ad un raggruppamento in \textit{background}
-cerca di accedere al terminale questo invii a tutti i processi del
-raggruppamento un segnale di \macro{SIGTTIN} o di \macro{SIGTTOU}, a seconda
-che l'accesso sia rispettivamente in lettura o scrittura, bloccando (secondo
-il comportamento di default esposto in \secref{sec:sig_job_control}) i
-processi.
+cerca di accedere al terminale, venga inviato un segnale a tutti i processi
+del raggruppamento, in modo da bloccarli (vedi \secref{sec:sess_ctrl_term}).
Un comportamento analogo si ha anche per i segnali generati dai comandi di
-tastiera inviati dal terminale con \cmd{C-z}, \cmd{C-c}, \cmd{C-y} e
-\verb|C-\|; questi generano rispettivamente i segnali \macro{SIGTSTP},
-\macro{SIGINT}, \macro{SIGQUIT} e \macro{SIGTERM}, che vengono inviati a tutti
-i processi del raggruppamento in \textit{foreground}. In particolare il primo
-di essi, \macro{SIGTSTP}, interrompe l'esecuzione del comando, che può poi
-essere mandato in \textit{background} con il comando \cmd{bg}. Il comando
-\cmd{fg} consente invece di mettere in \textit{foreground} un comando
-precedentemente lanciato in \textit{background}.
+tastiera inviati dal terminale che vengono inviati a tutti i processi del
+raggruppamento in \textit{foreground}. In particolare \cmd{C-z} interrompe
+l'esecuzione del comando, che può poi essere mandato in \textit{background}
+con il comando \cmd{bg}. Il comando \cmd{fg} consente invece di mettere in
+\textit{foreground} un comando precedentemente lanciato in
+\textit{background}.
Di norma la shell si cura anche di notificare all'utente (di solito prima
della stampa a video del prompt) lo stato dei vari processi, essa infatti usa
Come accennato in \secref{sec:sess_job_control_overview} nel job control i
processi vengono raggruppati in \textit{process group} e \textit{sessioni};
per far questo vengono utilizzati due ulteriori identificatori (oltre quelli
-visti in \secref{sec:proc_pid}) che il kernel associa a ciascun processo:
-l'identificatore del \textit{process group} e l'identificatore della
-\textsl{sessione}, che vengono indicati rispettivamente con le sigle
-\acr{pgid} e \acr{sid}, e sono mantenuti in variabili di tipo \type{pid\_t}. I
-valori di questi identificatori possono essere visualizzati dal comando
-\cmd{ps} usando l'opzione \cmd{-j}.
+visti in \secref{sec:proc_pid}) che il kernel associa a ciascun
+processo:\footnote{in Linux questi identificatori sono mantenuti nei campi
+ \var{pgrp} e \var{session} della struttura \var{task\_struct} definita in
+ \file{sched.h}.} l'identificatore del \textit{process group} e
+l'identificatore della \textsl{sessione}, che vengono indicati rispettivamente
+con le sigle \acr{pgid} e \acr{sid}, e sono mantenuti in variabili di tipo
+\type{pid\_t}. I valori di questi identificatori possono essere visualizzati
+dal comando \cmd{ps} usando l'opzione \cmd{-j}.
Un \textit{process group} è pertanto definito da tutti i processi che hanno lo
stesso \acr{pgid}; è possibile leggere il valore di questo identificatore con
\begin{errlist}
\item[\macro{ESRCH}] Il processo selezionato non esiste.
\item[\macro{EPERM}] Il cambiamento non è consentito.
+ \item[\macro{EACCESS}] Il processo ha già eseguito una \func{exec}.
\item[\macro{EINVAL}] Il valore di \param{pgid} è negativo.
\end{errlist}
}
La funzione imposta il \acr{pgid} ed il \acr{sid} del processo corrente al
valore del suo \acr{pid}, creando così una nuova sessione ed un nuovo
\textit{process group} di cui esso diventa leader (come per i \textit{process
- group} un processo si dice leader di sessione se il suo \acr{sid} è uguale
-al suo \acr{pid}). Inoltre il processo non avrà più un terminale di
-controllo.
-
-La funzione ha successo soltanto se il processo non è già leader per un
+ group} un processo si dice leader di sessione\footnote{in Linux la proprietà
+ è mantenuta in maniera indipendente con un apposito campo \var{leader} in
+ \var{task\_struct}.} se il suo \acr{sid} è uguale al suo \acr{pid}) ed unico
+componente. Inoltre la funzione distacca il processo da ogni terminale di
+controllo (torneremo sull'argomento in \secref{sec:sess_ctrl_term}) cui fosse
+in precedenza associato.
+
+ funzione ha successo soltanto se il processo non è già leader di un
\textit{process group}, per cui per usarla di norma si esegue una \func{fork}
e si esce, per poi chiamare \func{setsid} nel processo figlio, in modo che,
avendo questo lo stesso \acr{pgid} del padre ma un \acr{pid} diverso, non ci
-siano possibilità di errore. Questa funzione viene usata di solito nel
-processo di login (per i dettagli vedi \secref{sec:sess_login}) per
-raggruppare in una sessione tutti i comandi eseguiti da un utente dalla sua
-shell.
+siano possibilità di errore.\footnote{potrebbe sorgere il dubbio che, per il
+ riutilizzo dei valori dei \acr{pid} fatto nella creazione dei nuovi processi
+ (vedi \secref{sec:proc_pid}), il figlio venga ad assumere un valore
+ corrispondente ad un process group esistente; questo viene evitato dal
+ kernel che considera come disponibili per un nuovo \acr{pid} solo valori che
+ non corrispondono ad altri \acr{pid}, \acr{pgid} o \acr{sid} in uso nel
+ sistema.} Questa funzione viene usata di solito nel processo di login (per i
+dettagli vedi \secref{sec:sess_login}) per raggruppare in una sessione tutti i
+comandi eseguiti da un utente dalla sua shell.
-\subsection{Il terminale di controllo}
+\subsection{Il terminale di controllo e il controllo di sessione}
\label{sec:sess_ctrl_term}
-Come accennato in \secref{sec:sess_job_control_overview} ad ogni sessione di
-lavoro di norma viene associato un terminale di controllo. Alla creazione
-della sessione con \func{setsid} infatti ogni associazione con un precedente
-terminale di controllo viene spezzata, ed il processo dovrà riottenere (se
-necessario, vedi \secref{sec:sess_daemon}), un terminale di controllo.
+Come accennato in \secref{sec:sess_job_control_overview}, nel sistema del
+\textit{job control} i processi all'interno di una sessione fanno riferimento
+ad un terminale di controllo (ad esempio quello su cui si è effettuato il
+login), sul quale effettuano le operazioni di lettura e
+scrittura,\footnote{nel caso di login grafico la cosa può essere più
+ complessa, e di norma l'I/O è effettuato tramite il server X, ma ad esempio
+ per i programmi, anche grafici, lanciati da un qualunque emulatore di
+ terminale, sarà quest'ultimo a fare da terminale (virtuale) di controllo.} e
+dal quale ricevono gli eventuali segnali da tastiera.
+
+A tale scopo lo standard POSIX.1 prevede che ad ogni sessione possa essere
+associato un terminale di controllo; in Linux questo viene realizzato
+mantenendo fra gli attributi di ciascun processo anche qual'è il suo terminale
+di controllo. \footnote{Lo standard POSIX.1 non specifica nulla riguardo
+ l'implementazione; in Linux anch'esso viene mantenuto nella solita struttura
+ \var{task\_struct}, nel campo \var{tty}.} In generale ogni processo eredita
+dal padre, insieme al \acr{pgid} e al \acr{sid} anche il terminale di
+controllo (vedi \secref{sec:proc_fork}). In questo modo tutti processi
+originati dallo stesso leader di sessione mantengono lo stesso terminale di
+controllo.
+
+Alla creazione di una nuova sessione con \func{setsid} ogni associazione con
+il precedente terminale di controllo viene cancellata, ed il processo che è
+divenuto un nuovo leader di sessione dovrà riottenere\footnote{solo quando ciò
+ è necessario, cosa che, come vedremo in \secref{sec:sess_daemon}, non è
+ sempre vera}, un terminale di controllo. In generale questo viene fatto
+automaticamente dal sistema\footnote{a meno di non avere richiesto
+ esplicitamente che questo non diventi un terminale di controllo con il flag
+ \macro{O\_NOCTTY} (vedi \secref{sec:file_open}). In questo Linux segue la
+ semantica di SVr4; BSD invece richiede che il terminale venga allocato
+ esplicitamente con una \func{ioctl} con il comando \macro{TIOCSCTTY}.}
+quando viene aperto il primo terminale (cioè uno dei vari file di dispositivo
+\file{/dev/tty*}) che diventa automaticamente il terminale di controllo,
+mentre il processo diventa il \textsl{processo di controllo} di quella
+sessione.
+
+In genere (a meno di redirezioni) nelle sessioni di lavoro questo terminale è
+associato ai file standard (di input, output ed error) dei processi nella
+sessione, ma solo quelli che fanno parte del cosiddetto gruppo di
+\textit{foreground}, possono leggere e scrivere in certo istante. Per
+impostare il gruppo di \textit{foreground} di un terminale si usa la funzione
+\func{tcsetpgrp}, il cui prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+
+ \funcdecl{int tcsetpgrp(int fd, pid\_t pgrpid)} Imposta a \param{pgrpid} il
+ \textit{process group} di \textit{foreground} del terminale associato al
+ file descriptor \param{fd}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\macro{ENOTTY}] Il file \param{fd} non corrisponde al terminale di
+ controllo del processo chiamante.
+ \item[\macro{ENOSYS}] Il sistema non supporta il job control.
+ \item[\macro{EPERM}] Il \textit{process group} specificato non è nella
+ stessa sessione del processo chiamante.
+ \end{errlist}
+ ed inoltre \macro{EBADF} ed \macro{EINVAL}.
+ }
+\end{functions}
+\noindent la funzione può essere eseguita con successo solo da
+un processo nella stessa sessione e con lo stesso terminale di controllo.
+
+Come accennato in \secref{sec:sess_job_control_overview}, tutti i processi (e
+relativi gruppi) che non fanno parte del gruppo di \textit{foreground} sono
+detti in \textit{background}; se uno si essi cerca di accedere al terminale di
+controllo provocherà l'invio da parte del kernel di uno dei due segnali
+\macro{SIGTTIN} o \macro{SIGTTOU} (a seconda che l'accesso sia stato in
+lettura o scrittura) a tutto il suo \textit{process group}; dato che il
+comportamento di default di questi segnali (si riveda quanto esposto in
+\secref{sec:sig_job_control}) è di bloccare il processo, di norma questo
+comporta che tutti i membri del gruppo verranno fermati, ma non si avranno
+condizioni di errore.\footnote{la shell in genere notifica comunque un
+ avvertimento, avvertendo la presenza di processi bloccati grazie all'uso di
+ \func{waitpid}.} Se però si bloccano o ignorano i due segnali citati, le
+funzioni di lettura e scrittura falliranno con un errore di \macro{EIO}.
+
+Un processo può contollare qual'è il gruppo di \textit{foreground} associato
+ad un terminale con la funzione \func{tcgetpgrp}, il cui prototipo è:
+\begin{functions}
+ \headdecl{unistd.h} \headdecl{termios.h}
+
+ \funcdecl{pid\_t tcgetpgrp(int fd)} Legge il \textit{process group} di
+ \textit{foreground} del terminale associato al file descriptor \param{fd}.
+ \bodydesc{La funzione restituisce in caso di successo il \acr{pgid} del
+ gruppo di \textit{foreground}, e -1 in caso di errore, nel qual caso
+ \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\macro{ENOTTY}] Non c'è un terminale di controllo o \param{fd} non
+ corrisponde al terminale di controllo del processo chiamante.
+ \end{errlist}
+ ed inoltre \macro{EBADF} ed \macro{ENOSYS}.
+ }
+\end{functions}
+
+Si noti come entrambe le funzioni usino come argomento il valore di un file
+descriptor, il risultato comunque non dipende dal file descriptor che si usa
+ma solo dal terminale cui fa riferimento; il kernel inoltre permette a ciascun
+processo di accedere direttamente al suo terminale di controllo attraverso il
+file speciale \file{/dev/tty}, che per ogni processo è un sinonimo per il
+proprio terminale di controllo. Questo consente anche a processi che possono
+aver rediretto l'output di accedere al terminale, pur non disponendo più del
+file descriptor originario; un caso tipico è il programma \cmd{crypt} che
+accetta la redirezione sullo standard input di un file da decrittare, ma deve
+poi leggere la password dal terminale.
+
+Un'altra caratteristica del terminale di controllo usata nel job control è che
+utilizzando su di esso le combinazioni di tasti speciali (\cmd{C-z},
+\cmd{C-c}, \cmd{C-y} e \verb|C-\|) si farà si che il kernel invii i
+corrispondenti segnali (rispettivamente \macro{SIGTSTP}, \macro{SIGINT},
+\macro{SIGQUIT} e \macro{SIGTERM}, trattati in \secref{sec:sig_job_control}) a
+tutti i processi del gruppo di \textit{foreground}; in questo modo la shell
+può gestire il blocco e l'interruzione dei vari comandi.
+
+Per completare la trattazione delle caratteristiche del job control legate al
+terminale di controllo, occorre prendere in considerazione i vari casi legati
+alla terminazione anomala dei processi, che sono di norma gestite attraverso
+il segnale \macro{SIGHUP}. Il nome del segnale deriva da \textit{hungup},
+termine che viene usato per indicare la condizione in cui il terminale diventa
+inutilizzabile, (letteralmente sarebbe \textsl{impiccagione}).
+
+Quando si verifica questa condizione, ad esempio se si interrompe la linea, o
+va giù la rete o più semplicemente si chiude forzatamente la finestra di
+terminale su cui si stava lavorando, il kernel provvederà ad inviare il
+segnale di \macro{SIGHUP} al processo di controllo. L'azione preimpostata in
+questo caso è la terminazione del processo, il problema che si pone è cosa
+accade agli altri processi nella sessione, che non han più un processo di
+controllo che possa gestire l'accesso al terminale, che potrebbe essere
+riutilizzato per qualche altra sessione.
+
+Lo standard POSIX.1 prevede che quando il processo di controllo termina, che
+ciò avvenga o meno per un \textit{hungup} del terminale (ad esempio si
+potrebbe terminare direttamente la shell con \cmd{kill}) venga inviato un
+segnale di \macro{SIGHUP} ai processi del gruppo di foreground. In questo modo
+essi potranno essere avvisati che non esiste più un processo in grado di
+gestire il terminale (di norma tutto ciò comporta la terminazione anche di
+questi ultimi).
+
+Restano però gli eventuali processi in background, che non ricevono il
+segnale; in effetti se il terminale non dovesse più servire essi potrebbero
+proseguire fino al completamento della loro esecuzione; ma si pone il problema
+di come gestire quelli che sono bloccati, o che si bloccano nell'accesso al
+terminale, in assenza di un processo che sia in grado di effettuare il
+controllo dello stesso.
+
+Questa è la situazione in cui si ha quello che viene chiamato un
+\textit{orphaned process group}. Lo standard POSIX.1 lo definisce come un
+\textit{process group} i cui processi hanno come padri esclusivamente o altri
+processi nel gruppo, o processi fuori della sessione. Lo standard prevede
+inoltre che se la terminazione di un processo fa sì che un raggruppamento di
+processi diventi orfano e se i suoi membri sono bloccati, ad essi vengano
+inviati in sequenza i segnali di \macro{SIGHUP} e \macro{SIGCONT}.
+
+La definizione può sembrare complicata, e a prima vista non è chiaro cosa
+tutto ciò abbia a che fare con il problema della terminazione del processo di
+controllo. Consideriamo allora cosa avviene di norma nel \textit{job
+ control}: una sessione viene creata con \func{setsid} che crea anche un
+nuovo process group: per definizione quest'ultimo è sempre \textsl{orfano},
+dato che il padre del leader di sessione è fuori dalla stessa e il nuovo
+process group contiene solo il leader di sessione. Questo è un caso limite, e
+non viene emesso nessun segnale perché quanto previsto dallo standard riguarda
+solo i raggruppamenti che diventano orfani in seguito alla terminazione di un
+processo.\footnote{l'emissione dei segnali infatti avviene solo nella fase di
+ uscita del processo, come una delle operazioni legate all'esecuzione di
+ \func{_exit}, secondo quanto illustrato in \secref{sec:proc_termination}.}
+
+Il leader di sessione provvederà a creare nuovi raggruppamenti di processi che
+a questo punto non sono orfani in quanto esso resta padre per almeno uno dei
+processi del gruppo (gli altri possono derivare dal primo). Alla terminazione
+del leader di sessione però avremo che, come visto in
+\secref{sec:proc_termination}, tutti i suoi figli vengono adottati da
+\cmd{init}, che è fuori dalla sessione. Questo renderà orfani tutti i process
+group creati direttamente dal leader di sessione (a meno di non aver spostato
+con \func{setpgid} un processo da un gruppo ad un altro, cosa che di norma non
+viene fatta) i quali riceveranno, nel caso siano bloccati, i due segnali:
+\macro{SIGCONT} ne farà proseguire l'esecuzione, e, essendo stato nel
+frattempo inviato anche \macro{SIGHUP}, se non c'è un gestore per
+quest'ultimo, essi saranno terminati.
+
-Le modalità con cui
\subsection{Dal login alla shell}
per ripetere da capo tutto il procedimento.
+In generale quando con il contollo di sessione è la shell che assume il ruolo
+di processo di controllo, seleziona il gruppo di \textit{foregroud} e gestisce
+l'assegnazione dei process group ai programmi eseguiti sulla stessa riga di
+comando.
+
+Qualora un processo venga bloccato nella gestione della sessione, sia
+implicitamente, perché cerca di eseguire dell'I/O sul terminale mentre è in
+background, sia esplicitamente con l'uso di \cmd{C-z}, la shell è in grado di
+rilevare l'evento grazie all'uso di \func{waitpid} con l'opzione
+\macro{WUNTRACED}. In questo modo la shell può notificare (di solito prima
+della stampa del prompt, lo stato dei vari processi.
+
+
+
+
\subsection{Prescrizioni per un programma \textit{daemon}}
\label{sec:sess_daemon}