Kernel Startup

After GRUB loads the kernel into RAM and jumps to it, an enormous amount of initialization happens before your first process starts. This phase is entirely kernel code — no userspace, no shell. Here's what the kernel does to prepare the system.

The Kernel is Compressed

What is vmlinuz? The vmlinuz file in /boot/ is a compressed kernel image. The "z" suffix means gzip compression (or nowadays zstd). GRUB loads this compressed file into RAM, then a small decompressor in its header runs first and unpacks the actual kernel code in-place.
$ ls -lh /boot/ -rw-r--r-- 1 root root 13M vmlinuz-6.2.0-39-generic ← compressed kernel -rw-r--r-- 1 root root 79M initrd.img-6.2.0-39-generic ← initramfs # The real kernel would be much larger uncompressed (~70MB+)

Early Architecture Setup

Once decompressed, the kernel starts in architecture-specific assembly code (arch/x86/boot/ for x86-64). It does:

  • Switch to protected/long mode: x86 CPUs start in 16-bit real mode; the kernel switches to 64-bit long mode immediately.
  • Set up page tables: Maps the kernel's own virtual address space before enabling the MMU.
  • Interrupt Descriptor Table (IDT): Sets up the table telling the CPU what code to run for each interrupt/exception (page fault, divide by zero, etc.).
  • Identify CPU features: CPUID instruction reveals what the CPU supports (SSE, AVX, etc.).

Initializing Core Subsystems

Then the kernel initializes its major subsystems in a defined order:

start_kernel() in init/main.c: setup_arch() → CPU, memory map, ACPI mm_init() → Memory manager, buddy allocator sched_init() → Process scheduler (CFS) rcu_init() → Read-Copy-Update locking init_IRQ() → Interrupt handling time_init() → Timers and clock sources console_init() → Early console (you see output now) rest_init() → Create kthreadd (PID 2) and init (PID 1)

PID 0 and PID 1

What is PID 0? The kernel itself runs as the "idle process" (PID 0, also called the swapper). It runs whenever no other process is runnable — it executes the CPU's hlt instruction to save power. You won't see it in ps output.

From rest_init(), the kernel forks two threads:

  • PID 1 — runs /sbin/init (or systemd). This is the first userspace process and the ancestor of all other processes.
  • PID 2 — kthreadd, the kernel thread daemon. All kernel threads are created from here.

Hardware Detection

The kernel doesn't probe hardware blindly — it uses structured discovery mechanisms:

  • ACPI (Advanced Configuration and Power Interface): Firmware provides a table describing all hardware. Kernel reads this to discover CPUs, PCI devices, power management.
  • Device Tree: On ARM/embedded systems (not x86), a flat binary structure describes hardware topology.
  • PCI enumeration: Kernel walks the PCI bus and finds connected devices.
# See kernel boot messages (hardware detection output) dmesg | head -100 # See ACPI info dmesg | grep -i acpi # See detected PCI devices lspci