fork and exec
Challenge Gallery
Quick Reference
The fork-replace-wait pattern:
pid_t pid = fork();
if (pid == 0) {
// CHILD: replace with a different program
execlp("ls", "ls", "-l", NULL);
perror("launch failed");
_exit(1);
} else {
// PARENT: wait for child
wait(NULL);
}
fork() return values:
| Return | You are |
|---|---|
< 0 |
Error (fork failed) |
== 0 |
The child process |
> 0 |
The parent (value = child’s PID) |
Pipe recipe for cmd1 | cmd2:
1. pipe(fd) — create the pipe
2. fork() child 1 — dup2(fd[1], STDOUT), close both, execlp(cmd1)
3. fork() child 2 — dup2(fd[0], STDIN), close both, execlp(cmd2)
4. parent — close both fd ends, wait() twice
Common signals:
| Signal | Trigger | Catchable? |
|---|---|---|
| SIGINT | Ctrl+C | Yes |
| SIGTERM | kill PID |
Yes |
| SIGKILL | kill -9 PID |
No |
| SIGSEGV | Bad memory access | Yes (rarely useful) |
Common Pitfalls
- Forgetting wait() — Child becomes a zombie. Parent must collect exit status.
- Code after execlp — Only runs if the call fails. Always follow with perror + _exit(1).
- Not closing pipe ends — Reader blocks forever if a write end stays open.
- Using exit() in child — Use
_exit(1)to avoid flushing parent’s stdio buffers. - Fork bomb — fork() in a loop without an exit condition creates exponentially many processes. Always have child exit or replace itself.