CSE 2431
Unix/Linux fork()
1. To create a process, Unix/Linux use fork(), which is a system call.
2. When fork() is executed by a process:
a. The process executing fork(), called the parent, makes a system call to
the OS which causes a new process (a child of the parent) to be created
(assuming no error occurs, and they occur very rarely).
b. The fork() system call returns (in the return register, as always):
If an error occurs, -1 is returned to the parent, and no child process is created;
else
i. The pid of the child is returned to the parent;
ii. 0 is returned to the child.
c. Notice that the different return values for the parent and child can be
used to have the parent and child execute different code after return
from the fork system call.
d. When the OS creates the child, the child is assigned its own pid by the
OS, and its pid will be greater than the pid of its parent (often 1 greater,
but it depends on whether or not any other fork system calls were
made (by other processes running in the system) between the time the
parent was created and the time the fork call is made in the parent).
e. The child gets its own separate address space (its own space in
memory), which initially contains a copy of the parent’s address space
(both code and data).
f. Linux implements fork() using copy-on-write pages [discussed later], so
process creation is quite efficient.
g. As part of creating the child process, the OS will also create a process
control block (PCB) for the child, which will be used by the OS to keep
track of data needed to manage the process, such as the pid of the
process, current process execution state (register values), process state
(ready, running, blocked), open files, etc.
h. Notice carefully that the child ALSO gets a copy of the parent’s register
values (PC, PSR, in Intel, rax, rbx, etc.), except the parent’s rax will be
overwritten by the fork return value to the child (0).
i. In some cases, the child process may subsequently overwrite its
address space with a different program to execute. This can be done
using exec() system calls, such as execvp() [discussed later].
j. Notice carefully: When the parent process resumes execution, the PC
had already been incremented to the address of the next instruction
after the fork() instruction when the fork instruction executed, so the
fork() call is only made once by the parent (that is, the parent will start
executing instructions starting with the next instruction after the fork
when the parent runs again). Also notice carefully that the child gets a
copy of all the code and data for the parent, and also all of the parent’s
registers (context), so the child also gets the incremented PC (which
has the address of the next instruction after the fork() call); therefore,
the child will not execute the fork call, but rather, will start executing
instructions starting with the first instruction after the fork instruction.