Learn fork() command
What is fork()?
fork() is a POSIX system call that creates a new process by duplicating the calling (parent) process. The new process is the child. After fork() both processes continue execution from the point of the call, but each has its own memory space (copy-on-write), file descriptors, and execution context.
Key properties
-
Two processes after the call: parent and child.
-
Return value distinguishes them:
-
In the parent,
fork()returns the child PID (>0). -
In the child,
fork()returns 0. -
On error,
fork()returns -1 in the parent and no child is created.
-
-
Copy-on-write: The address space is logically copied but physically shared until either process writes.
-
File descriptors are duplicated (share same open file description).
-
Child inherits environment, open files, signal dispositions (mostly).
-
Use
wait()/waitpid()in parent to reap child; otherwise child can become a zombie until reaped. -
If parent exits before child, child gets reparented to
init(orsystemd) — becomes an orphan.
Simple example — fork_demo.c
Compile and run
Typical output (annotated)
Explanation:
-
The line before
fork()shows only the original process. -
After
fork(), parent prints child PID, child prints zero return. -
Parent waits until child exits (
waitpid).
Inspecting process relationships
While program sleeps you can inspect:
Important concepts and gotchas
Zombie processes
-
If parent does not
wait()and child exits, child becomes a zombie (entry in process table with statusZ) until parent reaps it. -
Use
wait()/waitpid()in parent or setSIGCHLDhandler toSIG_IGN(with care) to avoid zombies.
Orphans
-
If parent exits while child runs, init/systemd adopts the child; child continues running.
exec after fork
-
Common pattern:
fork()then in child call anexec*()(e.g.,execvp()) to run a new program. This replaces child's image while keeping the same PID.
fork failure
-
fork()can fail (returns -1) when system resources are exhausted (e.g., RLIMIT_NPROC or kernel limits).
Race conditions
-
Because parent and child run concurrently, careful ordering with
wait()or IPC is required when they share resources.
stdout buffering gotcha
-
If parent and child both inherit standard I/O buffers (line vs block buffering), printed lines may appear duplicated. Use
_exit()in child after exec or flush buffers properly.
fork bomb (dangerous!)
-
A trivial fork misuse can create many processes quickly (e.g.,
:(){ :|:& };:in shell) — do not run on shared systems. Use process limits in labs (ulimit -u) to avoid system lockup.
Advanced notes (brief)
-
vfork()is a variant that suspends parent and intended to optimize immediate exec; use only with care. -
clone()(Linux) allows more control (used to implement threads). -
fork()duplicates file descriptor table but they share the same underlying file offset — careful with concurrent lseek().
Lab exercises
-
Modify the example: child
execvp()/bin/lsand parent prints waiting messages. -
Remove
waitpid()and observepsto find zombies; then fix by addingwaitpid. -
Create a chain of forks (two successive
fork()calls) and analyze how many processes are created (draw tree). -
Show reparenting:
fork()a child that sleeps for 10s, parent exits immediately — inspect child'sPPID.
Quick summary
-
fork()creates a new process; return value tells parent vs child. -
Parent should manage child lifecycle (use
waitpid). -
Child can replace itself with
exec*()or continue running different code. -
Watch for zombies, orphans, buffering issues and resource limits.
Comments
Post a Comment