The fork() system call is used to create a new process On success, the PID of the child process is returned in the parent, and 0 is returned in the child..
int main(int argc, char *argv[]){ printf("hello world (pid:%d)\n", (int) getpid()); int rc = fork(); if (rc < 0) { // fork failed; exit fprintf(stderr, "fork failed\n"); exit(1); } elseif (rc == 0) { // child (new process) printf("hello, I am child (pid:%d)\n", (int) getpid()); sleep(1); } 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()); } return0; }
wait(), waitpid() can be used to wait. In this example, the parent process calls wait() to delay its execution until the child finishes executing. When the child is done, wait() returns to the parent. This makes the code deterministic.
The exec() System Call
This system call is useful when you want to run a program that is different from the calling program.
int main(int argc, char *argv[]){ printf("hello world (pid:%d)\n", (int) getpid()); int rc = fork(); if (rc < 0) { // fork failed; exit fprintf(stderr, "fork failed\n"); exit(1); } elseif (rc == 0) { // child (new process) printf("hello, I am child (pid:%d)\n", (int) getpid()); char *myargs[3]; myargs[0] = strdup("wc"); // program: "wc" (word count) myargs[1] = strdup("p3.c"); // argument: file to count myargs[2] = NULL; // marks end of array execvp(myargs[0], myargs); // runs word count printf("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()); } return0; }
exec() does not create a new process; rather, it transforms the currently running program into a different running program.
Why?
This is such an odd interface to what should be the simple act of creating a new process. However, the separation of fork() and exec() is essential in building a UNIX shell, because it lets the shell run code after the call to fork() but before the call to exec().
Eg. Manage file descriptor so new execution’s output is stored somewhere else.