Skip to main content

System Calls & POSIX

System calls are the gateway between your program and the operating system kernel. Think of them as the reception desk at a secure government building: your program (a visitor) cannot walk into the vault and grab files directly. Instead, you fill out a request form (set up registers), ring a bell (execute the syscall instruction), and a trusted employee (the kernel) fetches what you need and hands it back through the window. Every printf, every file open, every network packet your C program sends eventually passes through this gateway. Understanding system calls is the difference between knowing C syntax and understanding how programs actually interact with hardware. System call path from user space to kernel

User Space vs Kernel Space

User Mode vs Kernel Mode Transition

The Transition Steps

  1. User Mode (Ring 3): Your program runs with limited privileges. It cannot access hardware directly.
  2. Library Call: You call printf(). The C library (libc) formats the string and calls write().
  3. System Call: The write() wrapper puts arguments in CPU registers (e.g., rax=1 for write) and executes a special instruction (syscall on x86-64).
  4. Mode Switch: The CPU switches to Kernel Mode (Ring 0) and jumps to a predefined kernel entry point.
  5. Kernel Execution: The kernel validates arguments, checks permissions, and performs the operation (e.g., writing to the terminal buffer).
  6. Return: The kernel executes sysret, switching the CPU back to User Mode and returning the result (number of bytes written or error).

Making System Calls

Via libc Wrappers

In practice, you almost never call system calls directly. Instead, you call libc wrapper functions that set up the arguments, execute the syscall instruction, check for errors, and set errno. This is like having an assistant who fills out the government forms for you.

Direct System Calls


Error Handling


File Descriptors

File descriptors are the kernel’s universal handle for “anything you can read from or write to.” Files, pipes, sockets, terminals, even special devices like /dev/null — they all look the same to your program: just an integer you pass to read() and write(). This uniform interface is one of Unix’s most powerful design decisions, and it is why shell pipes like cat file.txt | grep pattern | wc -l just work.

Process Information


Environment Variables


Time and Date


Resource Limits


POSIX Portability


Common System Call Reference


Exercises

1

System Info Tool

Build a tool that prints comprehensive system information (CPU, memory, disk, network).
2

Safe Wrapper Library

Create a library of safe wrappers for common system calls with proper error handling and EINTR retry.
3

Syscall Tracer

Use ptrace to build a simple strace-like tool.
4

Resource Monitor

Build a tool that monitors a process’s resource usage over time.

Next Up

Concurrency

Process and thread programming