La chiamata di sistema UNIX per la creazione del processo, fork(), crea un processo figlio copiando il processo padre. La mia comprensione è che questo è quasi sempre seguito da una chiamata a exec() per sostituire lo spazio di memoria del processo figlio (incluso il segmento di testo). Copiare lo spazio di memoria del genitore in fork() mi è sempre sembrato uno spreco (anche se mi rendo conto che lo spreco può essere ridotto al minimo facendo i segmenti di memoria copy-on-write in modo che vengano copiati solo i puntatori). Ad ogni modo, qualcuno sa perché questo approccio di duplicazione è necessario per la creazione del processo?
Risposta accettata:
È per semplificare l'interfaccia. L'alternativa a fork
e exec
sarebbe qualcosa come la funzione CreateProcess di Windows. Nota quanti parametri CreateProcess
has, e molti di essi sono struct con ancora più parametri. Questo perché tutto potresti voler controllare il nuovo processo deve essere passato a CreateProcess
. Infatti, CreateProcess
non dispone di parametri sufficienti, quindi Microsoft ha dovuto aggiungere CreateProcessAsUser e CreateProcessWithLogonW.
Con il fork/exec
modello, non hai bisogno di tutti quei parametri. Al contrario, alcuni attributi del processo vengono mantenuti in exec
. Questo ti permette di fork
, quindi modifica gli attributi di processo che desideri (utilizzando le stesse funzioni che useresti normalmente) e poi exec
. In Linux, fork
non ha parametri e execve
ne ha solo 3:il programma da eseguire, la riga di comando da dargli e il suo ambiente. (Ci sono altri exec
funzioni, ma sono solo wrapper di execve
fornito dalla libreria C per semplificare i casi d'uso comuni.)
Se vuoi avviare un processo con una directory corrente diversa:fork
, chdir
, exec
.
Se vuoi reindirizzare stdin/stdout:fork
, chiudi/apri file, exec
.
Se vuoi cambiare utente:fork
, setuid
, exec
.
Tutte queste cose possono essere combinate secondo necessità. Se qualcuno esce con un nuovo tipo di attributo di processo, non devi cambiare fork
e exec
.
Come accennato in precedenza, la maggior parte degli Unix moderni usa il copy-on-write, quindi fork
non comporta un sovraccarico significativo.