Operating Systems — Lecture 02
./hello (prints one line) ~1,015,131 instructions
./hello_nostd (write + exit) ~108,573 instructions
The program wrote a dozen instructions. The machine ran a hundred thousand to a million.
The rest is the operating system.
The operating system is a provider of services — so it has an interface.
It is an enforcer of isolation — so that interface is a boundary, not a function call.
A library — but not linked into your program, and shared by every program at once.
A normal library trusts its caller. The kernel must not: its callers are every program on the machine, and some are hostile.
Unikernel: the smallest an OS can be
c-hello_qemu-x86_64 241K 855 symbols
240 KB to print one line. “Run a program on a machine” is a big job.
Monolithic (all in the kernel) · microkernel (drivers are processes) · unikernel (no boundary)
$ strace ./read_write_syscall
write(1, "Gimme message: ", 15) = 15
read(0, "hello there\n", 64) = 12
write(1, "hello there\n", 12) = 12
exit_group(0) = ?
Call number in rax, args in registers, syscall, result in rax.
The trace is the program. Nothing sits between it and the kernel.
Programs call printf(), malloc(). libc turns those into system calls — when it has to.
getpid() — one system callstrlen() — none, everprintf() — a write(), or nothing, depending on the bufferlibc decides when to cross. That is what optimisation exploits.
$ ./cli
first
Segmentation fault (core dumped)
cli disables interrupts — ring 0 only.
There is no check for it in the kernel. The CPU faults on it at ring 3.
A software check can have a bug. This cannot.
kernel/user = a hardware mode · root/non-root = a software identity
Root still runs in user mode. Root still faults on cli.
./make_syscalls (write to /dev/null) 703224 us
./make_libcalls (a function call) 9360 us
~70x. /dev/null does nothing — almost all of it is the crossing.
So: cross it less.
fwrite_buffered 65846 us sendfile server ~1800 us
fwrite_unbuffered 1508197 us write server ~5900 us
Down — buffer in user space, batch the crossings.
Up — push the whole job into the kernel, remove them.
One idea, two ends.
No correct answer. Linux is monolithic; seL4 flies aircraft.
A hypervisor is to operating systems what an OS is to applications.
More privileged than the kernel. Each guest OS believes it owns the machine.
Dual role: provider of services, enforcer of isolation.
Isolation needs a boundary. The boundary is entered through system calls, it costs, and OS types and virtualization are where you put it.