2011-10-15 10 views
12

Non capisco perché Unix abbia fork() per creare un nuovo processo. Nell'API Win32 abbiamo CreateProcess() che crea un nuovo processo e carica un eseguibile nel suo spazio indirizzo, quindi inizia l'esecuzione dal punto di ingresso. Tuttavia Unix offre fork per la creazione di un nuovo processo, e non capisco perché dovrei duplicare il mio processo se mi piacerebbe eseguire un altro processo.Perché Unix ha fork() ma non CreateProcess()?

Quindi permettetemi di chiedere a queste due domande:

  1. Se fork() e poi exec() è più efficiente, perché non c'è una funzione forkexec(const char *newProc) da quando chiameremo exec() dopo fork() quasi in tutti i casi?
  2. Se non è più efficiente, perché esiste lo fork()?
  3. sistemi operativi

risposta

11

La chiamata fork() è sufficiente. E ' è anche più flessibile, consente di regolare il reindirizzamento I/O nel processo figlio, piuttosto che complicare la chiamata di sistema per creare il processo. Con i programmi SUID o SGID, consente il bambino perde i suoi privilegi elevati prima di eseguire l'altro processo.

Se si desidera un modo complesso per creare un processo, cercare la funzione posix_spawn().

#include <spawn.h> 

int posix_spawn(pid_t *restrict pid, const char *restrict path, 
     const posix_spawn_file_actions_t *file_actions, 
     const posix_spawnattr_t *restrict attrp, 
     char *const argv[restrict], char *const envp[restrict]); 

int posix_spawnp(pid_t *restrict pid, const char *restrict file, 
      const posix_spawn_file_actions_t *file_actions, 
     const posix_spawnattr_t *restrict attrp, 
     char *const argv[restrict], char *const envp[restrict]); 

La differenza è la posix_spawnp() fa una ricerca sul percorso per l'eseguibile.

Esiste un'intera serie di altre funzioni per la gestione dei tipi posix_spawn_file_actions_t e posix_spawnattr_t (seguire i collegamenti "Vedere anche" nella parte inferiore della pagina man referenziata).

Questo è un po 'più simile a CreateProcess() su Windows. Per la maggior parte, però, usare fork() seguito a breve da exec() è più semplice.


Non capisco cosa vuoi dire. Il codice di processo figlio verrà scritto da me, quindi qual è la differenza tra scrivere if (fork() == 0) e inserire questo codice all'inizio di main() per figlio?

Molto spesso, il codice che si esegue non viene scritto da voi, quindi non è possibile modificare ciò che accade all'inizio del processo del bambino. Pensa a una conchiglia; se gli unici programmi che esegui dalla shell sono quelli che hai scritto, la vita sarà molto impoverita.

Molto spesso, il codice che si esegue verrà chiamato da molti posti diversi. In particolare, pensate a una shell ea un programma che a volte verrà eseguito in una pipeline e talvolta eseguito senza pipe. Il programma chiamato non può dire quali reindirizzamenti I/O e correzioni dovrebbero fare; il programma chiamante lo sa.

Se il programma chiamante è in esecuzione con privilegi elevati (privilegi SUID o SGID), è normale voler disattivarli prima di eseguire un altro programma. Affidarsi all'altro programma per sapere cosa fare è ... sciocco.

+0

Non ho capito cosa intendi. codice di processo figlio verrà scritto da me quindi qual è la differenza tra scrivere se (fork() == 0) e inserire questo codice all'inizio di child's main()? –

+0

hmm, quindi dici che è semplicemente più facile con fork() - exec() fare coppia per fare cose del genere (reindirizzamento/i/o reindirizzamento, ecc.) Ho capito? –

+1

Sì: confrontato con le contorsioni richieste per 'posix_spawn()', è molto più semplice usare 'fork()' e poi fare in modo che il bambino esegua le azioni di cui ha bisogno, prima di usare 'exec()'. Leggi la spiegazione per 'posix_spawn()'; è abbastanza illuminante (o, almeno, lo era per me). L'elenco di cose che puoi fare con 'posix_spawn()' è impressionante, ma è anche più complesso di quello che fornisce 'fork()'. –

3

UNIX-like (almeno più recenti di Linux e BSD kernel) hanno generalmente un molto efficientefork implementazione - è "così a buon mercato" che ci sono "filettato" implementazioni basate su di essa in alcune lingue .

Alla fine la funzione forkexec è ~ n - per un piccolo valore di n - linee di codice dell'applicazione.

io certo desiderare finestre avevano un tale utile ForkProcess :(

Felice di codifica.


A cnicutar accennato, Copy-On-Write (COW) è una strategia utilizzata.

+2

ok ma se io trasformare il processo in un altro dopo forcella molto efficiente, non è meglio per creare la nuova processo dall'inizio? quindi non devo duplicare il mio processo. questo è quello che non ottengo –

+0

@Ali I forchette Veli Modern non duplicano affatto il processo. Cerca "copia su scrittura". – cnicutar

+0

diciamo che creerò un nuovo processo. c-o-w o no, la forcella fa qualcosa di giusto? quindi penso che se creo un nuovo processo, non farei questo qualcosa (anche se è solo 1 istruzione). –

Problemi correlati