System Calls

[!NOTE] This module explores the core principles of System Calls, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.

1. Crossing the Border

Your application runs in User Space (Ring 3). It is powerless. It cannot touch the disk, the network, or even allocate more RAM without asking permission.

To do anything useful, it must cross the border into Kernel Space (Ring 0) using a System Call.

This is expensive. It involves a Context Switch:

  1. Save CPU registers of the current process.
  2. Switch CPU mode from User to Kernel.
  3. Load Kernel code.
  4. Execute the request.
  5. Switch back.

2. Anatomy of a Syscall (read)

Let’s trace what happens when you read a file.

  1. User App: Calls read(fd, buffer, 1024).
  2. C Library (glibc): Puts the System Call ID (e.g., 0 for read) into the RAX register. Executes the SYSCALL CPU instruction.
  3. CPU: Switches to Ring 0. Jumps to the kernel’s entry_SYSCALL_64 function.
  4. Kernel:
    • Checks if fd is valid.
    • Checks if you have permission.
    • Asks the Disk Driver to fetch data.
    • BLOCKS your process (puts it to sleep) while waiting for the disk.
  5. Hardware: Disk Interrupts CPU: “Data is ready!”.
  6. Kernel: Wakes up your process. Copies data from Kernel Buffer to User Buffer.
  7. CPU: Switches back to Ring 3. Returns control to your app.

3. Code Example: Making a Syscall

Most languages hide this complexity. Let’s peel back the layers.

package main

import (
    "syscall"
)

func main() {
    // Directly invoking the 'Write' syscall (ID 1 on Linux)
    // 1 (Stdout), "Hello\n", 6 bytes
    data := []byte("Hello System Call\n")

    // Low-level syscall wrapper
    syscall.Write(1, data)
}

4. Interactive: The Syscall Crossing

Visualize the data journey.

  • User Buffer: Your app’s memory.
  • Kernel Buffer: OS memory.
  • Hardware: The actual disk.
User App
Ring 3
Ring 0
Kernel
💾
Disk

5. Summary

System Calls are the gateway to the hardware. They are necessary but expensive. High-performance applications (like Databases or Game Engines) try to minimize them (e.g., by buffering data).