What a System Call Is
Chapter Nine
Syllabus topic Module 1, "Fundamentals of Operating systems - System Calls"
Pages 35 to 38 of 452
In one line
A system call is a request from a program to the kernel, made by executing a special instruction that traps into kernel mode.
The precise form: a system call is the programming interface to the services of the operating system. It is invoked by a trap instruction, which switches the processor to kernel mode and transfers control to the kernel's system call handler.
Why a program cannot simply call the kernel
A program calls one of its own functions by jumping to its address. Why not jump to the kernel's function the same way?
Because of Chapter three. The kernel's code sits in memory the program cannot touch, and it runs in kernel mode, which the program cannot enter. A jump would be an invalid access and the program would die with a segmentation fault. The mode bit cannot be set by the program, because setting it is privileged.
So there has to be one controlled door, and the door is a trap. The program executes an instruction whose whole purpose is to say "kernel, I want something", the processor switches mode, and the kernel's own handler decides what to do. The program never gets to choose where in the kernel it lands.
That single sentence is why the system call interface is the security boundary of the whole machine. Everything a program is allowed to do, it does through one of a few hundred numbered requests, each of which the kernel checks.
The steps, in order
- The program puts the system call number where the kernel will look for it, and the
arguments where the kernel will look for those.
- The program executes the trap instruction.
- The processor switches to kernel mode and jumps to the kernel's system call handler.
- The handler reads the number and uses it as an index into the system call table, which
holds the address of the routine for each number.
- That routine checks the arguments, does the work, and puts a return value where the program
will find it.
- The handler returns from the trap. The mode bit goes back to user mode and the program
continues at the instruction after the trap.
Step 5's check is not optional and is not a formality. The arguments came from a program that may be hostile. A pointer the program supplies might point into the kernel; a length might be negative; a file descriptor might not be open. Every one of those has to be verified before it is used, and a kernel bug in that checking is a security hole.
The three ways arguments are passed
More arguments are often needed than there are registers, and the trap instruction cannot carry them. Three methods are in use and all three are examined.
What a System Call Is
| Method | How | Limit |
|---|---|---|
| In registers | each argument in a named register | the number of registers, typically six |
| In a block or table in memory | the program builds a block, and passes its address in one register | none |
| On the stack | the program pushes them, and the kernel pops them | none |
Linux on this machine uses registers, which is why write takes exactly three arguments and why a call needing more, such as mmap with six, is at the practical limit.
A library call is not a system call
This is the distinction the chapter exists for. printf is a function in the C library. write is a system call. printf eventually calls write, but it is not the same thing, and the difference can be measured.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
const char *a = "written by the library, with printf\n";
const char *b = "written by the system call, with write\n";
printf("%s", a);
write(STDOUT_FILENO, b, strlen(b));
return 0;
}$ gcc -std=c17 -Wall -Wextra -o twoways twoways.c
$ ./twoways
written by the library, with printf
written by the system call, with writeOn the screen they look identical. Now send the output to a file instead, and the order changes.
$ ./twoways > out.txt
$ cat out.txt
written by the system call, with write
written by the library, with printfThe lines came out in the wrong order, and that is the proof. printf did not write anything when it was called: it put the text in a buffer inside the C library and returned. The write call went straight to the kernel. Only when the program ended did the library flush its buffer, which is why the library's line is last.
When the output was the screen, the library flushed at every newline, because a terminal is treated as interactive. When the output was a file, it flushed only when the buffer was full or the program ended. Nothing about the kernel changed. The library changed its mind.
This is a real bug students meet. A program that prints with printf and then crashes loses the printed lines, because they were never given to the kernel. A program that prints with write does not.
The count of system calls confirms it: printf called write once, at the end, with both lines buffered together or separately depending on where the output went.
What a system call looks like in the manual
Every system call has a manual page in section 2, and the lab machine also carries the POSIX standard's own page for the same call in section 3p. Reading both is how this book knows what a call promises.
What a System Call Is
$ man 2 write 2>/dev/null | sed -n '/^SYNOPSIS/,/^DESCRIPTION/p' | head -6
SYNOPSIS
#include <unistd.h>
ssize_t write(int fd, const void buf[.count], size_t count);
DESCRIPTION
$ man 3p write 2>/dev/null | sed -n '2,4p'
PROLOG
This manual page is part of the POSIX Programmer's Manual. The LinuxThe first is what Linux does. The second is what every Unix must do. Where they differ, the Linux page says so, and this book says which one it is quoting.
Worked example: counting the doors a simple program uses
/bin/true does nothing at all. It is the simplest program on the machine. Count the system calls it makes.
$ strace -c /bin/true 2>&1 | tail -2
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 0 27 1 totalTwenty seven system calls to do nothing at all. They are the program being loaded: the kernel finding and opening the C library, mapping it into memory, arranging the stack, and then exiting. Every program pays that, and it is why starting a process is not free, which is the point Chapter thirty one makes about thread pools.
Distinctions that carry marks
| System call | Library function | |
|---|---|---|
| Runs in | kernel mode | user mode |
| Entered by | a trap instruction | an ordinary function call |
| Costs | a mode switch each time | a jump |
| Can be avoided? | no, for anything needing the hardware | yes, it is just code |
| Example | write, open, fork | printf, strlen, malloc |
| Where documented | manual section 2 | manual section 3 |
| System call | Ordinary function call | |
|---|---|---|
| Destination | chosen by the kernel from a table | chosen by the caller |
| Mode | changes | does not change |
| Arguments checked | always, by the kernel | not usually |
What it does not mean
A system call is not slow because it does a lot. It is expensive because of the mode switch and the checking, so a program that makes a million small calls is slower than one that makes a thousand large ones. This is why buffering exists at all.
printf is not "the system call for printing". There is no system call for printing. There is write, which puts bytes somewhere, and printf is a formatting function that ends up calling it.
A system call is not a function in your program that the kernel calls back. The traffic is one way: your program asks, the kernel answers.
The number of system calls is not large. Linux has a few hundred. Everything any program does goes through them.
Quick revision
- A system call is the programming interface to the operating system's services, invoked by a
trap that switches to kernel mode.
- There is one controlled door because the program cannot enter kernel mode itself and cannot
What a System Call Is
choose where in the kernel it lands.
- The steps: number and arguments in place, trap, mode switch, handler, system call table
lookup, argument check, work, return.
- Arguments are passed in registers, in a block whose address is passed, or on the
stack.
printfis a library function,writeis a system call. Redirecting a program's
output to a file changes the order in which they appear, because the library buffers and the system call does not.
- A system call costs a mode switch, so few large calls beat many small ones.
- Manual section 2 is Linux's system calls; section 3p is the POSIX standard's own page.
Test yourself
- Define a system call. The programming interface to the services of the operating system,
invoked by a trap instruction that switches the processor into kernel mode and enters the kernel's handler.
- Why can a program not just call a kernel function directly? The kernel's memory is not
accessible to it and the kernel runs in kernel mode, which the program cannot enter because setting the mode bit is privileged.
- Name the three ways arguments are passed to a system call. In registers, in a block of
memory whose address is passed in a register, and on the stack. 4. A program prints two lines, one with printf and one with write, and the output is redirected to a file. What order do they appear in and why? The write line first. printf buffered its text in the C library and the buffer was not flushed until the program ended.
- Why is a system call more expensive than a function call? It switches processor mode twice
and the kernel must check every argument, because the arguments came from a program that may be hostile.
/bin/truedoes nothing, yet makes twenty seven system calls. What are they? The work of
starting a program: opening and mapping the C library, arranging memory, and exiting.
The rest of this subject
These notes are cut from the University's printed syllabus. Open the syllabus itself, or the past papers, for the same subject.