Linux System Programming · intermediate · ~12 min
Create a child process and dispatch on the return value.
fork() creates a copy of the current process. The original is the parent; the copy is the child. After fork, both processes continue from the same line — but fork returns 0 in the child and the child's PID in the parent. This is how Unix creates new processes.
Every command you run in a shell starts with fork. So does every web server that handles requests in subprocesses, every make job running in parallel, every Docker container's first process. Without fork (or its successor clone), Unix would be a single-user operating system.
Copy-on-write. The child inherits an exact copy of the parent's memory, but the kernel doesn't physically copy pages until one side writes — making fork cheap. Return-value branching. pid_t pid = fork(); if (pid == 0) { /* child */ } else { /* parent */ }. Resource inheritance. File descriptors are shared (until one side closes or exec's).
#include <sys/types.h>
#include <unistd.h>
pid_t pid = fork();
if (pid < 0) { perror("fork"); return 1; }
if (pid == 0) {
/* child: usually exec or do work, then _exit */
} else {
/* parent: usually waitpid(pid, ...) */
}
pid_t fork(void) duplicates the current process. After it returns:
Both processes continue from the same point. They have independent memory; modifications in one are not visible to the other.
pid_t pid = fork();
if (pid < 0) { perror("fork"); return 1; }
if (pid == 0) {
/* child */
printf("child\n"); _exit(0);
}
/* parent */
int st; waitpid(pid, &st, 0);
exit (not _exit) in the child runs atexit handlers twice.wait for the child — it becomes a zombie.gdb debugging across fork requires set follow-fork-mode child (or 'parent'). pstree -p <pid> shows the process tree. strace -f follows forked children. When a fork test seems to print twice for one parent line — that's correct! Both processes are running the line.
After fork, both processes have valid copies of every pointer — including pointers to in-memory caches that may now be invalid in one side. Be careful with stdio buffers; flush them before fork to avoid duplicated output.
Every shell, every cron, every webserver's worker pool, the early-90s inetd super-server, Python's multiprocessing module under the hood, Postgres's per-connection backend.
getppid(). 3. Combine fork with waitpid so the parent waits for the child.fork duplicates the current process. Branch on the return value: 0 means you're the child, non-zero means you're the parent with the child's PID. Combine with exec to run new programs, with wait to clean up — those three syscalls power every Unix.