Frontend Labs
⋯

0.8 The Go labs: the OS from inside a program

The commands in this guide show the operating system from the outside: ps, strace, free, docker stats. Part 20 shows it from the inside, with Go programs that make the kernel's behaviour visible: how many OS threads a goroutine really costs, what happens when a container's memory limit meets Go's garbage collector, why PID 1 must reap zombies, how to write a file that survives a power cut, and a working container runtime in about 150 lines.

Every lab was run on Linux (in Docker on an Apple-silicon Mac) while writing this guide, and the outputs shown are real. Most labs are Linux-only (//go:build linux). On a Mac, cross-compile and run them in a container:

mkdir -p ~/oslabs && cd ~/oslabs && go mod init oslabs
mkdir threads    # save the lab as threads/main.go
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bin/threads ./threads   # GOARCH=amd64 on Intel
docker run --rm -v "$PWD/bin":/b debian:bookworm /b/threads
Lab Chapter What it shows
threads 73 Goroutines vs OS threads: sleeping, network-blocked, syscall-blocked
pid1 74 Zombies piling up under a PID 1 that doesn't reap, and three fixes
gomaxprocs 75 Go's container-aware GOMAXPROCS, and CPU throttling when it's wrong
memlimit 76 An OOM kill at 300 MB, prevented by GOMEMLIMIT, and what that costs
atomicwrite 77 Durable, atomic file replacement, and what fsync costs
fdlimit 78 RLIMIT_NOFILE, EMFILE, and Go raising its own limit
gops 79 ps/top rebuilt from /proc
minicontainer 80 Namespaces + chroot + cgroup v2 = a container
profiled 81 A CPU hot spot and a goroutine leak, found with pprof
Dockerfile, unit, manifest 82 Shipping a Go service: 15 MB distroless image, systemd, Kubernetes

Generated from real-life-os-guide.md · 8 Oct 2026 16:36