Why Do System Calls Cost So Much? Exploring Linux’s Three Execution Methods
This article explains how Linux implements system calls via software interrupts, fast syscall/sysenter instructions, and the virtual dynamic shared object (vDSO), comparing their performance to regular function calls and showing concrete code examples and step‑by‑step execution details.
Overview of Linux System Calls
System calls are the kernel‑level interface that user‑space programs use to request services such as file I/O, process creation, and time retrieval. Typical programs invoke many system calls during startup; only the calls directly caused by user code (e.g., write from printf) are essential for the program’s logic.
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}Running the program under strace shows dozens of calls, most of which belong to the dynamic loader and runtime initialization.
Three Execution Paths for System Calls
Software interrupt (INT 0x80)
Fast entry instructions (SYSENTER / SYSCALL)
Virtual Dynamic Shared Object (vDSO)
1. Software Interrupt (INT 0x80)
On 32‑bit x86 Linux the classic path uses the INT 0x80 instruction. The sequence is:
Application calls a libc wrapper (e.g., write).
The wrapper copies arguments to registers and places the syscall number in eax.
Processor executes INT 0x80, switching to kernel mode.
Kernel entry point entry_INT80_32 saves all registers ( SAVE_ALL) on the kernel stack.
Kernel validates the syscall number via do_syscall_32_irqs_on.
Implementation is looked up in ia32_sys_call_table.
Arguments are checked, data is copied between user and kernel space, and the result is placed back in eax.
Kernel restores registers and returns to user space; the libc wrapper translates the result into a return value or sets errno.
This path involves full context saving, an interrupt‑descriptor‑table lookup, and data copying, which adds noticeable latency.
2. Fast Entry Instructions (SYSENTER / SYSCALL)
Modern kernels replace the interrupt with dedicated entry instructions. On 64‑bit systems the SYSCALL / SYSRET pair is used; on 32‑bit systems SYSENTER / SYSEXIT are used. These instructions bypass the IDT and avoid saving a full stack frame, reducing the number of clock cycles by roughly 25 % compared with the software‑interrupt method.
void syscall_init(void) {
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
/* other MSR setup */
}During boot the kernel writes the address of entry_SYSCALL_64 to the model‑specific register MSR_LSTAR. When a user program executes SYSCALL, the CPU jumps directly to this entry point, which then calls do_syscall_64 to dispatch the request via the 64‑bit syscall table.
3. vDSO (Virtual Dynamic Shared Object)
vDSO is a small kernel‑provided shared object mapped into every process’s address space. It implements a limited set of “safe” syscalls (e.g., gettimeofday, clock_gettime, clock_getres, rt_sigreturn) entirely in user space, eliminating the kernel transition.
$ ldd /bin/cat
linux-vdso.so.1 (0x00007fff2709c000)
$ cat /proc/self/maps
7ffe8ca90000-7ffe8ca92000 r-xp 00000000 00:00 0 [vdso]During program start‑up the ELF loader records the vDSO base address in the auxiliary vector entry AT_SYSINFO_EHDR. The dynamic linker reads this entry, and libc resolves symbols such as __vdso_gettimeofday to function pointers inside the vDSO. Calls to these functions execute with the same cost as ordinary function calls, providing performance improvements of dozens of times over the traditional syscall path.
Practical Implications
Software‑interrupt syscalls involve full context saving and IDT lookup, resulting in the highest overhead.
Fast entry instructions are the default on modern Linux kernels and reduce unnecessary work, offering a lower‑latency path for most syscalls.
vDSO provides the fastest path for a small, non‑privileged subset of syscalls, effectively flattening their cost to that of a regular function call.
Understanding these mechanisms helps developers diagnose performance bottlenecks and choose the appropriate interface when writing low‑level Linux applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
