Processes & Process Control

fork() and the parent/child relationship

How does one process create another? On Unix-like systems the basic answer is surprisingly strange: a process clones itself. The fork() system call takes the running process and makes a near-identical copy of it - same code, same variable values, same open files, same place in the program. You now have two processes: the original (the parent) and the new copy (the child). It is less like building a new program and more like a cell dividing: one becomes two, and both keep running from the very next line after the fork().

The famous twist is that fork() returns twice - once in each process - and that single return value is how each copy learns who it is. In the parent, fork() returns the child's PID (a positive number). In the child, fork() returns 0. (On failure, it returns -1 in the parent and no child is made.) So the same line of code runs in both, but takes different branches: 'if the return value is 0, I am the child; otherwise I am the parent and this number is my child's PID.' After the fork the two processes are independent - they have separate address spaces, so a variable the child changes does not change in the parent, and vice versa. To avoid copying potentially gigabytes of memory instantly, modern kernels use copy-on-write: parent and child initially share the same physical pages marked read-only, and a page is duplicated only when one of them actually writes to it. The split is logical immediately, physical only on demand.

Why it matters: fork() is the root of how every process tree grows - every process except init descends from a fork. It pairs with exec() (next term) to launch new programs, and with wait() to clean up children. The double return is the single most surprising thing for newcomers, and getting it wrong - assuming code after fork() runs once - is a classic bug. Also note: fork() copies the whole address space, but with threads it has sharp pitfalls (only the calling thread survives in the child), which is one reason fork-then-exec is the safe everyday pattern.

pid_t pid = fork(); if (pid == 0) { /* child runs here */ } else if (pid > 0) { /* parent runs here, pid is the child's PID */ } else { /* fork failed, errno is set */ }. Both branches' code physically exists once, but at run time the child takes the first branch and the parent takes the second.

fork() returns twice: 0 in the child, the child's PID in the parent - that is how each knows itself.

Copy-on-write does not mean parent and child share variables. They share physical pages only until a write, then get private copies; logically their memory was independent from the instant of the fork.

Also called
forking a processprocess duplication衍生行程