Finally, The exec() System Call
This lesson demonstrates and describes an example of the `exec()` system call.
We'll cover the following
A final and important piece of the process creation API is the exec()
system call.
Running p3.c
This system call is useful when you want to run a program that is different from the calling program. For example, calling fork()
in p2.c
is only useful if you want to keep running copies of the same
in the program. However, often you want to run a different program; exec()
does just that (see the code below).
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/wait.h>int main(int argc, char *argv[]){printf("hello world (pid:%d)\n", (int) getpid());fflush(stdout);int rc = fork();if (rc < 0) {// fork failed; exitfprintf(stderr, "fork failed\n");exit(1);} else if (rc == 0) {// child (new process)printf("hello, I am child (pid:%d)\n", (int) getpid());fflush(stdout);char *myargs[3];myargs[0] = strdup("wc"); // program: "wc" (word count)myargs[1] = strdup("p3.c"); // argument: file to countmyargs[2] = NULL; // marks end of arrayexecvp(myargs[0], myargs); // runs word countprintf("this shouldn't print out");} else {// parent goes down this path (original process)int wc = wait(NULL);printf("hello, I am parent of %d (wc:%d) (pid:%d)\n",rc, wc, (int) getpid());}return 0;}
In this example, the child process calls execvp()
in order to run the program wc
, which is the word counting program. In fact, it runs wc
on the source file p3.c
, thus telling us how many lines, words, and bytes are found in the file:
prompt> ./p3hello world (pid:29383)hello, I am child (pid:29384)29 107 1030 p3.chello, I am parent of 29384 (rc_wait:29384) (pid:29383)prompt>
The fork()
system call is strange; its partner in crime, exec()
, is not so normal either. What it does: given the name of an executable (e.g., wc
), and some arguments (e.g., p3.c
), it loads code (and static data) from that executable and overwrites its current code segment (and current static data) with it; the heap and stack and other parts of the memory space of the program are re-initialized. Then the OS simply runs that program, passing in any arguments as the argv
of that process. Thus, it does not create a new process; rather, it transforms the currently running program (formerly p3
) into a different running program (wc
). After the exec()
in the child, it is almost as if p3.c
never ran; a successful call to exec()
never returns.
TIP: GETTING IT RIGHT (LAMPSON’S LAW)
As Lampson states in his well-regarded
, “Get it right. Neither abstraction nor simplicity is a substitute for getting it right.” Sometimes, you just have to do the right thing, and when you do, it is way better than the alternatives. There are lots of ways to design APIs for process creation; however, the combination of “Hints for Computer Systems Design” “Hints for Computer Systems Design” by Butler Lampson. ACM Operating Systems Review, Volume 15:5, October 1983. Lampson’s famous hints on how to design computer systems. You should read it at some point in your life, and probably at many points in your life. fork()
andexec()
are simple and immensely powerful. Here, the UNIX designers simply got it right. And because Lampson so often “got it right”, we name the law in his honor.
Get hands-on with 1400+ tech skills courses.