Back to Computing & Systems Foundations Series

Part 3: Linux Fundamentals — Architecture & Philosophy

May 13, 2026 Wasil Zafar 18 min read

How the Linux kernel is structured, how the system boots, and the Unix philosophy that shapes everything from process design to networking — the mental model that makes Linux legible.

Table of Contents

  1. Why Linux Dominates
  2. Kernel Architecture
  3. The Linux Boot Sequence
  4. The Unix Philosophy
  5. The Filesystem Hierarchy Standard
  6. /proc and /sys — The Virtual Filesystems
  7. Exercises
  8. Conclusion & Next Steps

Why Linux Dominates

Linux runs on approximately 96% of the world's top 1 million web servers, nearly 100% of public cloud infrastructure, every Android device, most routers, IoT devices, and supercomputers. When you deploy to AWS, GCP, or Azure, you're deploying to Linux. When you run Docker or Kubernetes, you're relying on Linux kernel features. When you SSH into a server, you're almost always connecting to Linux.

Understanding Linux is not optional for anyone working in modern software infrastructure. The question isn't whether you'll encounter it — it's how deeply you need to understand it. This article gives you the mental model that makes the rest of Linux legible.

Key Insight: Linux is not just an operating system — it's a set of kernel APIs (system calls) that every container, virtual machine, and cloud workload relies on. Docker containers are not magic isolation boxes; they're processes using Linux kernel features (namespaces, cgroups) that have existed since 2008.

Kernel Architecture

The Linux kernel is a monolithic kernel — most OS services (process scheduling, memory management, file systems, device drivers, networking) run in a single large kernel address space in Ring 0. This is in contrast to a microkernel (like QNX or seL4) where most services run as user-space processes, communicating via IPC.

Monolithic kernels have a performance advantage (no context switches between kernel services) but a reliability tradeoff (a bug in any driver can crash the entire kernel). Linux mitigates this via loadable kernel modules (LKMs) — drivers and file system code can be compiled separately and loaded/unloaded at runtime without rebooting.

# View currently loaded kernel modules
lsmod | head -20

# Get info about a specific module
modinfo ext4

# Load a module (requires root)
# sudo modprobe nf_conntrack

# See the kernel version currently running
uname -r        # e.g., 6.8.0-45-generic

# Detailed kernel build info
uname -a

# View kernel compile-time configuration (what features are built in vs modular)
zcat /proc/config.gz 2>/dev/null | grep CONFIG_EXT4 || \
cat /boot/config-$(uname -r) | grep CONFIG_EXT4

Key Kernel Subsystems

Linux Kernel Architecture
flowchart TD
    subgraph US["User Space"]
        A["Applications, Shells, Daemons, System Libraries (glibc)"]
    end
    subgraph KS["Kernel Space (Ring 0)"]
        SC["System Call Interface\n(openat, read, write, fork, mmap, ioctl...)"]
        PM["Process Scheduler\n(CFS — Completely Fair Scheduler)"]
        MM["Memory Manager\n(Virtual memory, page tables, OOM killer)"]
        VFS["Virtual File System\n(ext4, tmpfs, procfs, sysfs, overlayfs)"]
        NET["Networking Stack\n(TCP/IP, netfilter, socket API)"]
        DD["Device Drivers\n(block, char, network, USB, GPU)"]
        KM["Kernel Modules\n(Loadable drivers, FS, net filters)"]
    end
    subgraph HW["Hardware"]
        CPU["CPU"] --- RAM["RAM"] --- DISK["NVMe/HDD"] --- NIC["NIC"] --- USB["USB/Other"]
    end

    US <-->|syscall / sysret| SC
    SC --> PM & MM & VFS & NET
    VFS & NET --> DD
    DD --> HW
    KM -..->|extend| DD & VFS & NET

    style US fill:#f8f9fa,stroke:#3B9797
    style KS fill:#132440,color:#fff,stroke:#3B9797
    style HW fill:#16476A,color:#fff,stroke:#3B9797
                            
SubsystemRoleKey Concepts
Process SchedulerDecides which process runs on which CPU core at what timeCFS (Completely Fair Scheduler), run queues, nice values, cgroups CPU limits
Memory ManagerVirtual memory, page allocation, OOM handlingPage tables, TLB, slab allocator, OOM killer, HugePages
VFS (Virtual File System)Uniform file/directory API over many storage backendsinodes, dentries, superblock, file operations struct
Networking StackTCP/IP implementation, socket API, firewallsk_buff (socket buffer), netfilter hooks, iptables, eBPF
Device DriversHardware abstraction for block, char, and network devicesIRQ handlers, DMA, MMIO, device tree
IPC SubsystemInter-process communication primitivespipes, FIFOs, Unix sockets, POSIX message queues, shared memory, futex

The Linux Boot Sequence

Understanding the boot sequence is invaluable for debugging startup failures, configuring services, and understanding container/VM startup times. The sequence from power-on to a usable shell has six stages:

Linux Boot Sequence
sequenceDiagram
    participant FW as UEFI/BIOS Firmware
    participant BL as Bootloader (GRUB2)
    participant KN as Linux Kernel
    participant ID as initramfs
    participant SD as systemd (PID 1)
    participant SV as Services & Shell

    FW->>FW: POST — test hardware, find boot device
    FW->>BL: Load GRUB2 from EFI partition
    BL->>BL: Show boot menu, apply kernel cmdline params
    BL->>KN: Load kernel image + initramfs into RAM
    KN->>KN: Decompress self, detect hardware, init subsystems
    KN->>ID: Mount initramfs as root, run /init script
    ID->>ID: Load drivers needed to mount real root partition
    ID->>KN: Switch root to real disk partition (pivot_root)
    KN->>SD: Execute /sbin/init = systemd (PID 1)
    SD->>SD: Parse unit files, calculate dependency graph
    SD->>SV: Start services in parallel (networking, sshd, etc.)
    SV->>SV: Login prompt available
                            
# View boot messages from the kernel ring buffer
dmesg | head -50
dmesg --level=err,warn  # Show only errors and warnings

# View systemd boot timing (which services took how long)
systemd-analyze
systemd-analyze blame | head -20   # Slowest units first
systemd-analyze critical-chain     # Critical path to reaching default target

# View kernel command line passed by bootloader
cat /proc/cmdline

# See GRUB config
cat /boot/grub/grub.cfg | grep menuentry | head -5

systemd — The Init System

When the kernel starts PID 1 (systemd), it becomes responsible for bringing up every service the system needs. systemd uses unit files to describe resources (services, mount points, sockets, timers) and calculates a dependency graph to start them in the correct order, with maximum parallelism.

# List all active systemd units
systemctl list-units --type=service --state=active

# Inspect a service unit file
systemctl cat sshd.service   # or ssh.service on Debian/Ubuntu

# Common service management commands
systemctl status nginx
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl enable nginx    # Start on boot
systemctl disable nginx   # Don't start on boot

# View the dependency graph for a service
systemctl list-dependencies sshd.service

# See the current default target (equivalent to old runlevel)
systemctl get-default    # usually "multi-user.target" or "graphical.target"

# View logs for a specific service (systemd's journalctl)
journalctl -u nginx --since "1 hour ago" --no-pager
Container Engineering

Why Containers Don't Run systemd by Default

Docker containers normally run a single application process as PID 1 (not systemd). This is because: (1) systemd tries to manage hardware, D-Bus, cgroups mounting, and other system-level things that conflict with the container runtime's ownership of these resources; (2) most container workloads are single services that don't need an init system; (3) systemd as PID 1 has different signal handling than expected by Docker (e.g., it doesn't forward SIGTERM to child processes by default).

When you do need systemd in a container (e.g., for testing Ansible roles or running legacy multi-service applications), use the --privileged flag and mount the cgroups — but understand you're breaking the single-process container model.

DockerPID 1init

The Unix Philosophy

Linux inherits its design from Unix, and the Unix philosophy — articulated by Doug McIlroy in 1978 — continues to shape how Linux tools are built and composed:

The Unix Philosophy (McIlroy's version):
  1. Write programs that do one thing and do it well.
  2. Write programs to work together.
  3. Write programs that handle text streams, because that is a universal interface.

This explains why Unix/Linux tools are designed the way they are: grep just filters lines, sort just sorts them, wc just counts words/lines. Power comes from composition via pipes: cat /var/log/nginx/access.log | grep "500" | awk '{print $1}' | sort | uniq -c | sort -rn | head -10 — a five-tool pipeline that identifies the top 10 source IPs causing 500 errors, written from primitives in 30 seconds.

Other corollaries of the Unix philosophy that you'll encounter constantly:

  • Everything is a file: Devices (/dev/sda), processes (/proc/1234/), kernel parameters (/sys/kernel/), network sockets — all exposed as filesystem paths you can read, write, and manipulate with standard tools.
  • Silence is success: Well-behaved tools print nothing on success and output errors to stderr. This allows clean chaining — if a command is silent, it succeeded.
  • Small sharp tools: Prefer composing small tools over building large monolithic programs. This is why the Linux command line has thousands of single-purpose utilities.

The Filesystem Hierarchy Standard

Linux follows the FHS (Filesystem Hierarchy Standard) — a convention for where files live. Knowing this lets you find any file on any Linux system without documentation:

DirectoryContentsExamples
/Root — everything hangs off here
/bin, /usr/binUser-facing command binariesls, grep, bash, python3
/sbin, /usr/sbinSystem administration binariesip, mount, fdisk, sysctl
/lib, /usr/libShared libraries (.so files)libc.so.6, libssl.so
/etcSystem-wide configuration files/etc/passwd, /etc/nginx/, /etc/systemd/
/varVariable runtime data (logs, databases, mail)/var/log/, /var/lib/docker/, /var/run/
/tmpTemporary files (cleared on reboot)Scratch space for programs
/procVirtual FS: kernel/process state (in RAM)/proc/cpuinfo, /proc/1/maps
/sysVirtual FS: hardware/kernel parameters/sys/class/net/, /sys/block/sda/
/devDevice files managed by udev/dev/sda, /dev/null, /dev/tty
/homeUser home directories/home/alice, /home/bob
/rootroot user's home
/optOptional third-party software/opt/google/, /opt/homebrew/
/usr/localLocally compiled/installed software/usr/local/bin/, /usr/local/lib/
/bootKernel images and bootloader filesvmlinuz-6.8.0, initrd.img, grub/

/proc and /sys — The Virtual Filesystems

/proc and /sys are pseudo-filesystems — they don't exist on disk. They're generated by the kernel in RAM and expose live kernel and process state as readable (and sometimes writable) files. They're the primary way to introspect and tune a running Linux system.

# === /proc — process and kernel state ===

# Your current process's info (PID of the running shell)
ls /proc/$$          # cmdline, exe, fd/, maps, mem, net/, status...
cat /proc/$$/status  # Memory usage, UIDs, GIDs, thread count
cat /proc/$$/maps    # Virtual memory map (same as /proc/PID/maps)

# System-wide info
cat /proc/cpuinfo    # CPU model, cores, features (SSE4.2, AVX, etc.)
cat /proc/meminfo    # RAM usage: MemTotal, MemFree, Buffers, Cached...
cat /proc/loadavg    # Load averages (1, 5, 15 min) + running/total processes
cat /proc/net/tcp    # Active TCP connections (hex addresses)
cat /proc/sys/kernel/hostname  # Current hostname (readable!)

# Kernel tunable parameters via /proc/sys
cat /proc/sys/vm/swappiness      # How aggressively the kernel swaps (0-100)
cat /proc/sys/net/ipv4/ip_forward # IP forwarding (0=off, 1=on — needed for routing/containers)

# === /sys — hardware and device parameters ===
ls /sys/class/net/                    # Network interfaces
cat /sys/class/net/eth0/speed         # Link speed in Mbps
cat /sys/class/net/eth0/statistics/rx_bytes  # Bytes received
ls /sys/block/                        # Block devices (sda, nvme0n1, etc.)
cat /sys/block/sda/queue/rotational   # 1=HDD, 0=SSD

# Tuning example: disable transparent hugepages (common for databases)
cat /sys/kernel/mm/transparent_hugepage/enabled

Exercises

# Exercise 1: Explore your kernel and loaded modules
uname -r                         # Kernel version
lsmod | wc -l                    # How many modules are loaded?
lsmod | grep "^ext"              # Find the ext4 filesystem module

# Exercise 2: Trace the boot timeline
systemd-analyze
systemd-analyze blame | head -10  # Top 10 slowest services
# Which service takes the most time on your system?

# Exercise 3: Navigate the FHS with purpose
ls /etc/*.conf | head -10        # Config files in /etc
ls /var/log/ | head -10          # Log files
ls /proc/ | grep "^[0-9]" | wc -l  # How many processes are running?

# Exercise 4: Read live system state from /proc
cat /proc/loadavg    # What's the current load average?
cat /proc/meminfo | grep -E "MemTotal|MemFree|Buffers|Cached"
# Free memory = MemFree + Buffers + Cached (Linux caches aggressively)

# Exercise 5: Inspect a systemd service
systemctl status sshd 2>/dev/null || systemctl status ssh
# Note: active/inactive state, PID, memory usage, recent log lines

Conclusion & Next Steps

The Linux kernel is a monolithic, modular OS kernel whose architecture — process scheduler, memory manager, VFS, networking stack, and device drivers — maps directly to the system calls you've already seen in Part 1. The Unix philosophy of small, composable, text-streaming tools gives Linux its characteristic power through composition. The FHS makes any Linux system navigable, and /proc//sys make the live system inspectable without any special tools.