2013-02-12 15 views
14

Sembra che ci siano due modi comuni di esecuzione di un eseguibile esterno da C in UNIX, chiamataa system() o fork()/exec()?

system() 

e

pid = fork() 
switch(pid) 
//switch statement based on return value of pid, 
//one branch of which will include and exec() command 

C'è qualche motivo per preferire un fork/exec sopra il sistema nel caso in cui sono funzionalmente equivalenti (il processo genitore attende che il bambino finisca, nessuna informazione complessa viene restituita dal bambino) ?.

risposta

18

system esegue un interprete di comandi, ovvero una shell, che (a) è più lenta di una fork/exec diretta, (b) può comportarsi in modo diverso su sistemi diversi e (c) è un potenziale rischio per la sicurezza se la si passa una stringa da una fonte non attendibile. Inoltre, system attende l'uscita del processo figlio, mentre è possibile che venga eseguito contemporaneamente al processo principale.

Più in generale, il basso livello fork/exec ti dà ulteriore controllo: prima o tra le due operazioni, si potrebbe desiderare di chdir, tubi aperti, chiudere descrittori di file, impostare la memoria condivisa, ecc

(Con sistemi diversi, non intendo Windows contro Unix (poiché Windows non ha nemmeno fork): sto parlando di Red Hat Linux contro Ubuntu. Il primo usa Bash per eseguire ciò che viene passato a system, il secondo è una shell leggera compatibile con POSIX.)

+0

Ho chiesto al mio prof quale sia la differenza e ha detto 'system()' è un'API per il sistema operativo e 'fork/exec' sono chiamate a livello di sistema. È vero? La mia comprensione è che le API per il sistema operativo sono più sicure, nel senso che possono contenere controlli aggiuntivi, al contrario delle chiamate di sistema. – Celeritas

+2

@Celeritas In un certo senso (le chiamate di sistema sono anche API del sistema operativo), ma la tua conclusione è falsa, come ho sostenuto nella risposta. 'system' non aggiunge controlli; aggiunge funzionalità non controllata. –

0

system() digiterà il comando ed eseguirà come un utente avrebbe digitato. l'ho visto principalmente come system("pause"); system("cls");

Ma se è necessario controllare il processo figlio, si desidera fork.

+5

'system (" pause ");' è una malattia! È come il modo più inefficiente per far sì che il tuo programma attenda che l'utente digiti qualcosa. –

+0

@JohnZwinck è stato abbastanza buono per il college :) di solito era lì per far sì che la console "restasse lì" quando il programma stava per uscire. – Shark

+1

La prossima volta, prova qualcosa come 'cin >> dummy;' (o scanf()). E non pensare che il lavoro abbia standard più alti della scuola! –

1

Passando tramite system() viene inoltre richiamato un processo shell, che potrebbe non essere quello desiderato.

Anche il processo di chiamata viene notificato solo quando tale shell non muore quando il processo effettivo eseguito dalla shell è morto.

3

fork() crea un nuovo processo. Se non è necessario, utilizzare system() (o popen()). Potresti volere un secondo processo per raggiungere il parallelismo, o per un controllo più fine sul lavoro, ma spesso non ti interessa per questo se il lavoro deve essere sincrono.

D'altra parte, trovo che il 95% degli usi di system() non è necessario o che in qualche modo sarebbe meglio farlo in un altro modo (ad esempio utilizzando zlib anziché system("gzip")). Quindi forse la migliore risposta è non usare nessuno dei due!

+0

in questo caso è uno strumento personalizzato creato da qualcun altro, quindi devo ridirigere il loro codice in una libreria, chiamarlo tramite sys o exec, o copiare su un blocco della sorgente nei miei binari. È una scelta complicata tra la velocità di manutenibilità dell'implementazione. – Sparky

+1

Solo per completezza, c'è una scelta in più: utilizzare un linguaggio di livello superiore come Python per richiamare questo strumento di terze parti e anche servire come "main()" per il proprio codice. Cioè, esponi la tua logica come una libreria o un eseguibile, e usa uno script di qualche tipo per collegare i pezzi insieme, piuttosto che sborsare da C. Cibo per il pensiero. –

+2

Sia system() che popen() creano effettivamente due nuovi processi, uno per la shell e l'altro per il comando da eseguire all'interno della shell. – pelya