E ExamMaster

AP Exams (Advanced Placement) · Operating Systems

System calls and the process API

User versus kernel mode, the trap that is a system call, and fork / wait / exit.

maya still has PID 1420. This lesson is how she asks the kernel for work she is not allowed to do herself: the user-mode / kernel-mode fence, the trap called a system call, and the process API — fork returns twice, exit ends a child, wait collects it. Three forks in a row still make 2^3 = 8 processes.

  • AP Exams (Advanced Placement)
  • Medium level
  • 5 concepts

1User mode and kernel mode

The CPU has a privilege bit. In user mode, maya may run her own editor instructions and may not touch another process's memory or talk to the disk controller directly. In kernel mode, the operating system may do those things. The bit is the fence: user code asks; kernel code is allowed.

maya spends almost all of her time in user mode. She crosses into kernel mode only when she needs a service the fence forbids — open a file, read the disk, create a process. That crossing is the system call.

Figure. maya runs in user mode. A request she is not allowed to perform herself crosses into kernel mode.

Who may do what

  1. User modemaya's editor code. No raw disk, no other process's memory.
  2. Kernel modeThe OS. May change page tables, talk to devices, create PIDs.
  3. The fencemaya cannot flip the bit herself. She asks, through a system call.
Mode
ModeWho is runningWhat they may do
Usermaya's editorHer own instructions and her own memory
Kernelthe operating systemDevices, page tables, other processes
maya adds two numbers in the editor. Which mode is that?
  1. User mode — it is her own arithmetic
  2. Kernel mode — every instruction is kernel
  3. Neither — arithmetic needs a system call

Ordinary editor work stays in user mode. A system call is only for work the fence forbids, such as disk or a new process.

2A system call is a request through the fence

A system call is a named request from user mode into the kernel: open, read, write, fork, exec, wait, exit. maya does not jump to kernel code like an ordinary function. She executes a trap instruction. The CPU switches to kernel mode, the kernel looks up which service she asked for, does the work (or refuses it), and returns to user mode with a result.

A library function such as printf is not itself a system call. It may end up calling write. The system call is the trap, not the C name in a textbook. If maya never needs the kernel, she never traps.

Figure. maya does not call the disk driver. She traps; the kernel runs the service and returns.

One call

  1. Askmaya executes a trap with a service number — say, read.
  2. SwitchThe CPU enters kernel mode. The fence is open for the OS only.
  3. ReturnThe kernel finishes, puts a result in a register, and returns to user mode.

Names, not a runnable kernel

fd = open("essay.txt")   # trap: open
n  = read(fd, buf, 64)    # trap: read
pid = fork()              # trap: fork — returns twice
What actually enters kernel mode when maya reads a file?
  1. A trap that names the read service
  2. The printf library itself
  3. The editor window toolkit

printf may call write later. The mode switch is the trap. A GUI toolkit is user code.

3One fork, two processes, two return values

fork() is the process API most people meet first. maya, PID 1420, calls fork(). The kernel copies her address space, open files and registers into a new process — say PID 1421. Then it returns in both. In 1421 the return value is 0. In 1420 the return value is 1421.

That is why textbook code writes if (pid == 0) for the child and else for the parent. There is no third return. A failed fork returns −1 in the caller and creates no child — one return, the error path.

Figure. One call. Two processes. The child sees 0; the parent sees the child's PID.

Who sees what

  1. BeforeOnly maya, PID 1420, is running this line.
  2. After success1420 sees pid = 1421. 1421 sees pid = 0.
  3. After failureOnly 1420 remains; the return is −1.
Return values
Whofork() returned
Parent maya, PID 1420child PID (1421)
Child, PID 14210
Parent, if fork failed−1, and no child exists

Only the child forks again

maya (PID 1420) runs pid = fork(); then if (pid == 0) fork();. The inner fork() sits inside the child-only branch. How many processes exist in total when the program finishes, assuming both forks succeed?

  • start, before any fork()1 process (maya)
  • pid = fork()2 processes: parent sees pid > 0, child sees pid == 0
  • if (pid == 0) is true only in the childonly the child reaches the inner fork()
  • child runs fork()+1, so 3 processes total

Pro tip. Guarding a fork() with if (pid == 0) puts it in the child branch only, so it does not double the whole crowd the way a bare 2^n chain would. Read the return value before you apply the rule.

In the child created by fork(), the return value is
  1. 0
  2. the parent's PID
  3. −1

Child sees 0. Parent sees the new PID. −1 is failure in the caller, with no child.

4fork() returns twice and doubles the count

maya, still PID 1420, can ask the kernel to clone her. The call is fork(). After a successful fork the machine has two processes: the parent (still 1420) and a child with a new PID. fork() returns twice — once in each process. The child sees 0. The parent sees the child's PID, a positive number. That is how each side knows who it is.

If maya, and every child she creates, calls fork() again with no one exiting, each call doubles the crowd. After n such calls the total number of processes is 2^n, including the original. New children created along the way are 2^n - 1. Three calls in a row: 2^3 = 8 processes, 7 of them new.

Figure. Standard tree when every living process runs all three forks: P0's children are C1 (fork 1), C2 (fork 2) and leaf C4 (fork 3). Eight nodes total — 2^3.

Why the count doubles

  1. Each call doublesEvery living process that reaches the next fork() becomes two.
  2. n in a rowStarting from 1, after n sequential forks the total is 2^n.
  3. Watch the returnsParent sees PID > 0; child sees 0 — useful when a problem asks who runs which branch.

Three forks in a row

int main(void) {
    fork();
    fork();
    fork();
    /* how many processes now? */
    return 0;
}

Three consecutive forks

The main process executes fork() three times in a row, with no exits between calls. How many processes exist in total, and how many new children were created?

  • after 1st fork()2 processes
  • after 2nd fork() (each of 2 calls fork)4 processes
  • after 3rd fork() = 2^38 processes
  • new children = 2^3 - 17

Pro tip. Total processes = 2^n for n consecutive forks; new children = 2^n - 1. If any process exits or branches around a fork, drop the blind 2^n rule and draw the tree.

Coding lab. Count the processes after three forks runs in the app, with checks on your output.

After fork() is called four times in a row (no exits), the total number of processes is
  1. 4
  2. 8
  3. 16

2^4 = 16 total processes, including the original. 8 would be three forks; 4 would be two.

5exit ends a process; wait collects it

When the child PID 1421 is done, it calls exit. That moves it to Terminated and leaves a small record — the exit status — behind so the parent can read it. Until someone collects that record, 1421 is a zombie: dead, but still occupying a PCB slot.

maya, the parent, calls wait (or waitpid). The kernel hands her the exit status and frees the child's PCB. If she calls wait before the child has exited, she blocks — Running → Waiting — until 1421 exits. If she never waits, zombies accumulate. The pair is the process API: fork creates, exit ends, wait collects.

Figure. exit without wait leaves a zombie. wait reads the status and frees the PCB.

Create, end, collect

  1. fork1420 creates 1421.
  2. exit1421 finishes and leaves a status. It is a zombie until collected.
  3. wait1420 reads the status. The PCB slot is freed.
A child has called exit but the parent has not called wait. The child is
  1. a zombie — Terminated, PCB still allocated
  2. Ready, waiting for the CPU
  3. already deleted, so wait will fail

exit ends execution and leaves the status. wait collects it. Until then the PCB remains.

Notes

  • User mode cannot touch devices or other address spaces; kernel mode can.
  • A system call is a trap into the kernel, not a C library name.
  • fork() returns 0 in the child and the child's PID in the parent.
  • n consecutive forks with no exits create 2^n processes.
  • exit without wait leaves a zombie until the parent reaps it.

Formulas

  • After n consecutive fork() calls with no exits, total processes = 2^n.
  • New children created = 2^n - 1.
  • fork() return: 0 child, >0 parent (child PID), −1 failure.

Exam traps & shortcuts

  • Count processes as 2^n only when every process executes all n forks and nobody exits.
  • if (pid == 0) is the child; the parent sees a positive PID.

Reference tables

Four calls, one family. Numbers from the three-fork walk.

Process API
CallWhat it does for maya
forkClone 1420; returns 0 in the child, child PID in 1420
execReplace the child's memory with a new program (not counted here)
waitCollect a child's exit status; free its PCB
exitEnd this process and leave a status

Recap

A system call is a trap. fork returns twice. Three in a row make 8 processes.

Modes
User mode runs maya. Kernel mode runs the OS. The fence is the privilege bit.
Syscall
A trap with a service name — open, read, fork — not a library label.
fork returns
0 in the child, child PID in the parent, −1 on failure.
Count
n forks in a row, no exits: 2^n processes, 2^n-1 new children.
wait / exit
exit without wait leaves a zombie. wait reaps the PCB.

Practise System calls and the process API

Reading is free and needs no account. Practice, mocks and progress live in the app.

  • A 1-question practice set that ends the chapter
  • 5 quick checks with worked explanations
  • Timed mocks scored with the real marking scheme
  • Readiness tracked per topic, kept on your device
Continue with Google — freeNo card, no trial. Works offline once installed.