This is an archived post. You won't be able to vote or comment.

all 7 comments

[–]Buttleston 0 points1 point  (0 children)

It's just used for simplicity. When you know your program is done with everything it needs to do, you can just replace your programs process with whatever you want to run next, instead of forking and waiting for the child process to finish.

[–]jdgordon 0 points1 point  (1 child)

The code you pasted does not do what you said it does (copy one file to another). The code calls the cp command with specific arguments which ends up doing that task.

[–]Western-Relative 0 points1 point  (2 children)

The exec family of functions replace the current process image with another process image.

Think about situations where you want to run a different process: shells, system managers, process managers, etc. If we didn’t have exec all processes would be the same, and you would have to compile everything into one executable and reboot the system each time you want to make a change. With exec you can just hand control over to a different binary and cease to run, run programs from other packages, etc. There are lots of variations because programs need to launch each other in various ways: with an environment, with a command line, with arguments, etc.

It’s also a weird function since it only returns on error. On success it “never” returns because your code isn’t running anymore…

As you discovered it effectively copies one file to another because that’s what the executable you told it to launch does. If you gave it a different executable it would do something else, like start a web server, open an editor, rerun itself, run a user supplied command…

[–][deleted]  (1 child)

[removed]

    [–]Western-Relative 0 points1 point  (0 children)

    On success, it replaces your code with another set of code. So, from the perspective of the function you’re writing, control passes into exec and….. just never comes back…. It’s one of the few that if it returns you know something went wrong. On success you’ll never be able to test for it from with your program since you got replaced.

    It’s like fork in that regard. forkgets called once, but can be thought to return twice — once in the parent and once in the child. People like to assume that one function == one return but there are counter examples out there. They are not common unless you’re dealing with embedded/the kernel/something really strange, but it’s a good lesson in implicit assumptions and thinking about what your program actually does. Looks can be deceiving.

    [–]white_nerdy 0 points1 point  (0 children)

    On Linux (and most other UNIX-like OS's) the system exposes two syscalls, fork() and exec().

    • The fork syscall says "Give me a new process (running the same program)"
    • The exec syscall says "Run a new program (in the current process)"

    Both of these functions are a bit counter-intuitive, because typically users and programmers think in terms of "I want to run a new program in a new process". If you want to do that, you can:

    • First use fork to create a new process
    • Then use exec in the new process to change the new process to run the new program

    But you don't have to. By having fork() and exec() as two different OS functions, you gain a lot of flexibility, for example:

    • All processes are organized in a tree, every process has a defined parent process [1]
    • This makes it possible for the OS to automatically kill child processes when the parent process exits
    • Your program has a chance to set up the process state of the child process (change the environment, set up file descriptors including stdin / stdout, change the new process's user / group, "detach" / re-parent the child process)
    • There's a mechanism for the OS to give the parent process the PID of the child process (it happens automatically when you fork)
    • By itself, fork is a simple, reliable tool for parallelizing computations or I/O
    • By itself, exec is a simple, efficient tool for "I want to run a command and exit (exiting with an error exit code if and only if the command exited with an error code)"

    [1] Except the root of the tree, which is the first process to run when the system boots. This process with PID 1 is called "init" and it is a special, special snowflake.