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