"Spazio utente" si riferisce l'ambiente di runtime di normali (al contrario di kernel) processi. Questo non significa necessariamente che questi processi siano effettivamente avviati dagli utenti perchè normalmente un sistema standard ha diversi processi "demoni" (o in background) in esecuzione prima che l'utente apri anche una sessione. I processi demoni sono considerati processi user-space.
Qunado il kernel ternima la sua fase di inizializzazione, avvia il primo processo, init
. Il processo #1 da solo è molto raramente utile di per sé, ed i sistemi Unix-like vengono eseguiti con molti processi aggiuntivi.
Prima di tutto, un processo può clonare se stesso (questo è noto come fork). Il kermel alloca un nuovo (ma identico) spazio di memoria per il processo, ed un'altro processo per usarlo. In questo momento, l'unica differenza tra questi due processi è il loro pid. Il nuovo processo è chiamato di solito processo figlio, ed il processo originale il cui pid non cambia, è chiamato processo padre.
A volte, il processo figlio continua a condurre la sua propria vita indipendentemente dal suo genitore, con i propri dati copiati dal processo genitore. In molti casi, però, questo processo figlio esegue un altro programma. Con poche eccezioni, la memoria viene semplicemente sostituita da quella del nuovo programma, e l'esecuzione di questo nuovo programma inizia. Questo è il meccanismo utilizzato dal processo init (con il processo numero 1) per avviare servizi aggiuntivi ed eseguire l'intera sequenza di avvio. Ad un certo punto, un processo tra i processi figli di
init
avvia un'interfaccia grafica per gli utenti che devono fare il login (la sequenza reale degli eventi è descritta in dettaglio in
Sezione 9.1, «Avvio del sistema»).
Quando un processo completa il compito per cui è stato avviato, termina. Il kernel poi recupera la memoria assegnata a questo processo, e smette di assegnarli porzioni di tempo per l'esecuzione. Al processo genitore viene detto che il proprio processo figlio è terminato, questo permette ad un processo di attendere il completamento del compito delegato ad un processo figlio. Questo comportamento è chiaramente visibile negli interpreti a riga di comando (conosciuti come shell). Quando viene digitato un comando in una shell, il prompt ritorna disponibile solo quando l'esecuzione del comando è completata. La maggior parte delle shell consentono l'esecuzione di comandi in background, si tratta solo di aggiungere un &
alla fine del comando. Il prompt viene subito visualizzato di nuovo, e ciò può causare problemi se il comando ha bisogno di visualizzare i propri dati.
Un "demone" è un processo avviato automaticamente dalla sequenza di avvio. Continua a funzionare (in background) per eseguire operazioni di manutenzione o per fornire servizi ad altri processi. Questa "attività in background" è in realtà arbitraria, e non corrisponde a niente di particolare dal punto di vista del sistema. Sono semplicemente processi, molto simili ad altri processi, che a loro volta si avviano quando arriva il loro intervallo di tempo. La distinzione è solo nel linguaggio umano: un processo che viene eseguito senza interazione con l'utente (in particolare, senza alcuna interfaccia grafica) è detto essere in esecuzione "in background" o "come demone".
B.5.3. Comunicazioni tra Processi
Un processo isolato, sia esso un demone o un'applicazione interattiva, raramente è utile di per sé, ed è per questo ci sono diversi metodi che consentono ai processi separati di comunicare tra loro, sia per lo scambio di dati che per controllarsi l'un l'altro. Il termine generico che si riferisce a questo è comunicazione tra processi, o IPC in breve.
Il più semplice sistema di IPC è quello di utilizzare i file. Il processo che desidera inviare dati scrive in un file (con un nome noto in anticipo), mentre il destinatario deve solo aprire il file e leggere i contenuti.
Nel caso in cui non si desideri memorizzare i dati su disco, è possibile utilizzare una pipe, che è semplicemente un oggetto con due estremità; i byte scritti in una delle estremità sono leggibili dall'altra. Se le estremità sono controllate da processi separati, questo porta ad un canale di comunicazione tra processi semplice e conveniente. Le pipe possono essere classificate in due categorie: pipe con nome, e pipe anonime. Una pipe con nome è rappresentata da una sola voce sul filesystem (anche se i dati trasmessi non sono memorizzati lì), quindi entrambi i processi possono aprirla indipendentemente se la posizione della pipe con nome è nota in anticipo. Nel caso in cui sono collegati processi comunicanti (per esempio, un processo genitore ed un processo figlio), il processo padre può anche creare una pipe anonima prima di fare il fork, ed il processo figlio la eredita. Entrambi i processi saranno quindi in grado di scambiare dati attraverso la pipe senza bisogno del filesystem.
Comunque, non tutte le comunicazioni tra processi sono usate per sposteare dati in giro. In molte situazioni, l'unica informazione che deve essere trasmessa sono i messaggi di controllo come "metti in pausa l'esecuzione" oppure "riprendi l'esecuzione". Unix (e Linux) forniscono un meccanismo noto come signals, attraverso il quale un processo può semplicemente inviare un segnale specifico (scelto da un'elenco predefinito di segnali) ad un'altro processo. L'unico requisito è quello di conoscere il pid del bersaglio.
Per le comunicazioni più complesse, ci sono anche meccanismi che consentono ad un processo di aprire l'accesso, o condividere, parte della sua memoria con altri processi. La memoria ora condivisa tra di essi può essere utilizzata per spostare i dati tra i processi.
Infine, le connessioni di rete possono anche aiutare i processi a comunicare; questi processi possono anche essere in esecuzione su computer diversi, forse anche a migliaia di chilometri di distanza.
E 'abbastanza normale per un tipico sistema Unix-like fare uso di tutti questi meccanismi a vari gradi.
Le librerie di funzioni svolgono un ruolo cruciale in un sistema operativo Unix-like. Esse non sono programmi veri e propri, poiché non possono essere eseguiti da soli, ma raccolte di frammenti di codice che possono essere utilizzate da programmi standard. Tra le librerie comuni, potete trovare:
la libreria standard C (glibc), che contiene le funzioni di base come quelle per aprire i file o le connessioni di rete, ed altre che facilitano le interazioni con il kernel;
i toolkit grafici, come Gtk e Qt, consentono a molti programmi di riutilizzare gli oggetti grafici che forniscono;
la libreria libpng, consente il caricamento, l'interpretazione ed il salvataggio delle immagini in formato PNG.
Grazie a queste librerie, le applicazioni possono riutilizzare il codice esistente. Lo sviluppo delle applicazioni è semplificato dal momento che molte applicazioni possono riutilizzare le stesse funzioni. Con librerie spesso sviluppate da persone diverse, lo sviluppo globale del sistema è più vicino alla filosofia storica di Unix.
Inoltre, queste librerie sono spesso indicate come "librerie condivise", dato che il kernel è in grado di caricarle in memoria solo una volta, anche se più processi utilizzano la stessa libreria allo stesso tempo. Ciò permette risparmio di memoria, se confrontato con la situazione (ipotetica) contraria in cui il codice per una libreria sarebbe caricato tante volte quanti sono i processi che la utilizzano.