System Call : int fork() fork() causes a process to duplicate. The child process is an almost-exact duplicate of the original parent process; it inherits a copy of its parent's code, data, stack, open file descriptors, and signal table. However, the parent and child have different process id numbers and parent process id numbers. If fork() succeeds, it returns the PID of the child to the parent process, and returns 0 to the child process. If it fails, it returns -1 to the parent process and no child is created. fork() is a strange system call, because one process(the original) calls it, but two processes(the original and its child) return from it. Both processes continue to run the same code concurrently, but have completely separate stack and data spaces. A process may obtain its own process id and parent process id numbers by using the getpik() and getppid() system calls, respectively. Here's a synopsis of these system calls: System Call: int getpid() int getppid() getpid() and getppid() return a process's id and parent process's id numbers, respectively. They always succeed. The parent process id number of PID 1 is 1. To illustrate the operation of fork(), here's a small program that duplicates and then branches based on the return value of fork(): $ cat fork.c #include main() { int pid; printf("I'm the original process with PID %d and PPID %d.\n", getpid(),getppid()); pid=fork(); /* Duplicate. Child and parent continue from here.*/ if (pid!=0) /* pid is non-zero, so I must be the parent */ { printf("I'm the parent process with PID %d and PPID %d.\n", getpid(),getppid()); printf("My child's PID is %d.\n", pid); } else /* pid is zero, so I must be the child. */ { printf("I'm the child process with PID %d and PPID %d.\n", getpid(),getppid()); } printf("PID %d terminates.\n",pid); /* Both processes execute this */ } $fork.exe ... run the program. I'm the original process with PID 13292 and PPID 13273. I'm the parent process with PID 13292 and PPID 13273. My child's PID is 13293. I'm the child process with PID 13293 and PPID 13292. PID 13293 terminates. ... child terminates. PID 13292 terminates. ... parent terminates. WARNING: As you will soon see, it is dangerous for a parent to terminate without waiting for the death of its child. The only reason that the parent doesn't wait for its child in this example is because I haven't yet described the wait() system call! Orphan Processes If a parent dies before its child, the child is automatically adopted by the original "init" proces, PID 1. To illustrate this, I modified the previous program by inserting a sleep statement into the child's code. This ensured that the parent process terminated before the child. Here's the program and the resultant output: $cat orpan.c ... list the program #include main() { int pid; printf("I'm the original process with PID %d and PPID %d.\n", getpid(),getppid()); pid=fork(); /* Duplicate. Child and parent continue from here.*/ if (pid!=0) /* Branch based on return value from fork() */ { /* pid is non-zero, so I must be the parent */ printf("I'm the parent process with PID %d and PPID %d.\n", getpid(),getppid()); printf("My child's PID is %d.\n", pid); } else { /* pid is zero, so I must be the child. */ sleep(5); /*Make sure that the parent terminates first. */ printf("I'm the child process with PID %d and PPID %d.\n", getpid(),getppid()); } printf("PID %d terminates.\n",pid); /* Both processes execute this */ } $orphan.exe ... run the program. I'm the original process with PID 13364 and PPID 13346. I'm the parent process with PID 13364 and PPID 13346. PID 13364 terminates. I'm the child process with PID 13365 and PPID 1. ...orphaned! PID 13365 terminates. ... child terminates. $ - System Call: int exit(int status) exit() closes all of a process's file descriptors, deallocates its code, data, and stack, and then terminates the process. When a child process terminates, it sends its parent a SIGCHLD signal and waits for its termination code status to be accepted. A process that is waiting for its parent to accept its return code is called a zombie process. A parent accepts a child's termination code by executing wait(), which is described shortly. The kernel ensures that all of a terminating process's children are orphaned and adopted by "init" by setting their PPID to 1. The "init" process always accepts its children's termination codes. exit() never returns. The termination code of a child process may be used for a variety of purposes by the parent process. Shells may access the termination code of their last child process via one of their special variables. For example, the C shell stores the ternimation code of the last command in the variable $status: %cat exit.c ...list the program #include main() { printf("I'm going to exit with return code 42\n"); exit(42); } % exit.exe ... run the program I'm going to exit with return code 42 % echo $status ... display the termination code. 42 % - Zombie Processes $ cat zombie.c ... list the program. #include main() { int pid; pid=fork(); /* Duplicate */ if (pid!=0) /* Branch based on return value from fork() */ { while (1) /* never terminate, and never execute a wait() */ sleep(1000); } else { exit(42); /* Exit with a silly number */ } } $ zombie.exe & ... execute the program in the background. [1] 13545 $ ps PID TT STAT TIME COMMAND 13535 p2 s 0:00 -ksh(ksh) ...the shell 13545 p2 s 0:00 aombie.exe...the parent process 13536 p2 z 0:00 ...the zombie child process 13537 p2 R 0:00 ps $ kill 13545 ... kill the parent process. [1] Terminated zombie.exe $ ps ... notice the zombie is gone now. PID TT STAT TIME COMMAND 13535 p2 s 0:00 -csh(csh) 13548 p2 R 0:00 ps Waiting For A Child: wait() A parent process may wait for one of its children to terminate and then accept its child's termination code by executing wait(): System Call: int wait(int* status) wait() causes a process to suspend until one of its children terminates. A successful call to wait() returns the pid of the child that terminated and places a status code into status that is encoded as follows: . If the rightmost byte of status is zero, the leftmost byte conains the low eight bits of the value returned by chils's exit()/return(). . If the rightmost byte is non-zero, the rightmost seven bits are equal to the number of the signal that caused the child to terminate, and the remaining bit of the rightmost byte is set to 1 if the child produced a core dump. If a process executes a wait() and has no children, wait() returns immediately with -1. If a process executes a wait() and one or more of its children are already zombies, wait() returns immediately with the status of one of the zombies. $ cat wait.c #include main() { int pid, status, childPid; printf("I'm the parent process and my PID is %d\n", getpid()); pid=fork(); /* Duplicate.*/ if (pid!=0) /* Branch based on return value from fork() */ { printf("I'm the parent process with PID %d and PPID %d.\n", getpid(),getppid()); childPid=wait(&status); /* wait for a child to terminate */ printf("A child with PID %d terminated with exit code %d\n", childPid, status>>8); } else { printf("I'm the child process with PID %d and PPID %d.\n", getpid(),getppid()); exit(42); /* Exit with a silly number. */ } printf("PID %d terminates.\n",pid); } $wait.exe ... run the program. I'm the parent process and my PID is 13464 I'm the child process with PID 13465 and PPID 13464. I'm the parent process with PID 13464 and PPID 13409 A child with PID 13465 terminated with exit code 42 PID 13465 terminates $ -