fork()
Copy a process: the child gets 0, the parent gets a pid. Copy-on-write makes the copy cheap until a write.
Level: intermediate
What is it?
On POSIX systems, fork() creates a child process from the calling process. The child starts with a logical copy of the parent's address space and inherited process attributes, while the return value distinguishes the child from the parent.
Why does it matter?
fork plus exec is a classic way to launch programs while preserving the parent process. Copy-on-write keeps initial memory duplication relatively cheap, but the child must still handle inherited descriptors and multithreaded-process rules correctly.
Mental model
After fork, parent and child continue from the same point but have separate process identities and logically separate memory. They may run in either order, so communication should use explicit IPC rather than assuming execution order.
How it works
- In the parent, fork returns the child PID; in the child it returns zero; failure returns -1 in the parent and creates no child.
- Copy-on-write initially shares physical pages where safe and copies pages when a process writes.
- Open file descriptors are inherited and refer to the same underlying open file descriptions, affecting offsets and flags.
- After fork in a multithreaded process, only the calling thread exists in the child; only async-signal-safe operations are safe until exec under POSIX rules.
- Zombie children remain until their exit status is collected, typically via wait/waitpid or an equivalent mechanism.
Steps
- The parent calls fork and checks its return value.
- The kernel creates the child task/process and sets up resource and memory semantics.
- Parent and child continue independently; either may run first.
- The child often calls exec to replace its program image, while the parent supervises or waits for its completion.
Real-world usage
- Launching subprocesses in shells and service supervisors.
- Understanding process trees, inherited file descriptors, and zombie cleanup.
Common mistakes
- Assuming parent always executes before child.
- Assuming fork eagerly copies all physical memory pages.
- Calling unsafe library operations in a forked child of a multithreaded process before exec.
Interview questions
What does fork return in parent and child?
The parent receives the child's PID, the child receives 0, and the parent receives -1 on failure.
Why must a multithreaded child be careful before exec?
Only the calling thread survives in the child while locks may have been held by vanished threads; POSIX restricts pre-exec operations to async-signal-safe functions.