Appearance
Module 10 Article: API, ABI, and the System Call Boundary
The big idea
For code to talk to an OS or another library without rewriting everything each time, it needs a stable interface. Two layers matter:
- An API (application programming interface): the source-level contract — function names, argument types, and headers.
- An ABI (application binary interface): the binary contract — calling convention, name mangling, struct layout, and library format.
A program is source-compatible if it recompiles against a new version; it is binary-compatible if the existing executable keeps running without recompilation. ABIs are harder to keep stable, and that is where compatibility breaks.
API vs ABI, concretely
Consider a C function:
c
int add(int a, int b);- API: the signature
int add(int, int)and the headeradd.h. If a new version renames a parameter or keeps the same types, the API is unchanged and old code recompiles fine. - ABI: also specifies that
aandbgo in registers (e.g.,rdi,rsion x86-64 System V), the result comes back inrax, the symbol is literallyadd(not C++-mangled), andintis 32 bits. If any of these change, an already-compiled.soor executable breaks.
A breaking ABI change that does not break the API
Reordering struct fields changes the binary offsets:
c
struct S { char c; int i; }; // size 8 (1 + 3 pad + 4)→
c
struct S { int i; char c; }; // size 5 (different layout)The type and field names are the same API, but compiled code that reads field c at offset 4 now reads garbage. The ABI broke; the API didn't.
System calls: the kernel entry point
A system call is the program's request for OS service. The path:
program sets args in registers → issue `syscall` instruction →
CPU switches to kernel mode → kernel dispatches handler →
kernel returns result → program resumes in user modeExample (x86-64 Linux)
c
#include <unistd.h>
long _start() {
const char msg[] = "hi\n";
syscall(SYS_write, 1, msg, 2); // write(fd=1, buf=msg, count=2)
syscall(SYS_exit, 0);
}At the ABI level this means: rax = 1 (write), rdi = fd, rsi = buf, rdx = count; the kernel returns the byte count in rax. The exact register assignment is the ABI.
Protected mode and drivers
Protected mode (x86) / hypervisor mode (ARM EL1) is the hardware support that makes user/kernel separation real:
- Virtual addresses are translated (MMU) and checked against the process's page tables and ring 2/3 permissions.
- I/O instructions (
in/out, accessing PCIe MMIO) are privileged; only ring 0 can execute them. A userininstruction traps to the kernel. - The OS runs in ring 0; applications run in ring 3. Drivers are kernel modules — which is exactly why a bad driver can crash the whole system.
Keeping binaries compatible
Operating systems keep old programs working through:
- Symbol versioning (glibc attaches
GLIBC_2.2.5,GLIBC_2.34, … to each symbol so old and new callers link to the right version). - Deprecation without removal: keep old symbols forever; add new ones.
- Stable ABIs at the boundary: POSIX APIs and the Linux syscall ABI are kept stable even as kernels evolve.
Startup scripts and bootstrapping
Boot
- Firmware (UEFI/BIOS): runs POST, initializes hardware, selects a boot device.
- Bootloader (GRUB/systemd-boot): reads its config, loads the kernel image and an initrd (initial RAM disk with early drivers).
- Kernel: mounts
rootfs, brings up memory management and devices, starts the first process, init (PID 1, orsystemd). - init/systemd: bring up services in dependency order — this is what "startup scripts" used to mean (SysV
/etc/init.d/scripts), now systemd units started in parallel.
Startup scripts today
systemdunit files replace/etc/init.d/*scripts.systemctl enable <name>marks a service to start at boot;systemctl startruns it now.- The equivalent of "run level 3" is a target like
multi-user.target; "run level 5" isgraphical.target.
Exam angle
For "API vs ABI":
- Define both; stress that API = source-level, ABI = binary-level.
- Give a concrete difference: changing struct layout breaks ABI, not API.
- For system calls: trace the register setup +
syscall+ kernel-mode switch. - Mention protected mode gives ring 0 to the kernel (and drivers), ring 3 to applications.
Tip: when comparing "API change that breaks ABI," struct field reordering is the textbook example examiners expect.