Frequently Asked Question
How do fork and exec actually create a new program?
Unix splits process creation into two distinct system calls, and the split is the
reason pipes, redirection, and job control all work so cleanly. fork() duplicates
the calling process: the kernel makes a near-identical copy with a new PID, the same
open files, the same memory contents (copy-on-write, so nothing is actually copied
until one side writes), and returns. The parent gets the child's PID back; the child
gets 0. After the fork there are two processes running the same code from the same
point.
execve() then replaces the calling process's memory image with a new program loaded
from disk. The PID is unchanged, but the code, data, heap, and stack are all swapped
out. Crucially, the child can run arbitrary code between the fork and the exec;
closing files, redirecting standard input, changing directory, dropping privileges,
setting up pipes, and the new program inherits whatever environment the child
arranged. When you type ls | wc -l, bash forks twice, wires the two children
together with a pipe, and only then execs ls and wc in them.