Topics
Subtopics
Code Examples
What You Will Learn
This series covers Chapter 24: Process Creation from The Linux Programming Interface (TLPI) by Michael Kerrisk. You will master fork(), vfork(), memory semantics (copy-on-write), file sharing, race conditions, and signal-based synchronization — all with hands-on C examples.
Process definition, parent-child relationships, process tree, real-world examples (server patterns)
fork(), exit(), wait(), execve() — lifecycle diagram, status macros, exec() family table
Why UNIX separates creation from execution, I/O redirection between fork and exec, posix_spawn()
Kernel steps, inherited vs unique attributes table, file locks not inherited, signal handler inheritance
The three return cases (-1/0/+PID), switch/case pattern, multiple children, safe_fork() wrapper
Stack/data/BSS/heap/text layout, t_fork.c from TLPI, heap independence, /proc memory viewing
footprint.c pattern, isolating leaky functions, returning results via exit status and pipes
3-layer file model diagram, shared vs unique properties, fork_file_sharing.c, coordinated writing
lseek() offset sharing, O_APPEND atomic writes, fcntl F_SETFL, independent re-open pattern
Pipe EOF problem, O_CLOEXEC/FD_CLOEXEC, close_all_fds_except() utility
CoW step-by-step, page table before/after diagram, fork timing benchmark, /proc RSS observation
Why text is always shared, r-xp permissions, /proc/PID/maps, shared library text pages
VSZ vs RSS explained, measuring CoW with /proc, Linux overcommit, minimize before fork
Historical context, what vfork() guarantees, signature, the only correct usage pattern
Complete comparison table, t_vfork.c from TLPI, parent suspension proof, benchmark
Safe vs dangerous actions, stdio double-flush bug, stack corruption, POSIX obsolescence
Indeterminate execution order, race condition demo, shared file race, why sleep() doesn’t fix it
Linux kernel version history, sched_child_runs_first tunable, multicore implications
SIGUSR1 pattern, sigsuspend() vs pause(), block-before-fork rule, mutual sync
fork_sig_sync.c from TLPI, pipe-based sync alternative, reusable sync helper, multiple children
| Call | Signature | Returns | Key Fact |
|---|---|---|---|
fork() |
pid_t fork(void) |
0 child, PID parent, -1 error | Copy-on-write memory |
vfork() |
pid_t vfork(void) |
Same as fork() | Shares address space; parent suspended |
wait() |
pid_t wait(int *status) |
PID of exited child | Reaps zombie; use WIFEXITED/WEXITSTATUS |
waitpid() |
pid_t waitpid(pid, status, opts) |
PID of waited child | WNOHANG for non-blocking; -1 for any child |
execve() |
int execve(path, argv, envp) |
-1 on error; never returns on success | Replaces process image; PID unchanged |
_exit() |
void _exit(int status) |
Never returns | Use in forked child; no stdio flush |
sigsuspend() |
int sigsuspend(const sigset_t*) |
Always -1 (EINTR) | Atomic unblock + sleep; use for sync |
