16

There appear to be two common ways of running an external executable from C in unix, the

system()

call and

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

Is there any reason to prefer a fork/exec over system in the case where they are functionally equivalent (parent process waits for child to finish, no complex information is returned from child)?.

billz
  • 44,644
  • 9
  • 83
  • 100
Sparky
  • 2,694
  • 3
  • 21
  • 31

4 Answers4

20

system executes a command-interpreter, i.e. a shell, which (a) is slower than a direct fork/exec, (b) may behave differently on different systems and (c) is a potential security hazard if you pass it a string from an untrusted source. Also, system waits for the child process to exit, while you might want it to run concurrently with the parent process.

More in general, the low-level fork/exec gives you additional control: before or in between the two operations, you might want to chdir, open pipes, close file descriptors, set up shared memory, etc.

(By different systems, I don't mean Windows vs. Unix (as Windows doesn't even have fork): I'm talking Red Hat Linux vs. Ubuntu. The former uses Bash to execute what is passed to system, the latter a lightweight POSIX-compatible shell.)

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • I asked my prof what the difference is and he said `system()` is an API to the OS and `fork/exec` are system level calls. Is this true? My understanding is that APIs to the OS are more secure in the sense they may contain additional checking, as opposed to system calls. – Celeritas Sep 16 '14 at 23:11
  • 3
    @Celeritas In a sense (system calls are OS APIs as well), but your conclusion is false, as I've argued in the answer. `system` does not add checks; it adds unchecked functionality. – Fred Foo Sep 20 '14 at 10:41
4

fork() creates a new process. If you don't need to do that, just use system() (or popen()). You might want a second process to achieve parallelism, or for finer-grained control over the job, but often you just don't care for that if the job is meant to be synchronous.

On the other hand, I find that 95% of uses of system() are unnecessary or would somehow be better off done another way (e.g. using zlib instead of system("gzip")). So maybe the best answer is to use neither!

Michael Wild
  • 24,977
  • 3
  • 43
  • 43
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • in this case it's a custom tool built by someone else, so I've either got to refactor their code into a library, call it via sys or exec, or copy over a chunk of the source into my own binaries. It's a tricky choice between speed of implementation maintainability. – Sparky Feb 12 '13 at 11:55
  • 1
    Just for completeness, there is one more choice: use a higher-level language like Python to invoke this third-party tool and also serve as the "main()" for your own code. That is, expose your own logic as a library or executable, and use a script of some sort to connect the pieces together, rather than shelling out from C. Food for thought. – John Zwinck Feb 12 '13 at 12:02
  • 2
    Both system() and popen() actually create two new processes - one for the shell, and another for the command to be executed inside the shell. – pelya Mar 31 '15 at 18:31
  • 1
    @pelya: not necessarily: if the shell commands are built-in ones (of which e.g. Bash has many, like `time`), only a single new process is required. – John Zwinck May 04 '15 at 00:46
1

Going via system() additionally invokes a shell process, which might not be what you want.

Also the calling process is notified only when such shell dies not when the actual process run by the shell died.

alk
  • 69,737
  • 10
  • 105
  • 255
-1

system() will type out the command and execute it like a user would have typed out. i mostly saw it like system("pause"); system("cls");

But if you need to control the child process, you want to fork.

Shark
  • 6,513
  • 3
  • 28
  • 50
  • 7
    `system("pause");` is a disease! It's like the most inefficient way to make your program wait for the user to type something. – John Zwinck Feb 12 '13 at 10:48
  • @JohnZwinck it was good enough for college :) was usually there to make the console 'stay there' when the program is about to exit. – Shark Feb 12 '13 at 10:52
  • 1
    Next time, try something like `cin >> dummy;` (or scanf()). And don't think that work has higher standards than school! – John Zwinck Feb 12 '13 at 10:54
  • `system("pause")` is never needed on Unix systems, so this is irrelevant to the question. – Fred Foo Feb 12 '13 at 11:00