C++ / a working model

109 / 163   ·   C11   ·   8 min

Interlude: Process API

Keep this sentence

This interlude presents the core UNIX interfaces for process creation and control. fork duplicates the calling process so parent and child resume from the same return point with different values, wait lets a parent block until a child finishes, and the exec family replaces the entire process image with a new executable. Together they form a compact yet highly expressive API.

In this lesson
  1. How fork() Duplicates a Running Process
  2. Using wait() to Synchronize Parent and Child
  3. exec() Completely Overwrites the Current Image
  4. Example
  5. Exercise

Official chapter PDF

How fork() Duplicates a Running Process

fork instantly clones the caller: the child receives its own address space, registers and instruction pointer, yet resumes immediately after the fork return as if it had issued the call itself. The parent is given the child's PID while the child is given zero, allowing an immediate split in control flow. Thereafter the two processes are independent; the scheduler decides who runs next, so unsynchronized output order is unpredictable.

Using wait() to Synchronize Parent and Child

A parent that calls wait or waitpid suspends until one of its children exits and its termination status is reaped. This both eliminates zombies and makes the order of later statements deterministic: whichever process is scheduled first, the parent will not continue until the child has finished printing and terminated.

exec() Completely Overwrites the Current Image

A child frequently calls one of the exec-family functions right after fork. On success the entire address space (code, data and stack) is replaced by the named executable, so statements after the exec never execute. Shells rely on exactly this fork-then-exec sequence to launch the commands a user types.

Pitfalls

  • Continuing without inspecting the fork return value can send both parent and child down the wrong path
  • Omitting wait turns an already-exited child into a zombie that occupies a process-table slot
  • Assuming the child always prints first when no wait is present

Run an example

Minimum C11 · complete program · Download .c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void) {
    pid_t rc = fork();
    if (rc < 0) {
        fprintf(stderr, "fork failed\n");
        return 1;
    } else if (rc == 0) {
        printf("hello from child\n");
    } else {
        wait(NULL);
        printf("hello from parent after wait\n");
    }
    return 0;
}

Compile locally

gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-05-process-api.c -o example && ./example

Expected result

hello from child
hello from parent after wait

CHECK YOUR UNDERSTANDING

Close the answer. Explain it.

Once the parent contains wait(NULL), why does the child's output always appear before the parent's output?

Show a reference answer

Whichever process the scheduler picks first, the parent blocks inside wait until the child has exited. The child prints and then terminates, so its line necessarily appears first.

Check the sources

Drafts and official chapters change. The version mark is only the example’s minimum.

Back to the catalog