The Privilege Boundary
User code runs in unprivileged mode (user space) with restricted access to hardware and memory. Kernel code runs in privileged mode (kernel space) with full access. A system call is the bridge: user code requests a kernel service (open a file, allocate memory, fork a process) via a trap instruction, which switches the CPU to kernel mode and transfers control to the kernel.
The CPU saves the user-space state (registers, instruction pointer, stack pointer) into kernel memory, switches the stack to a kernel-mode stack, and begins executing kernel code. The kernel performs the requested operation, then switches back: restores user-space state, drops to user mode, and resumes the user code.
Cost and Implications
A system call is expensive, costing hundreds to thousands of CPU cycles due to mode switching, cache flushing, and stack swapping. This makes batching system calls important: opening 100 files with 100 separate open() calls is slower than opening them in a batch if possible.
Operating systems optimize system call overhead through caching (vdso, vsyscall), batching (e.g., readv/writev for multiple buffers), and asynchronous APIs (epoll, aio). User-space libraries (musl libc) also minimize unnecessary calls. Applications that make frequent system calls (like database engines with per-operation I/O) use buffering, async patterns, or memory-mapped I/O to reduce the number of kernel transitions.