Linux System Programming · advanced · ~12 min
Run a different program inside the current process.
The exec* family of functions replaces the program running inside the current process with a different program.
Here is what stays and what changes:
On success, exec does not return. Control passes straight to the main function of the new program.
fork alone only gives you two copies of the same program.
exec is the second half of the story. After forking, the child calls something like exec("/bin/ls") to become the new program.
This pair, fork then exec, is how every shell launches every command.
Variants. The family includes execl, execv, execle, execve, execlp, and execvp. They differ in three ways:
$PATH is searched to find the programNo return on success. If exec returns at all, the call failed. The usual cause is that the executable could not be found.
Inherits file descriptors. The new program inherits any file descriptors the old program had open, except those marked close-on-exec.
execl("/bin/ls", "ls", "-la", (char *)NULL);
/* If we reach this line, exec failed. */
perror("execl");
_exit(127);
The exec* family replaces the current process image with a new program.
main.errno.Fork, then call exec in the child. The parent then waits for the child to finish.
execvp(file, argv) searches $PATH for file. The arguments are passed as an array.execve(path, argv, envp) is the most explicit form. It takes an absolute path and an explicit environment.pid_t pid = fork();
if (pid == 0) {
char *argv[] = { "ls", "-la", NULL };
execvp("ls", argv);
_exit(127); // only reached if execvp fails
}
int st; waitpid(pid, &st, 0);
exec only returns on failure. Always write the error-handling path right after the call.strace -e trace=execve ./prog shows every exec attempt, along with its arguments.
No such file or directory means the first argument (the path) is wrong. Double-check it.Permission denied means the file is not executable. Run chmod +x on it.After exec succeeds, your current heap and stack vanish.
Any malloc'd buffers that were still in use are leaked by definition.
This is usually fine, because the new program does not need them. Note that AddressSanitizer (ASan) and Valgrind will not flag this path.
system() call.getty exec's login, which then exec's bash.fork, have the child exec /bin/ls -l / while the parent waits.execvp to make the program look up the command via $PATH.execve.exec swaps the program running inside a process, keeping the same PID.fork: fork makes a copy, exec turns that copy into a different program.exec never returns; if it returns, it failed.exec, fork would only make duplicates. Together they implement the Unix process model.