System calls — how a program asks the kernel for help
A program can't read a file, open a network connection, or even print to the screen entirely on its own — every one of those requires asking the kernel to do it, through a mechanism called a system call.
Beginner
2 min read
Your program isn't actually allowed to touch hardware directly
Ordinary application code runs without direct access to disks, network
cards, or memory that belongs to other processes — that access is deliberately
restricted to the kernel (the next lesson covers exactly why). So when your
code calls something as simple as "read this file" or "print this text," it
isn't doing that itself — it's asking the kernel to do it on its behalf,
through a system call.
A call you already use, one layer down
Something as ordinary as Python's open("file.txt") or print("hello")
eventually reaches the open (on modern Linux, openat) and write system
calls underneath — the
language's standard library is a convenient wrapper, but the actual work of
touching the filesystem is still delegated to the kernel every time.
# strace shows every system call a program makes, live$ strace -e trace=openat,read,write cat file.txtopenat(AT_FDCWD, "file.txt", O_RDONLY) = 3read(3, "Hello, world!\n", 131072) = 14write(1, "Hello, world!\n", 14) = 14
Even a program as simple as cat — which just prints a file's contents —
is making a small, visible sequence of system calls to open the file, read
its contents, and write them to your terminal. Nothing about "reading a
file" happens without this handoff to the kernel.
Why this indirection exists at all
Routing every hardware-touching operation through the kernel is what makes
it possible to enforce permissions consistently (a program can't just read
any file on disk regardless of ownership — every read gets checked at the
system call boundary) and to multiplex shared hardware safely between many
processes at once (two programs writing to the same file, or reading from
the same network card, without corrupting each other). None of the earlier
lessons in this domain — process states, scheduling, memory — would be
enforceable if a program could simply bypass the kernel and touch hardware
directly.
Why this matters day to day
System calls are the actual, literal boundary where your code's requests
become real I/O — which is exactly why a slow disk or a slow network shows
up as time spent in system calls, not in your own code's logic, when
profiling a program. Tools like strace (Linux) exist specifically to make
that normally-invisible layer visible, letting you see exactly what your
program is really asking the operating system to do, one call at a time.