sn sysnerdunderstand it from the kernel up
← curriculum map
Operating Systems
Core · ~45 min · 5 labs
map / Concepts / Operating Systems
Concepts Core ~45 min

Operating Systems

An operating system is just a program that manages other programs and hands out the hardware. Once you can see that happening, containers and schedulers stop being magic.

Q1Watch the syscall boundarywarm-up

Every time a program touches the outside world — a file, the network, the clock — it asks the kernel with a system call. That boundary is where user space ends and the kernel begins.

Task

Run strace on a simple command and count the syscalls it makes.

Verify it yourself
verify
$ strace -c ls /

You get a table of syscalls (openat, read, write, mmap...). Every one is a request to the kernel.

Reveal solution
solution
$ sudo apt install -y strace   # if needed
$ strace -c ls /
Q2See the process treewarm-up

Processes are created by fork (copy) + exec (replace image). Every process has a parent — all the way up to PID 1.

Task

Start a background sleep and find it, its PID, and its parent.

Verify it yourself
verify
$ ps -o pid,ppid,cmd --ppid $$

You see the child sleep with ppid equal to your shell — the fork relationship, made concrete.

Reveal solution
solution
$ sleep 100 &
$ ps -o pid,ppid,cmd --ppid $$
$ pstree -p $$
Q3A socket is just a file descriptorcore

The deepest Unix idea: files, pipes, and sockets are all reached through small integers called file descriptors. 0/1/2 are stdin/stdout/stderr; the kernel tracks the rest per process.

Task

Open a file on fd 3 in your shell, then inspect the shell's open descriptors.

Verify it yourself
verify
$ ls -l /proc/$$/fd

fd 3 is a symlink to the file you opened. This is the same mechanism a network socket uses — it's just an fd too.

Reveal solution
solution
$ exec 3< /etc/hostname
$ ls -l /proc/$$/fd
$ exec 3<&-   # close it again
Sponsored

Reach engineers who read the man page

Native, contextual, no tracking — this is how the curriculum stays free.

Q4Read a process's memory mapcore

Each process sees its own private virtual address space; the kernel maps it onto real physical RAM behind the scenes. The map is readable in /proc.

Task

Print the memory map of a running process and find its heap, stack, and shared libraries.

Verify it yourself
verify
$ cat /proc/self/maps | head

You'll see regions labelled [heap], [stack], and mapped .so libraries — the anatomy of a running program.

Reveal solution
solution
$ cat /proc/self/maps | head -20
Q5Break-and-fix — too many open filesdebug

Every fd costs a slot, and the kernel caps how many a process may hold (ulimit -n). Hit the cap and syscalls fail with EMFILE — a real, common production outage.

Task

In a subshell, lower the fd limit hard, then watch a program fail to open files. Then explain what a real fix looks like.

Verify it yourself
verify
$ bash -c 'ulimit -n 8; for i in $(seq 20); do exec {fd}<>/tmp/f$i || { echo "failed at $i"; break; }; done'

It fails partway with an open-files error. The real fix: raise the soft limit or close leaked fds — never just paper over it.

Reveal solution
solution
# Inspect current limits:
$ ulimit -n
# Raise the soft limit for a session:
$ ulimit -n 4096
What you just built

Processes, file descriptors, virtual memory, syscalls — these four ideas are the vocabulary for everything above. A container is a process; a socket is an fd; an OOM kill is virtual memory hitting a wall. You'll reuse this in every module that follows.