System Calls

4 Posts

Privilege Levels, Exceptions, and System Calls: How CPUs Enter Controlled Paths

8 minute

An application calling read() looks like a normal function call. Illegal instructions, page faults, interrupts, and system calls can also look like “the CPU jumped to another handler.”

But these paths are not normal function calls.

A normal function call stays in the same privilege level and address space. The caller knows the callee address, passes arguments according to the ABI, and returns when the callee finishes. Exceptions and system calls are different: current code cannot freely choose a high-privilege entry. The CPU must switch state according to architectural rules, transfer execution to a controlled entry, and allow the kernel, firmware, or exception handler to decide what happens next.

Read More

Why I/O Multiplexing and Event Loops Are Common

8 minute

Many Linux services eventually become event loops: network sockets, pipes, timerfd, eventfd, device nodes, and signal notifications all enter a select, poll, or epoll loop.

This is not because epoll is a more advanced read(). It solves a more basic problem: one thread cannot block on many read() calls at the same time.

If a program has only one socket, blocking read() is natural. Once it must handle hundreds of connections, one control pipe, several timers, and a device fd, it cannot let the thread get stuck on any single object.

Read More

Why a System Call Is Not a Normal Function Call

7 minute

Application code calls read(), write(), open(), or mmap() in a way that looks very similar to an ordinary function call. Pass a few arguments, receive a return value, check errno on failure.

But a system call is not a normal function call.

A normal function call stays inside the same process, privilege level, and address space. A system call moves the CPU from user space into kernel space and hands control to the kernel. The kernel does not receive “trusted arguments.” It receives a request from user space: whether the file descriptor is valid, whether the pointer is accessible, whether the length is safe, whether the process has permission, and whether the call should block all have to be checked.

Read More

What Separates Applications, the Kernel, and Drivers?

8 minute

When application code calls read(), write(), or ioctl(), it can look like the program is directly operating a device. Reading a UART, writing to a network interface, controlling GPIO, or accessing a sensor may all appear to be simple function calls.

But that path is not the application touching hardware directly.

On systems with an operating system, applications, the kernel, and drivers are separated by several boundaries: permission boundaries, address-space boundaries, system-call boundaries, device abstraction boundaries, and blocking semantics. Many application-driver debugging problems come from mixing these boundaries together.

Read More