Supponiamo di lanciare il comando:
$ mkdir miacartella
Ecco, a grandi linee, cosa accade all'interno del nostro Sistema Operativo:
- invocazione della
fork()
, una system call; - passaggio alla modalità kernel, il bit di modo va a "0". Da questo momento il sistema non reagisce ad eventuali interrupt;
- interruzione del processo in corso sulla CPU e caricamento del codice relativo alla
fork()
(cambio di contesto); - duplicazione della memoria del processo padre (il terminale);
- il processo figlio avrà a disposizione tutte le informazioni del padre, non condivise, duplicate in un'area di memoria distinta;
- uscita dalla modalità kernel, bit di modo a "1". Si è nuovamente sensibili alle interrupt;
- restituzione del controllo del processore al programma.
A questo punto abbiamo due processi detti concorrenti poichè entrambi concorreranno all'uso del processore (sarà lo scheduler a decidere l'ordine di accesso). Il programma prende due strade differenti: il processo padre (il terminale) semplicemente si mette in attesa del termine del figlio (invocando la syscall apposita wait()
), quando ciò si verificherà esso raccoglierà lo stato di terminazione e seguirà le istruzioni del programmatore; vediamo invece come prosegue il cammino del figlio:
- lettura dell'area di memoria in cui è localizzato il codice relativo al programma
mkdir
; - invocazione della system call
exec()
; - passaggio a modalità kernel e cambio di contesto;
- la
exec()
rimpiazza il codice all'interno del processo, che ricordiamo essere ancora il codice relativo al terminale, col codice del nuovo programma richiesto dall'utente (mkdir
); - allocazione della memoria relativa al nuovo programma e lettura dei parametri passati da linea di comando (in questo caso la stringa "miacartella");
- uscita dalla modalità kernel, il controllo è restituito al programma.
All'inizializzazione di un nuovo programma da eseguire, quindi, verrà generato un nuovo PCB identico a quello del processo che ha invocato la fork()
. Sarà la exec()
a trasformare il nuovo PCB, operando sui campi in esso contenuti, in modo tale da renderlo adeguato al programma che si intende lanciare.
Questi sono alcuni dei meccanismi che stanno dietro alla creazione e manipolazione dei processi in Unix.
Ogni qual volta voi aprite un nuovo programma, sia che lo lanciate da terminale, sia che utilizziate l'ausilio di una interfaccia grafica, queste sono le direttive che il kernel Linux riceve ed esegue.