LearnThatStack Ace your next interview

Operating Systems

Linux commands and C system calls Checked Oct 2026 26 code snippets

The model

  • The kernel runs in kernel mode, where it can touch any memory or device. Your program runs in user mode. The only ways into the kernel are a system call, a fault or an interrupt.
  • A process owns a private address space and its open files. Its threads share that memory, and each thread has its own stack and registers.
  • The MMU translates each virtual address using the kernel's page tables. The TLB caches recent translations. A missing page raises a page fault.
  • The scheduler gives each core to one thread at a time. A timer interrupt lets it take the core back, and each switch leaves the next thread with cold caches.
  • A TLB hit costs about a cycle, a syscall hundreds, a context switch microseconds. A major fault waits on storage, from microseconds on SSD to milliseconds on disk.
Your programuser modeCPU and MMUhardwareKernelkernel modeDisk and devicesstorage, networkload, store TLB hitsyscall read, writepage fault not mappedtimer tick interruptread page major faultreturn or switch
A load or store that hits the TLB never involves the kernel. A syscall, a page fault or a timer tick traps into it. A major fault also waits on the disk.

User mode & the kernel

how your code gets the OS to act

System calls, traps and interrupts

Ask the OS to read a file or open a socketMake a system call. The CPU switches to kernel mode, runs kernel code, then switches back.
Know what a system call costsHundreds of cycles, to switch modes and save and restore registers.
Say how a syscall gets into the kernelA syscall instruction jumps to an entry point the kernel set at boot.
Tell a trap from an interruptA trap comes from the instruction that's running. Hardware raises an interrupt at any moment.
Count the syscalls a program makesstrace -c ./app

TipA page fault reruns the instruction that faulted. A syscall returns to the next one.

TrapYou can't jump to a kernel address. Code picks a service by number, and the CPU enters only at the kernel's fixed entry point.

Monolithic kernel or microkernel

Run the whole OS in kernel spaceA monolithic kernel, like Linux or FreeBSD. A service costs one syscall.
Run drivers and file systems as user processesA microkernel, like QNX, MINIX 3 or L4. Each request is IPC to a server and back.

TipA microkernel pays in context switches, but a crashed driver can often restart without a reboot. Windows NT and Apple's XNU are hybrids.

Processes & threads

what runs, and what it shares

Processes

Define a processA running program with its own memory, open files and one or more threads.
List what the OS tracks for each processIts process control block holds the PID, registers, program counter, memory map, open files, parent, priority and state.
Name the states a process moves betweenRunning, ready to run, or waiting on something like I/O.
Stop and inspect a running processgdb -p <pid>Debuggers use ptrace. A breakpoint swaps in a trap byte, int3 on x86.

TrapA debugger changes the timing, so race bugs often stop reproducing under it.

Process or thread

Run work in separate processesEach gets its own memory, so a crash usually stays in one. Talking needs pipes or sockets.
Run work as threads in one processThey share the heap and globals, so data passes as a pointer. Each has its own stack.
Isolate untrusted or crash-prone workUse processes. Browsers sandbox their tabs this way.
Run CPU-bound Python in parallelUse processes. The default build's GIL lets one thread run Python at a time.
Explain why a thread is cheaper to startIt reuses the address space. A process needs new page tables and a descriptor table.

TipCPython 3.13 added an optional free-threaded build without the GIL.

TrapOne thread's bad write can corrupt data every other thread uses.

User-level and kernel-level threads

Let the kernel schedule every threadKernel-level threads. Each Linux pthread is one, a one-to-one model.
Switch threads without a syscallUser-level threads. If the kernel sees only one thread, one blocking call stalls them all.
Run many light threads on a few kernel threadsMany to many, like Go's goroutines and Java 21 virtual threads.

TrapUser-level threads on one kernel thread never use two cores at once, however many you create.

Fork, exec & zombies

start programs, and clean up after them

Run a program with fork and exec

Copy the current processfork()It returns 0 in the child and the child's PID in the parent.
Replace this process with a new programexecvp(file, argv)Same PID, new code. It returns only if it fails.
Collect a child's exit statuswaitpid(pid, &status, 0)
Say what happens when you run a commandThe shell forks, the child execs, the dynamic linker loads libraries, then main runs.
Explain why fork and exec are separate callsIn between, the child can redirect files, change directory or drop privileges.

TrapForking a threaded program copies only the calling thread. A lock another thread held stays locked in the child.

Copy-on-write after fork

parentchildpage Apage B
after forkParent and child map the same pages, all marked read-only.
parentchildpage Apage BB copy
child writes BThe write faults, so the kernel copies B for the child. The faded line is the old mapping.
Explain why fork doesn't copy all the memoryParent and child share pages marked read-only. The first write faults and copies that page.
Know what a copy-on-write fault costsA minor fault plus a copy of one page.
Explain why fork is slow for a huge processIt still copies the page tables. Tens of gigabytes take milliseconds.
Launch a helper from a huge processUse posix_spawn or vfork. They skip copying the address space.

TipCOW saves the most when the child calls exec at once, because exec throws the memory away.

Zombies and orphans

Define a zombieA child that exited before its parent called wait. It holds no memory, only its exit status and PID.
Define an orphanA child whose parent died first. init, PID 1, adopts it and reaps it.
Reap every child that has exitedwhile (waitpid(-1, &st, WNOHANG) > 0) {}Loop in a SIGCHLD handler. Two exits can arrive as one signal.

TrapA server that forks and never reaps fills the process table. Then nothing on the machine can fork.

CPU scheduling

who runs next, and what a switch costs

What the scheduler does

Say what the scheduler decidesWhich ready thread runs next on each core, in short time slices.
Tell preemptive from cooperative schedulingPreemptive takes the CPU back on a timer tick. Cooperative waits for the task to yield.
Say how cooperative scheduling failsOne task that loops forever or blocks freezes everything.
Keep thousands of threads fairTrack each thread's virtual runtime in a per-CPU red-black tree. Picking one is O(log n).
Name Linux's scheduler since 6.6EEVDF. It runs the eligible thread with the earliest virtual deadline.

TipCooperative scheduling still wins inside one process, where you control every task.

FCFS, shortest job first and round robin

FCFSABCSJFBCARRABCAtime

Long job A arrives just before short jobs B and C, the dark bars. FCFS makes B and C wait. SJF runs them first. RR is round robin, 2 units a turn.

Run jobs in arrival orderFCFS. Nothing starves, but short jobs wait behind a long one.
Cut the average waitShortest job first. It needs run times up front and can starve long jobs.
Give every job a turnRound robin. A long slice acts like FCFS, and a tiny one wastes time switching.

TipAging stops starvation. It raises a job's priority the longer it waits.

Context switches

Say what a context switch doesIt saves one thread's registers and program counter, then loads the next one's.
Know what the switch itself costsMicroseconds, for the save, the restore and picking the next thread.
Name the bigger, hidden costCold caches. The new thread misses to RAM again and again until its data loads.

TrapProfilers rarely blame the switch. The cache refill shows up spread over thousands of later instructions.

Stack, heap & malloc

where a program's data lives

A process's memory layout

Name the regions from low addresses to highRead-only code, then data, BSS, the heap and mapped libraries. The stack sits near the top.
Say which way the heap and stack growThe heap grows up and the stack grows down, into the gap between them.
Tell the data segment from BSSData holds globals that start with a value. BSS holds globals that start at zero.
See a live process's memory mapcat /proc/<pid>/maps

TrapA pointer into a returned stack frame soon reads another call's data. One into freed heap may still look fine.

Stack or heap

Store small data that dies with the callUse the stack. Returning frees the frame at once.
Store data of unknown size, or that outlives the callUse the heap. It's slower, can fragment, and leaks if you never free it.
Explain why the stack has a fixed limitThe stack pointer moves through one reserved range, with other mappings around it.
See the main thread's stack limitulimit -sOften 8 MB. Deep recursion hits it long before RAM runs out.
Turn a stack overflow into a clean crashA guard page with no access sits past the end. Touching it raises SIGSEGV.

TrapA huge local array can jump past the guard page. Compilers add stack probes so it can't.

How malloc and free work

Allocate a small blockmalloc cuts it from a pool it got with brk or mmap. Usually no syscall.
Say whether free returns memory to the OSUsually not. The block goes on a free list for the next malloc.
Get memory that free hands back at onceBig requests the free list can't fill get their own mapping, from 128 KB by default. free unmaps them.

TipThe heap shrinks only from its top, so one live block there pins everything below it.

TrapRSS stays high after free. From outside, a leak and an allocator holding freed memory look alike.

Virtual memory & the TLB

how an address becomes a place in RAM

Virtual memory

Say what address space a process seesA private range from near zero. The OS maps it onto RAM, and unused pages can wait on disk.
Explain why each process gets its ownIsolation. Its map has no entries for other processes' pages.
Check the page sizegetconf PAGESIZEUsually 4 KB.
Tell paging from segmentationPages are fixed-size and mean nothing to the program. Segments are variable-size parts, like code or stack.

TipSegments leave gaps between them, external fragmentation. Pages waste their unused end, internal fragmentation.

Address translation and the TLB

Say who translates each addressThe MMU, in hardware. It splits off the page number and walks the page tables.
Translate a page you used recentlyA TLB hit, about one cycle.
Translate a page the TLB doesn't holdThe MMU walks the page tables, one memory read per level. That's tens to hundreds of cycles.
Say why a huge working set runs slowThe TLB holds a few thousand entries at most. Past that, misses spike.
Explain why page tables stay smallThe table is a tree. The kernel builds only the branches a process uses.
Explain why munmap slows down with more coresA TLB shootdown. The kernel interrupts every core that may cache the entry and waits for all.

TrapA switch to another process flushes the TLB, unless the CPU tags entries by process.

Huge pages and NUMA

Cover more memory with each TLB entryUse huge pages, 2 MB or 1 GB. A 2 MB page covers 512 small ones.
Say when huge pages pay offBig regions hit at random, like database buffers and JVM heaps.
Know what memory on another socket costsOften 1.5 to 2 times a local access, over shared bandwidth.
Keep a process and its memory on one nodenumactl --cpunodebind=0 --membind=0 ./appLinux puts a page on the node that first writes it.

TrapTransparent huge pages can stall a thread while the kernel compacts memory. Measure before you turn them on.

Page faults & low memory

when a page isn't in RAM, or RAM runs out

Page faults

Say what a page fault isYour program touched a page that isn't in RAM. Usually that's normal, since pages load on first touch.
Say when a fault kills the processWhen no valid page exists, like a null pointer. That's a segmentation fault.
Know what a minor fault costsMicroseconds. The page is already in RAM, or needs zero-filling.
Know what a major fault costsThe kernel reads the page from disk. Tens to hundreds of microseconds on SSD, milliseconds on a spinning disk.

TrapA high fault count alone isn't a problem. Most are minor first-touch faults, so watch the major ones.

Demand paging and cold pages

Explain why a program doesn't load all at oncePages load on first touch. Launch stays fast, and code you never run never loads.
Explain a p99 spike with a clean p50One request touches a cold page and faults. Nothing in the source shows it.
Keep a hot path from faultingmlock(addr, len)Lock the pages in RAM, or touch them all before you serve traffic.

TrapA fresh allocation faults too. The kernel zero-fills each page on first touch.

Thrashing

Spot thrashingWorking sets exceed RAM, so the machine spends its time swapping pages, not running code.
Stop thrashingRun less at once, or add RAM. Cap the requests in flight.
Confirm the machine is swappingvmstat 1Nonzero si and so columns mean pages are moving to and from swap.
Find the process using the most memoryps -eo pid,rss,maj_flt,cmd --sort=-rss

TrapBusy CPU and disk can look like a reason to queue more work. More load makes thrashing worse.

Overcommit, the OOM killer and eviction

Say why malloc succeeds past free RAMLinux overcommits. It backs a page only on its first write.
Say what happens when RAM runs outThe OOM killer scores processes, mostly by memory use, and kills the top one.
Check whether the OOM killer struckdmesg -T | grep -i oom
Say how the kernel picks a page to evictApproximate LRU. Hardware sets a referenced bit, and the kernel clears it as it scans.

TipClean pages evict for free. A dirty page needs a disk write first.

TrapThe OOM killer may kill a process that didn't cause the shortage.

Files & I/O

descriptors, buffers and the page cache

File descriptors

Say what a file descriptor isA small integer naming an open file, socket, pipe or device.
Name the three every process starts with0 is stdin, 1 is stdout, 2 is stderr.
List a process's open descriptorsls -l /proc/<pid>/fd
See the soft and hard limitsulimit -Snulimit -HnA process can raise its soft limit up to the hard one. fs.file-max caps the whole system.

TipA shell redirects output by pointing descriptor 1 at a file before it runs the program.

TrapEMFILE means a process hit its limit. Raising the limit only delays a leak.

Buffered I/O

Write one byte per callEach call is a syscall, hundreds of cycles to move one byte.
Batch small writesCollect bytes in a user-space buffer and flush kilobytes in one call.
Push buffered data to the kernelfflush(fp)A crash loses anything still in your buffer.

Trapfflush hands data to the kernel, not the disk. Only fsync makes it durable.

The page cache and fsync

Write to a filewrite copies into the page cache and returns. The kernel writes it to disk later.
Make a write survive a crashfsync(fd)It waits until the data and metadata reach storage.
Make a new file's name survive a crashAlso fsync the directory that holds it.
Bypass the page cacheopen(path, O_RDWR | O_DIRECT)Databases with their own buffer pool do, so data isn't cached twice.

Tipfdatasync skips metadata a read doesn't need, like the modification time, to save a seek.

TrapA crash after write returns but before writeback loses the data with no error.

mmap and sendfile

Read a file as memorymmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0)Pages load through faults, with no read calls and no copy.
Choose mmap over readFor random access into a big file. For a straight scan, read is as fast.
Map a file bigger than RAMIt works on 64-bit. The kernel drops clean pages and reads them back later.
Send a file to a socket without copyingsendfile(sock, fd, NULL, count)The NIC reads straight from the page cache. read plus write copies twice through your buffer.

TipWith sendfile your code never sees the bytes. To encrypt them, read them into user space or use kernel TLS.

TrapA disk error on a mapped page arrives as a SIGBUS signal, not an error return.

Blocking I/O, non-blocking I/O and epoll

Read with the simplest codeBlocking I/O. The thread sleeps until data arrives.
Read without waitingNon-blocking I/O. It returns at once, often with EAGAIN, and you retry later.
Watch 100,000 connectionsepoll_wait(epfd, events, maxevents, timeout)Register once. Each call returns only the ready descriptors.
Say why select fails at 100,000 connectionsIt rescans every descriptor each call, and stops at FD_SETSIZE, 1024.

TipA thousand idle blocking connections means a thousand parked threads.

TrapIn edge-triggered mode, drain each socket fully, or you wait for an event that already fired.

Signals & IPC

how processes interrupt and talk to each other

Signals

Say what a signal isA short async message from the kernel. Ctrl-C sends SIGINT.
Name the ways a process can respondIgnore it, take the default action, or run a handler.
Stop a process, politely then by forcekill -TERM <pid>kill -KILL <pid>SIGTERM can be caught for cleanup. Nothing can catch SIGKILL.
Say what a handler may callOnly async-signal-safe functions, like write and _exit. No printf or malloc.
Write a safe handlervolatile sig_atomic_t stop = 0;Set the flag in the handler, then do the work in the main loop.

TrapA handler that calls malloc while malloc holds its lock deadlocks the process.

Talk between processes

Stream bytes one wayA pipe, like ls | grep.
Talk both ways, on one machine or across a networkA socket.
Keep message boundariesA message queue. The reader gets whole messages.
Share data with no copiesShared memory. You coordinate access with locks or semaphores.
Know what a message through the kernel costsA syscall on each side and two copies, in and out.

TrapWith shared memory, nothing makes the reader wait for whole data. Without a lock or semaphore, it can read a half-written update.

Found this useful? Pass it on.
Pro · $10/mo

This sheet stays free. With Pro, you can:

  • Every answer on this sheet. Read the full answer to all 56 questions it links, not just the 7 free ones.
  • My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
  • PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
  • The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.