Computer Science › Operating Systems
fork and exec
How Unix creates new processes by copying, then replacing, the current one.
Also known as: fork and exec, fork exec, process creation
Unix creates new processes with a two-step dance: fork copies the current process, and exec replaces that copy’s program with a new one. The combination is how a shell runs a command, how a server spawns workers, and how system() works underneath.
forkcreates a near-identical child: same memory contents, same open file descriptors, continuing from the same point.forkreturns twice —0in the child, the child’s PID in the parent — which is how a program tells which side it’s on.exec(e.g.execve) then loads a new program into the current process, replacing its code and data but keeping its PID and file descriptors.
pid_t pid = fork();
if (pid == 0) { // child
execvp("ls", args); // replace child with "ls"
} else { // parent
waitpid(pid, ...); // wait for the child
}
The clever part is that fork uses copy-on-write: it doesn’t literally copy all memory, just page-table entries, and only duplicates a page when one side writes to it. That makes fork cheap enough to use routinely, even for large processes.
The classic mistakes:
- Forgetting the child must
execorexit. A forked child that neither execs nor exits continues running the parent’s code — often executing the wrong logic or looping. - Not reaping children. A parent that doesn’t
waitleaves terminated children as zombies, slowly filling the process table. - Assuming file descriptors are independent. All open descriptors are inherited by the child. A child holding a socket open keeps it alive even after the parent closes it — a classic cause of “why is this connection still here?”.
- A fork bomb. A program that forks without bound (often by accident) can exhaust the process table and take down the machine. Process limits (ulimit) are the guardrail.
- Preferring
forkfor threads. Threads are usually created differently (a dedicated call);forkin a multithreaded process is subtle, because only the calling thread survives in the child.
fork + exec is the Unix way of starting programs, and it explains a lot about process behaviour: inherited descriptors, the child/parent split, and why a shell can launch a command so cheaply. It’s the concrete mechanism behind the process lifecycle.