A program calls fork(). After fork() returns, how many processes are executing the instruction immediately after the fork() call?
AOne — the parent continues and the child starts from the beginning of main()
BOne — the child takes over execution and the parent is suspended
CTwo — both parent and child resume at the same point with different return values
DTwo — the parent continues normally; the child automatically starts a new program
After fork(), both the parent and child resume execution at exactly the same point — immediately after the fork() call — because the child is a copy of the parent's entire state, including the program counter. The parent receives the child's PID as the return value; the child receives 0. This is why fork() is said to 'return twice': there are now two processes running the same code, each branching based on which return value they received.
Question 2 Multiple Choice
A child process calls execvp() to run a new program. The call succeeds. What happens to the child process's original code, stack, and heap?
AThey are preserved and available when the new program finishes
BThey are saved to disk and restored if exec() is called again
CThey are completely replaced by the new program's image; exec() does not return
DThey are shared with the parent process via copy-on-write until the child exits
exec() replaces the entire process image — code, data, heap, stack — with the new program loaded from the executable file. The process ID stays the same, but everything else is replaced. exec() does not return on success because there is nothing to return to: the old program no longer exists in that process. It only returns if loading the new program fails (e.g., file not found, permission denied). A common bug is writing code after exec() assuming it will run on success.
Question 3 True / False
After fork() is called, the child process starts execution from the beginning of the main() function.
TTrue
FFalse
Answer: False
The child does NOT start from main(). It resumes at the instruction immediately after the fork() call, because the child is a copy of the parent's state including the program counter. The return value (0 for the child, the child's PID for the parent) is the only difference between the two processes. This surprises many students who expect process creation to behave like starting a fresh program.
Question 4 True / False
The fork-then-exec pattern gives the child process an opportunity to configure its environment — such as redirecting file descriptors — before the new program starts.
TTrue
FFalse
Answer: True
The window between fork() and exec() is intentional and powerful. Because the child runs the same code as the parent but can execute any operations before exec(), it can redirect stdin/stdout, change the working directory, set signal handlers, or drop privileges — all before the new program takes over. This is exactly how shell I/O redirection works: the child sets up file descriptor redirections (e.g., for > output.txt), then execs the command.
Question 5 Short Answer
Explain why it is said that fork() 'returns twice.' What does each return value mean, and how does a program use them to take different actions in the parent vs. the child?
Think about your answer, then reveal below.
Model answer: After fork(), there are two processes running the same code. The parent receives the child's PID (a positive integer) as the return value; the child receives 0. The program tests this value to branch: if fork() returned 0, the current process is the child; if it returned a positive number, the current process is the parent. 'Returns twice' means one call produced two outcomes in two separate processes — each process sees its own return value.
The apparent paradox resolves once you understand that after fork() there are two execution paths. From each path's perspective, fork() returned exactly once — they just received different values. This is why the idiom `if (fork() == 0) { /* child */ } else { /* parent */ }` works: the condition evaluates differently in each process, allowing a single code path to implement two roles. Understanding this also clarifies why the child resumes mid-program rather than starting fresh.