How Operating Systems Work: Watch the Kernel, Scheduler and Memory

Diagram of programs asking the kernel for CPU, memory and disk access, with Linux terminal output beside it

To understand how operating systems work, it helps to see the OS as a referee. It is the layer that manages your hardware and serves every running program, deciding who gets the CPU next, where each program's memory lives, and how requests reach the disk. This guide covers four parts: the kernel, system calls, the scheduler and virtual memory. Together they explain almost everything your OS does.

Instead of relying on diagrams, you'll catch each part in action on a real Linux system using a handful of read-only commands. You'll follow the boot hand-off, trace a program's requests to the kernel, watch two processes share one CPU core, look at a private memory map, and learn to read where a slowdown really comes from.

In short
  • The OS sits between programs and hardware so many apps can share one machine safely.
  • Boot is a relay: the bootloader loads the kernel, and the kernel starts PID 1.
  • Programs never touch hardware directly; they ask the kernel through system calls.
  • The scheduler gives each process short CPU slices, and virtual memory gives each a private address space.
  • Use vmstat to find the real bottleneck before buying more RAM or cores.
  1. 0:00Intro
  2. 0:28Get ready to look inside
  3. 1:24Why programs need a referee
  4. 2:14Follow the boot hand-off
  5. 3:13Trace a program's system calls
  6. 4:12Share one core between tasks
  7. 5:11Inspect a process's memory map
  8. 6:09Measure before you upgrade
  9. 7:06Confirm the whole chain works
  10. 7:59Fix the common errors
  11. 8:50Five things the OS does
  12. 9:29An OS is a careful referee

Prepare a Linux system to look inside

This is a hands-on walkthrough, so have a terminal open before you start. By the end, you will have seen each core job of the operating system happen on your own machine. A Linux machine or virtual machine is all you need, and a cloud server or a VirtualBox VM works fine.

Linux is a good choice because it shows its internals openly. The /proc folder isn't stored on disk at all. The kernel generates those files on demand, so reading one is like asking the kernel a question directly. That makes it an ideal place to watch the OS without special tools.

Every command in this guide only observes; nothing changes your system. The worst case is a stray background process, and you'll clean those up near the end. That means you can experiment freely and rerun anything as often as you like.

  • A Linux machine or VM is running
  • Your terminal user has sudo access
  • strace and procps are installed
  • You're comfortable with basic shell commands
  • You'll use sleep as a simple program to watch

Understand why programs need a referee

Your laptop might run a browser, a music player and a dozen background services, yet there is only one set of hardware underneath them all. Every one of those programs wants CPU time, space in RAM and access to the disk. Something has to keep order, and that something is the kernel.

The key rule is that programs never drive devices themselves. If every app talked to the disk on its own, two writes could collide and corrupt a file. Instead, apps ask the kernel, and the kernel puts those requests in a safe order before handing out time, memory and device access.

Sharing safely also means isolation. When one program crashes, the kernel cleans it up and everything else keeps running. This is why you can close a frozen app without restarting your computer. In short, the operating system is what makes multitasking trustworthy.

  • Programs request resources; the kernel grants them
  • Requests to shared devices are put in a safe order
  • A crashing app shouldn't take others down with it

Follow the boot hand-off

The OS starts at boot, and boot happens in stages. A bootloader loads the kernel, the kernel initializes the hardware, and then it starts the first process. You can find evidence of each hand-off with three read-only commands, one for each stage.

First, cat /proc/cmdline shows the line the bootloader passed to the kernel, including which kernel image to load and options such as the root drive. On most Linux systems the bootloader is GRUB. Its only job is to find the kernel on disk, load it into memory and pass along those options.

Next, sudo dmesg piped into head shows the kernel's very first log line, stamped at time zero. Finally, ps for PID 1 should show systemd. Once the kernel has set up the hardware, it launches this single process, and services, login screens and your shell all descend from it. Boot is a relay, not magic.

  • /proc/cmdline names the kernel image the bootloader chose
  • dmesg's first line starts at 0.000000
  • PID 1 is systemd on most modern distributions
cat /proc/cmdline
sudo dmesg | head -n 1
ps -p 1 -o pid,comm

Trace a program's system calls

Once the kernel is running, ordinary programs use it through system calls. The kernel runs in privileged mode, and programs can't do privileged work themselves, so they make a request instead. The strace tool sits between a program and the kernel and prints each system call as it happens, with its arguments and the value the kernel returns.

Create a tiny file with echo hi > hello.txt, then run strace -P hello.txt cat hello.txt. The -P option limits the output to calls involving that file. You'll see openat return file descriptor 3, then read pull in the bytes, then the text itself printed. After that comes close, and finally the program exits with 0.

This shows the two sides of the boundary. In user mode, cat packages a request such as open this file or read these bytes. In kernel mode, the CPU switches into privileged mode, the kernel checks you're allowed, does the work and switches back. Every file, socket and window your apps use passes through this same doorway.

  • openat returns a file descriptor, here 3
  • read reports how many bytes it returned
  • close returns 0 when it succeeds
  • The program ends with exited with 0
echo hi > hello.txt
strace -P hello.txt cat hello.txt

Share one core between two busy tasks

System calls explain how programs ask for help, but something must decide which program runs at all. That is the scheduler. It rapidly switches between processes, giving each one a slice of CPU time. To see it clearly, set up a contest: two processes that never stop working, both locked onto the same core.

Run taskset -c 0 yes > /dev/null & to start a busy loop on core 0 in the background, then run it a second time. Now check them with ps -o pid,psr,pcpu,comm -C yes. Both show 0 under PSR, the core they run on, and each uses about half the CPU.

Behind that split is a simple loop. The first yes runs until a timer tick says its slice has expired. The kernel saves its registers, and the second yes runs. Then the loop repeats. The switches happen so fast that both processes appear to run nonstop, which is how one core can seem to do several things at once.

  • Both yes processes show PSR 0
  • Each %CPU value sits near 50
  • Leave them running for now; you'll stop them later
taskset -c 0 yes > /dev/null &
taskset -c 0 yes > /dev/null &
ps -o pid,psr,pcpu,comm -C yes

Inspect a process's memory map

The scheduler shares time; virtual memory shares space. Each process gets its own address space, which isolates programs from each other. The addresses a program sees aren't real RAM locations. They are virtual, and the kernel translates each one to physical memory behind the scenes.

Start a quiet process with sleep 300 &. The shell prints its process ID, and yours will differ from the example. Then run pmap with that ID and pipe it into head. Each line is a region of virtual addresses: first the program's own code, then the C library, libc.so.6, along with each region's size and permissions.

This privacy is by design. If another program uses the very same address, it reaches its own memory, never sleep's. When sleep reads an address, the CPU looks it up in sleep's page table, which points to a frame in physical RAM. Meanwhile bash goes through its own page table to different frames. As a result, a bad pointer crashes only the program that made it.

  • Use the process ID your own shell printed
  • Expect separate regions for the program and libc
  • Permission flags like r-x mark executable code
sleep 300 &
pmap 5120 | head -n 4

Measure the bottleneck before you upgrade

A common mistake is assuming more RAM or more cores will always fix a slow machine. Bottlenecks vary, so measure first. The vmstat command prints a summary line each second of what the scheduler and memory manager are dealing with, which tells you where the real queue is.

Run vmstat 1 2 and read three groups of columns. r is the number of runnable processes waiting for the CPU. si and so show memory being swapped in from and out to disk. wa is time spent waiting on disk. The us, sy and id columns show user time, system time and idle time.

In the example, r is high, us is near the top, idle is zero and swap stays at zero. That machine is CPU-bound: adding RAM would change nothing, while faster or more cores might. Other problems look different. Steady si and so values point to memory pressure, and high wa means the disk is slow. The right fix depends on which column stands out.

  • High r with no idle time: CPU-bound
  • Steady si and so: memory pressure
  • High wa: a slow disk
vmstat 1 2

Confirm the whole chain works

Now check that everything fits together by following one simple command, cat hello.txt, through every part you've seen. Boot is done, and PID 1 is systemd. The process is mapped into its own address space. It gets a slice and is scheduled on the CPU. It makes a system call, and openat returns 3. Finally, hi is printed in your terminal.

For a quick self-test, rerun the boot commands, the strace line, ps for the yes processes, and pmap. Exact numbers such as process IDs and addresses will differ on your machine, but each output should have the same shape. When you're done, run pkill yes so the busy loops stop using a core. The sleep process ends on its own after five minutes.

  • Each command's output has the same shape as the examples
  • pkill yes stops both busy loops
  • sleep 300 exits by itself after five minutes

Fix the common errors

If something didn't match, a handful of errors catch almost everyone, and each has a quick fix. Notice the pattern: nearly every one is the kernel protecting itself or other processes, which is exactly its job. Most failures come down to permissions, a missing tool, or a process that has already ended.

If the CPU split in the scheduling step looks uneven, that isn't a bug. Other programs may also be scheduled on core 0 and take slices of their own. That's the scheduler being fair to everyone on that core, not just your two test processes.

  • strace: command not found — install strace with apt or dnf
  • dmesg: Operation not permitted — prefix the command with sudo
  • ptrace: not permitted — trace a new command instead, or use sudo
  • pmap: no such process — sleep already finished, so start it again
  • Uneven CPU split — other processes on core 0 are taking slices

Key takeaways

  • The bootloader loads the kernel, and the kernel starts PID 1.
  • Programs ask the kernel for help via system calls, crossing into privileged mode.
  • The scheduler gives each process CPU slices, fast enough to feel parallel.
  • Virtual memory isolates every process through its own page table.
  • Measure the bottleneck before upgrading, because more hardware only helps the part that's stuck.
  • An OS is a careful referee for time, memory and devices.

Frequently asked questions

What does the kernel actually do?

The kernel is the privileged core of the operating system. It initializes hardware at boot and hands out CPU time, memory and device access to programs. It also checks permissions and cleans up after programs that crash.

What is a system call in simple terms?

A system call is a request a program makes to the kernel, such as open this file or read these bytes. The CPU switches into privileged mode, the kernel does the work, and the result goes back to the program. You can watch system calls happen with strace.

How can one CPU core run several programs at once?

It doesn't truly run them at the same moment. The scheduler gives each process a short slice of time, saves its state when the slice ends, and switches to the next one. The switching is so fast that the programs appear to run in parallel.

Why does every process have its own memory addresses?

Virtual memory gives each process a private address space that the kernel maps to physical RAM through page tables. Two programs can use the same address and still reach different memory. This isolation means a bad pointer only crashes the program that made it.

Will more RAM make my slow computer faster?

Only if memory is the bottleneck. Running vmstat shows the answer: steady swapping points to memory pressure, high wa points to a slow disk, and a high run queue with no idle time means the CPU is the limit.

Are these Linux commands safe to run?

Yes. Every command in this guide only reads information and doesn't change your system. The only leftovers are the background yes processes, which you stop with pkill yes.

Watch the full video on YouTube →

Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
Ad