Risistemata introduzione e login
[gapil.git] / session.tex
index 969c05db00568956836ea4bafe8cc1fd63fa949a..67e5129ad880b8598639bf6be5ac9be6a4a4fdfa 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 raggruppamento, 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 (può 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}.\footnote{si tenga presente che \cmd{bg} e \cmd{fg}
+  sono parole chiave che indicano comandi interni alla shell, e nel caso non
+  comportano l'esecuzione di un programma esterno.} 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 sarà
+in grado, grazie all'uso di \func{waitpid}, di rilevare sia i processi che
+sono terminati, sia i raggruppamenti che sono bloccati (in questo caso usando
+l'opzione \macro{WUNTRACED}, secondo quanto illustrato in
+\secref{sec:proc_wait}).
+
+
+\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 raggruppamento 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
+raggruppamento, che si incarica di lanciare tutti gli altri. Un nuovo
+raggruppamento 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{group leader} di un nuovo raggruppamento, tutti
+i successivi processi da esso creati apparterranno (a meno di non cambiare di
+nuovo il \acr{pgid}) al nuovo raggruppamento. È possibile invece spostare un
+processo da un raggruppamento 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}.\footnote{questa caratteristica è implementata
+  dal kernel che mantiene allo scopo un altro campo, \var{did\_exec}, in
+  \var{task\_struct}.}  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 ragruppamento di
+\textit{foreground}, possono leggere e scrivere in certo istante. Per
+impostare il raggruppamento 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 raggruppamenti) 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 fermare 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 di controllo, 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à sì 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 raggruppamento 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 raggruppamento 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 raggruppamento, 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 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, ed essendo stato nel
+frattempo inviato anche \macro{SIGHUP}, se non c'è un gestore per
+quest'ultimo, i processi bloccati verranno automaticamente 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,9 +474,17 @@ 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
-una istanza di un programma che permetta l'accesso ad un terminale.
+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 \figref{fig:sess_term_login}.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[width=15cm]{img/tty_login}
+  \caption{Schema della procedura di login su un terminale.}
+  \label{fig:sess_term_login}
+\end{figure}
 
 Un terminale, che esso sia un terminale effettivo, attaccato ad una seriale o
 ad un altro tipo di porta di comunicazione, o una delle console virtuali
@@ -55,34 +493,38 @@ 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 in \file{/etc/inittab}.
-
-Il programma viene lanciato da \texttt{init} 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, di effettuare, qualora servano, ulteriori
-settaggi,\footnote{ad esempio, come qualcuno si sarà accorto scrivendo un nome
-  di login in maiuscolo, può effettuare la conversione in minuscole
-  automaticamente, ponendosi in una modalità speciale che non distingue fra i
-  due tipi di caratteri (a beneficio di vecchi terminali che non supportano le
-  minuscole).} ed infine di stampare un messaggio di benvenuto e porsi in
-attesa dell'immissione del nome di un utente.
-
-Una volta che si sia immesso un nome di login \cmd{getty} esegue 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 variabile di ambiente
-\texttt{TERM}) ad identificare il terminale su cui si sta operando, a
-beneficio dei programmi che verranno lanciati in seguito.
+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 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).} 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
+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.
 
 A sua volta \cmd{login}, che mantiene i privilegi di amministratore, usa il
 nome dell'utente per effettuare una ricerca nel database degli
@@ -96,85 +538,58 @@ 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 provvederà
-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)
-ad eseguire con un'altra \func{exec} la shell di login, che si troverà con un
-ambiente già pronto e con file standard di \secref{sec:file_std_descr}
-impostati sul terminale, pronta ad eseguire i comandi fino all'uscita. Dato
-che il processo genitore resta sempre \cmd{init} quest'ultimo provvederà,
-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}
+ad eseguire con un'altra \func{exec} la shell, che si troverà con un ambiente
+già pronto con i file standard di \secref{sec:file_std_descr} impostati sul
+terminale, e pronta, nel ruolo di leader di sessione e processo di controllo
+per il terminale, a gestire l'esecuzione dei comandi come illustrato in
+\secref{sec:sess_job_control_overview}. Dato che il processo padre resta
+sempre \cmd{init} quest'ultimo potrà provvedere, ricevendo un \macro{SIGCHLD}
+all'uscita della shell, a rilanciare \cmd{getty} sul terminale per ripetere da
+capo tutto il procedimento.
 
-Nel caso di un login via rete la cosa si fa leggermente diversa, in tal caso
-infatti non essendo possibile prevedere 
 
 
-\subsection{Il login attraverso X}
-\label{sec:sess_X_log}
+\subsection{Prescrizioni per un programma \textit{daemon}}
+\label{sec:sess_daemon}
 
-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}
+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.
 
-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.
+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{La struttura di base}
-\label{sec:sess_relation}
 
+\section{L'I/O su terminale}
+\label{sec:sess_terminal_io}
 
+Esamineremo in questa sezione le peculiarità dell'I/O eseguito sui terminali,
+tenendo conto delle differenze che quest'ultimi presentano rispetto ai normali
+file su disco.
 
 
-\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}
-
-
-
-\subsection{La shell e i programmi}
-\label{sec:sess_shell}
 
 
 %%% Local Variables: