4.2.3 · D3Operating Systems

Worked examples — System calls — user mode vs kernel mode, trap mechanism

4,224 words19 min readBack to topic

You have met the parent idea: a program rings a bell (a trap), the kernel checks the request, does it, and returns. That story had exactly one happy ending. Real programs hit many endings — good returns, error returns, blocked calls, calls that never even reach the kernel, calls that trigger a context switch, calls whose numbers are garbage.

This page walks every one of those endings. First we lay out a matrix of all the case classes. Then every example below is stamped with the matrix cell it covers, so by the end no scenario is left dark.

Before anything else, three tiny vocabulary anchors so nothing appears un-earned:


The scenario matrix

Every syscall outcome falls into one of these cells. The examples that follow are labelled by cell ID.

Cell Case class What varies Example
A Success, no I/O wait rax ≥ 0, returns instantly Ex 1 (getpid)
B Success, returns a count rax = bytes moved (could be less than asked) Ex 2 (read partial)
C Failure (negative rax) rax < 0 → an errno Ex 3 (open on missing file)
D Degenerate input: zero-size request asked for 0 bytes Ex 4 (read(fd, buf, 0))
E Blocking → context switch syscall sleeps, scheduler runs Ex 5 (read empty pipe)
F "Not actually a syscall" request served in user space Ex 6 (printf buffering)
G Invalid / out-of-range syscall number kernel rejects the index Ex 7 (rax = 999999)
H Bad pointer argument kernel must validate memory Ex 8 (read into NULL)
I Real-world word problem + cost counting the price of many crossings Ex 9 (log writer)
J Exam twist: trap vs interrupt vs exception classify who entered the kernel Ex 10
K Interrupted by a signal blocked syscall returns -EINTR, maybe restarts Ex 11
L Non-blocking, nothing ready -EAGAIN / -EWOULDBLOCK instead of sleeping Ex 12

We will show, for the sign of rax, all three regions — negative (error), zero (degenerate/EOF), positive (success) — because that single number decides your program's fate.

Figure — System calls — user mode vs kernel mode, trap mechanism

Example 1 — Cell A: instant success


Example 2 — Cell B: success that returns less than you asked


Example 3 — Cell C: the failure region (negative rax)


Example 4 — Cell D: degenerate zero-size request


Example 5 — Cell E: blocking, and the context switch it triggers

Figure — System calls — user mode vs kernel mode, trap mechanism

Example 6 — Cell F: the call that isn't a syscall (yet)


Example 7 — Cell G: garbage syscall number


Example 8 — Cell H: bad pointer argument


Example 9 — Cell I: word problem, counting the real cost

Two symbols appear below; earn them first:


Example 10 — Cell J: exam twist, classify the entry


Example 11 — Cell K: a blocked syscall interrupted by a signal


Example 12 — Cell L: non-blocking I/O with nothing ready


Recall Quick self-test on the sign of

rax rax after a syscall is -2. Success or failure, and what does it mean? ::: Failure — negative means -errno; -2 = -ENOENT, "no such file or directory". You called read(fd, buf, 100) and got rax = 30. Bug or normal? ::: Normal — a short read; you got 30 of up to 100 bytes. Loop for the rest. You called read(fd, buf, 100) and got rax = 0. Meaning? ::: End-of-file (because you asked for more than 0). No more data will come. You called read(fd, buf, 0) and got rax = 0. Meaning? ::: You asked for nothing and got nothing — success, not EOF. A single read triggered a context switch. What happened? ::: It blocked (no data); the scheduler ran another process while you slept. read returned -4 (EINTR). What do you do? ::: A signal interrupted the blocked call; retry the read (it never really finished). A non-blocking read returned -11 (EAGAIN). Meaning? ::: No data is ready right now; don't block — wait for readiness and try again.