Ancora orphaned process group
[gapil.git] / session.tex
index c6f1ce955506f7d1a49bf6ba38bec896876359f2..2f73d61b53bd790d8a3f0303dcf86eb926c7ac63 100644 (file)
-\chapter{Sessioni di lavoro}
+ \chapter{Sessioni di lavoro e terminali}
 \label{cha:session}
 
-Esamineremo in questo capitolo le modalità in cui sono organizzati i processi
-all'interno del sistema e le varie relazioni che intercorrono fra di essi, e
-le modalità che permettono, a partire dall'avvio del sistema, di organizzare
-il lavoro degli utenti in sessioni di lavoro associate ai terminali di
-controllo con cui essi si sono collegati al sistema.
+Esamineremo in questo capitolo i concetti base del sistema delle sessioni di
+lavoro, vale a dire il metodo con cui il kernel gestisce l'accesso concorrente
+al sistema da parte di più utenti, permettendo loro di eseguire più programmi
+in contemporanea.  Nella seconda parte del capitolo tratteremo poi il
+funzionamento dell'I/O su terminale, e delle varie peculiarità che esso viene
+ad assumere a causa del suo stretto legame con le modalità di accesso al
+sistema da parte degli utenti.
 
-\section{La procedura di login}
+
+\section{Il \textit{job control}}
+\label{sec:sess_job_control}
+
+Viene comunemente chiamato \textit{job control} quell'insieme di funzionalità
+il cui scopo è quello di permettere ad un utente di poter sfruttare le
+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 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}
+\label{sec:sess_job_control_overview}
+
+Il \textit{job control} è una caratteristica opzionale, introdotta in BSD
+negli anni '80, e successivamente standardizzata da POSIX.1; la sua
+disponibilità nel sistema è verificabile attraverso il controllo della macro
+\macro{\_POSIX\_JOB\_CONTROL}. In generale il \textit{job control} richiede il
+supporto sia da parte della shell (quasi tutte ormai lo fanno), che da parte
+del kernel; in particolare il kernel deve assicurare sia la presenza di un
+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, 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
+più programmi in una sola riga di comando con le pipe, ed in tal caso verranno
+eseguiti più programmi, inoltre, anche quando si invoca un singolo programma,
+questo potrà sempre lanciare sottoprocessi per eseguire dei compiti specifici.
+
+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 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
+terminale, possano fare riferimento ad esso.
+
+In generale allora all'interno di una sessione avremo un eventuale (possono
+non esserci) \textit{process group} in \textit{foreground}, che riunisce i
+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, 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 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
+le caratteristiche della funzione \func{waitpid} (si riveda quanto detto in
+\secref{sec:proc_wait}) per verificare quali gruppi di processi sono bloccati
+e quali sono terminati. 
+
+
+\subsection{I \textit{process group} e le \textsl{sessioni}}
+\label{sec:sess_proc_group}
+
+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:\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
+le funzioni \func{getpgid} e \func{getpgrp},\footnote{\func{getpgrp} è
+  definita nello standard POSIX.1, mentre \func{getpgid} è richiesta da SVr4.}
+i cui prototipi sono:
+\begin{functions}
+  \headdecl{unistd.h}
+
+  \funcdecl{pid\_t getpgid(pid\_t pid)} 
+  Legge il \acr{pgid} del processo \param{pid}.
+
+  \funcdecl{pid\_t getpgrp(void)}
+  Legge il \acr{pgid} del processo corrente.
+  
+  \bodydesc{Le funzioni restituiscono il \acr{pgid} del processo,
+    \func{getpgrp} ha sempre successo, mentre \func{getpgid} restituisce -1
+    ponendo \var{errno} a \macro{ESRCH} se il processo selezionato non esiste.}
+\end{functions}
+
+La funzione \func{getpgid} permette di specificare il \acr{pid} del processo
+di cui si vuole sapere il \acr{pgid}; un valore nullo per \param{pid}
+restituisce il \acr{pgid} del processo corrente; \func{getpgrp} è di norma
+equivalente a \code{getpgid(0)}.
+
+In maniera analoga l'identificatore della sessione può essere letto dalla
+funzione \func{getsid}, che però nelle \acr{glibc}\footnote{la system call è
+  stata introdotta in Linux a partire dalla versione 1.3.44, il supporto nelle
+  librerie del C è iniziato dalla versione 5.2.19. La funzione non è prevista
+  da POSIX.1, che parla solo di processi leader di sessione, e non di
+  identificatori di sessione.} è accessibile solo definendo
+\macro{\_XOPEN\_SOURCE} e \macro{\_XOPEN\_SOURCE\_EXTENDED}; il suo prototipo
+è:
+\begin{prototype}{unistd.h}{pid\_t getsid(pid\_t pid)}
+  Legge l'identificatore di sessione del processo \param{pid}.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un numero positivo) in
+  caso di successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà
+  i valori:
+    \begin{errlist}
+    \item[\macro{ESRCH}] Il processo selezionato non esiste.
+    \item[\macro{EPERM}] In alcune implementazioni viene restituito quando il
+      processo selezionato non fa parte della stessa sessione del processo
+      corrente.
+    \end{errlist}
+  }
+\end{prototype}
+
+Entrambi gli identificatori vengono inizializzati alla creazione di ciascun
+processo con lo stesso valore che hanno nel processo padre, per cui un
+processo appena creato appartiene sempre allo stesso raggruppamento e alla
+stessa sessione del padre. Vedremo poi come sia possibile creare più
+\textit{process group} all'interno della stessa sessione, e spostare i
+processi dall'uno all'altro, ma sempre all'interno di una stessa sessione.
+
+Ciascun gruppo di processi ha sempre un processo principale, il cosiddetto
+\textit{process group leader}, che è identificato dall'avere un \acr{pgid}
+uguale al suo \acr{pid}, in genere questo è il primo processo del gruppo, che
+si incarica di lanciare tutti gli altri. Un nuovo gruppo si crea con la
+funzione \func{setpgrp},\footnote{questa è la definizione di POSIX.1, BSD
+  definisce una funzione con lo stesso nome, che però è identica a
+  \func{setpgid}; nelle \acr{glibc} viene sempre usata sempre questa
+  definizione, a meno di non richiedere esplicitamente la compatibilità
+  all'indietro con BSD, definendo la macro \macro{\_BSD\_SOURCE}.} il cui
+prototipo è:
+\begin{prototype}{unistd.h}{int setpgrp(void)}
+  Modifica il \acr{pgid} al valore del \acr{pid} del processo corrente.
+  
+  \bodydesc{La funzione restituisce il valore del nuovo \textit{process
+      group}.}
+\end{prototype}
+
+La funzione, assegnando al \acr{pgid} il valore del \acr{pid} processo
+corrente, rende questo \textit{process leader} di un nuovo gruppo, tutti i
+successivi processi da esso creati apparterranno (a meno di non cambiare di
+nuovo il \acr{pgid}) al nuovo gruppo. È possibile invece spostare un processo
+da un gruppo ad un altro con la funzione \func{setpgid}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int setpgid(pid\_t pid, pid\_t pgid)}
+  Assegna al \acr{pgid} del processo \param{pid} il valore \param{pgid}.
+  
+  \bodydesc{La funzione ritorna il valore del nuovo \textit{process group}, e
+  -1 in caso di errore, nel qual caso \var{errno} assumerà i valori:
+    \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}
+ }
+\end{prototype}
+
+La funzione permette di cambiare il \acr{pgid} del processo \param{pid}, ma il
+cambiamento può essere effettuato solo se \param{pgid} indica un
+\textit{process group} che è nella stessa sessione del processo chiamante.
+Inoltre la funzione può essere usata soltanto sul processo corrente o su uno
+dei suoi figli, ed in quest'ultimo caso ha successo soltanto se questo non ha
+ancora eseguito una \func{exec}. Specificando un valore nullo per \param{pid}
+si indica il processo corrente, mentre specificando un valore nullo per
+\param{pgid} si imposta il \textit{process group} al valore del \acr{pid} del
+processo selezionato; pertanto \func{setpgrp} è equivalente a \code{setpgid(0,
+  0)}.
+
+Di norma questa funzione viene usata dalla shell quando si usano delle
+pipeline, per mettere nello stesso process group tutti i programmi lanciati su
+ogni linea di comando; essa viene chiamata dopo una \func{fork} sia dal
+processo padre, per impostare il valore nel figlio, che da quest'ultimo, per
+sé stesso, in modo che il cambiamento di \textit{process group} sia immediato
+per entrambi; una delle due chiamate sarà ridondante, ma non potendo
+determinare quale dei due processi viene eseguito per primo, occorre eseguirle
+comunque entrambe per evitare di esporsi ad una race condition. 
+
+Si noti come nessuna delle funzioni esaminate finora permetta di spostare un
+processo da una sessione ad un altra; infatti l'unico modo di far cambiare
+sessione ad un processo è quello di crearne una nuova con l'uso di
+\func{setsid}; il suo prototipo è:
+\begin{prototype}{unistd.h}{pid\_t setsid(void)}
+  Crea una nuova sessione sul processo corrente settandone \acr{sid} e
+  \acr{pgid}.
+  
+  \bodydesc{La funzione ritorna il valore del nuovo \acr{sid}, e -1 in caso di
+    errore, il solo errore possibile è \macro{EPERM}, che si ha quando il
+    \acr{pgid} e \acr{pid} del processo concidono.}
+\end{prototype}
+
+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\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.\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 e il controllo di sessione}
+\label{sec:sess_ctrl_term}
+
+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.
+
+
+
+
+\subsection{Dal login alla shell}
 \label{sec:sess_login}
 
-L'organizzazione del sistema del \textit{Job Control}\footnote{viene
-  usualmente chiamata così la capacità del sistema di poter gestire più
-  processi (i \textit{job}) lanciati in contemporanea a partire da una shell,
-  di solito associata al terminale su cui si è appunto effettuato il login, in
-  modo da poter gestire la possibile presenza di più di un processo che
-  necessita di accedere a quest'ultimo.} è strettamente connessa alle modalità
-con cui un utente accede al sistema, collegandosi ad esso con un terminale,
-che sia questo realmente tale, come un VT100 collegato ad una seriale o
-virtuale, come quelli associati a schermo e tastiera, o semplicemente
-associato ad una connessione di rete. Per questo motivo in questa prima
-sezione prenderemo in esame le modalità di come avviene tutto ciò e di come il
-sistema (a partire da \cmd{init}) sia in grado di gestire il tutto.
-
-
-\subsection{Il login su terminale}
-\label{sec:sess_tty_log}
-
-La modalità più classica di accesso ad un sistema Unix è quella del login su
-terminale, che pertanto esamineremo per prima. Abbiamo già brevemente
-illustrato in \secref{sec:intro_kern_and_sys} le modalità con cui il sistema
-si avvia, e di come, a partire da \cmd{init}, vengano lanciati tutti gli altri
-programmi. Adesso prenderemo in esame in maniera dettagliata le modalità con
-cui si arriva a fornire ad un utente la shell che gli permette di lanciare i
-suoi comandi.
+L'organizzazione del sistema del job control è strettamente connessa alle
+modalità con cui un utente accede al sistema per dare comandi, collegandosi ad
+esso con un terminale, che sia questo realmente tale, come un VT100 collegato
+ad una seriale o virtuale, come quelli associati a schermo e tastiera o ad una
+connessione di rete. Dato che i concetti base sono gli stessi, e dato che alla
+fine le differenze sono\footnote{in generale nel caso di login via rete o di
+  terminali lanciati dall'interfaccia grafica cambia anche il processo da cui
+  ha origine l'esecuzione della shell.} nel device cui il kernel associa i
+file standard (vedi \secref{sec:file_std_descr}) per l'I/O, tratteremo solo il
+caso classico del terminale.
+
+Abbiamo già brevemente illustrato in \secref{sec:intro_kern_and_sys} le
+modalità con cui il sistema si avvia, e di come, a partire da \cmd{init},
+vengano lanciati tutti gli altri processi. Adesso vedremo in maniera più
+dettagliata le modalità con cui il sistema arriva a fornire ad un utente la
+shell che gli permette di lanciare i suoi comandi su un terminale.
 
 Nella maggior parte delle distribuzioni di GNU/Linux\footnote{fa eccezione la
   distribuzione \textit{Slackware}, come alcune distribuzioni su dischetto, ed
@@ -44,10 +469,10 @@ lanciati, ed in quali modalit
 anch'esso definito nello stesso file.
 
 Tralasciando la descrizione del sistema dei run level, (per il quale si
-rimanda alla lettura della pagina di manuale di \cmd{init} e di
-\file{inittab}) quello che comunque viene sempre fatto è di lanciare almeno
+rimanda alla lettura delle pagine di manuale di \cmd{init} e di
+\file{inittab}) quello che comunque viene sempre fatto è di eseguire almeno
 una istanza di un programma che permetta l'accesso ad un terminale. Uno schema
-di massima della procedura è riportato in \secref{fig:sess_term_login}.
+di massima della procedura è riportato in \figref{fig:sess_term_login}.
 
 \begin{figure}[htb]
   \centering
@@ -63,33 +488,36 @@ driver che ne presenta un'interfaccia comune su un apposito file di
 dispositivo. Storicamente i primi terminali erano appunto terminali di
 telescriventi (\textit{teletype}), da cui deriva sia il nome dell'interfaccia,
 \textit{tty}, che quello dei relativi file di dispositivo, che sono sempre
-della forma \texttt{/dev/tty*}.
-
-Per controllare i terminali si usa di solito il programma \cmd{getty} (od una
-delle sue varianti), che permette di mettersi in ascolto sugli stessi. Alla
-radice della catena che porta ad una shell per i comandi perciò c'è sempre
-\cmd{init} che esegue prima una \func{fork} e poi una \func{exec} per lanciare
-una istanza di questo programma su un terminale, il tutto ripetuto per
-ciascuno dei terminali che si hanno a disposizione (o per un certo numero di
-essi, nel caso delle console virtuali), secondo quanto indicato
-dall'amministratore nel file di configurazione del programma,
+della forma \texttt{/dev/tty*}.\footnote{questo vale anche per i terminali
+  vitruali associati alle connessioni di rete con \cmd{telnet} o \cmd{ssh}.}
+
+Per controllare un terminale si usa di solito il programma \cmd{getty} (od una
+delle sue varianti), che permette di mettersi in ascolto su uno di questi
+dispositivi. Alla radice della catena che porta ad una shell per i comandi
+perciò c'è sempre \cmd{init} che esegue prima una \func{fork} e poi una
+\func{exec} per lanciare una istanza di questo programma su un terminale, il
+tutto ripetuto per ciascuno dei terminali che si hanno a disposizione (o per
+un certo numero di essi, nel caso delle console virtuali), secondo quanto
+indicato dall'amministratore nel file di configurazione del programma,
 \file{/etc/inittab}.
 
 Quando viene lanciato da \cmd{init} il programma parte con i privilegi di
-amministratore e con un ambiente vuoto; \cmd{getty} si cura di aprire il
-terminale in lettura sullo standard input ed in scrittura sullo standard
-output e sullo standard error, e di effettuare, qualora servano, ulteriori
-settaggi,\footnote{ad esempio, come qualcuno si sarà accorto scrivendo un nome
+amministratore e con un ambiente vuoto; \cmd{getty} si cura di chiamare
+\func{setsid} per creare una nuova sessione ed un nuovo process group, e di
+aprire il terminale (che così diventa il terminale di controllo della
+sessione) in lettura sullo standard input ed in scrittura sullo standard
+output e sullo standard error; inoltre effettuarà, qualora servano, ulteriori
+settaggi.\footnote{ad esempio, come qualcuno si sarà accorto scrivendo un nome
   di login in maiuscolo, può effettuare la conversione automatica dell'input
   in minuscolo, ponendosi in una modalità speciale che non distingue fra i due
   tipi di caratteri (a beneficio di alcuni vecchi terminali che non
-  supportavano le minuscole).} ed infine il programma stamperà un messaggio di
+  supportavano le minuscole).} Alla fine il programma stamperà un messaggio di
 benvenuto per poi porsi in attesa dell'immissione del nome di un utente.
 
 Una volta che si sia immesso il nome di login \cmd{getty} esegue direttamente
 il programma \cmd{login} con una \func{exevle}, passando come argomento la
-suddetta stringa ed un ambiente opportunamente costruito che contenga quanto
-necessario (ad esempio di solito viene opportunamente inizializzata la
+stringa con il nome, ed un ambiente opportunamente costruito che contenga
+quanto necessario (ad esempio di solito viene opportunamente inizializzata la
 variabile di ambiente \texttt{TERM}) ad identificare il terminale su cui si
 sta operando, a beneficio dei programmi che verranno lanciati in seguito.
 
@@ -105,17 +533,17 @@ la password non corrisponde\footnote{il confronto non viene effettuato con un
 numero di volte dopo di che \cmd{login} esce ed \cmd{init} provvede a
 rilanciare un'altra istanza di \func{getty}.
 
-Se invece la password corrisponde a questo punto \cmd{login} esegue
-\func{chdir} per settare la \textit{home directory} dell'utente, cambia i
-diritti di accesso al terminale (con \func{chown} e \func{chmod}) per
-assegnarne la titolarità all'utente ed al suo gruppo principale, assegnandogli
-al contempo i diritti di lettura e scrittura. Inoltre il programma provvede
-a costruire gli opportuni valori per le variabili di ambiente, come
-\texttt{HOME}, \texttt{SHELL}, ecc. Infine attraverso l'uso di \func{setuid},
-\func{setpid} e \func{initgroups} verrà cambiata l'identità del proprietario
-del processo, infatti, come spiegato in \secref{sec:proc_setuid}, avendo
-invocato tali funzioni con i privilegi di amministratore, tutti gli userid ed
-i groupid (reali, effettivi e salvati) saranno settati a quelli dell'utente.
+Se invece la password corrisponde \cmd{login} esegue \func{chdir} per settare
+la \textit{home directory} dell'utente, cambia i diritti di accesso al
+terminale (con \func{chown} e \func{chmod}) per assegnarne la titolarità
+all'utente ed al suo gruppo principale, assegnandogli al contempo i diritti di
+lettura e scrittura. Inoltre il programma provvede a costruire gli opportuni
+valori per le variabili di ambiente, come \texttt{HOME}, \texttt{SHELL}, ecc.
+Infine attraverso l'uso di \func{setuid}, \func{setpid} e \func{initgroups}
+verrà cambiata l'identità del proprietario del processo, infatti, come
+spiegato in \secref{sec:proc_setuid}, avendo invocato tali funzioni con i
+privilegi di amministratore, tutti gli userid ed i groupid (reali, effettivi e
+salvati) saranno settati a quelli dell'utente.
 
 A questo punto \cmd{login} provvederà (fatte salve eventuali altre azioni
 iniziali, come la stampa di messaggi di benvenuto o il controllo della posta)
@@ -127,78 +555,46 @@ ricevendo un \macro{SIGCHLD} all'uscita della shell, a rilanciare \cmd{getty}
 per ripetere da capo tutto il procedimento.
 
 
-\subsection{Il login via rete}
-\label{sec:sess_net_log}
-
-Nel caso di un login via rete la cosa si fa leggermente diversa, in tal caso
-infatti non esiste un terminale fisico che \cmd{init} può tenere sotto
-controllo diretto, in quanto il collegamento deve avvenire tramite la rete.
-Quello che succede in questo caso è che nel procedimento di avvio del sistema
-si occupa di eseguire tutti i programmi che attivano la connesione di rete,
-per poi avviare tutti i programmi di servizio. 
-
-Questo viene in genere fatto attraverso una serie di script di shell, che
-vengono eseguiti in un preciso ordine (di nuovo la struttura del procedimento
-di avvio di System V va al di là di quanto ci interessa trattare) che
-eseguiranno i programmi richiesti, fra i quali sarà compreso (se
-l'amministratore lo avrà previsto) pure il server per le connessioni di rete. 
-
-Quest'ultimo sarà posto in esecuzione e si metterà in ascolto di eventuali
-connessioni sulla rete, una volta che la procedura di avvio sarà completata
-gli script termineranno ed il server si troverà ad avere \cmd{init} come
-processo padre.  
-
+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. 
 
-\subsection{Il login attraverso X}
-\label{sec:sess_X_log}
+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. 
 
-Quanto scritto finora riguardo i terminali è piuttosto diverso quando si ha a
-che fare con X. In tal caso infatti la procedura grafica per il login è
-gestira da un apposito programma (il cosiddetto \textit{Display Manager}, come
-\cmd{xdm}, che fa parte della distribuzione base di X o uno dei suoi molti
-cloni) che viene lanciato all'avvio insieme agli altri demoni, e che si cura
-di gestire la procedura di login, lanciare eventuali programmi che si vogliono
-attivare all'avvio (sia fondamentali, come il gestore delle fineste, che
-effimeri, come un notificatore di posta in arrivo).
 
-In questo caso q
-
-\section{Il \textit{Job control}}
-\label{sec:sess_job_control}
-
-Lo scopo del \textit{Job control} è quello di permettere ad un utente di poter
-sfruttare le 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 vituali 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 su può avere accesso all'input ed all'output degli stessi.
 
 
 
-\subsection{La struttura di base}
-\label{sec:sess_relation}
+\subsection{Prescrizioni per un programma \textit{daemon}}
+\label{sec:sess_daemon}
 
+Come sottolineato fin da \secref{sec:intro_base_concept}, in un sistema
+unix-like tutte le operazioni sono eseguite tramite processi, comprese quelle
+operazioni di sistema (come l'esecuzione di comandi periodici, o la consegna
+della posta, ed in generale tutti i programmi di servizio) che non hanno a che
+fare con la gestione diretta dei comandi dell'utente.
 
+Questi programmi, che devono essere eseguiti in modalità non interattiva senza
+nessun intervento dell'utente, sono normalmente chiamati \textsl{demoni}, (o
+\textit{daemons}), nome ispirato dagli omonimi spiritelli che svolgevano vari
+compiti, di cui parlava Socrate (che sosteneva di averne uno al suo
+servizio).\footnote{NdT. ricontrollare, i miei ricordi di filosofia sono
+  piuttosto datati.}
 
 
-\subsection{I \textit{process group}}
-\label{sec:sess_proc_group}
-
-
-
-\subsection{Le sessioni}
-\label{sec:sess_sessions}
-
-
-
-\subsection{Il terminale di controllo}
-\label{sec:sess_ctrl_term}
 
 
+\section{L'I/O su terminale}
+\label{sec:sess_terminal_io}
 
-\subsection{La shell e i programmi}
-\label{sec:sess_shell}
+Esamineremo in questa sezione le peculiarità dell'I/O su terminale, tenendo
+conto delle 
 
 
 %%% Local Variables: