Linux Kernel Learning — Part 1
Overview
Looking at the full landscape of the Linux kernel, one can feel overwhelmed and lost amid the numerous subsystems. One approach is to observe the kernel's functionality from the perspective of Linux's diagnostic (measurement) tools and their functional slices.

Interrupt Subsystem
- Interrupts
hard interruptssoft interrupts- Interrupt nesting
hard interruptscan be nestedsoft interruptscannot be nested
- Differences between
hard interruptsandsoft interruptssoft interruptsare generated by executing interrupt instructions, whereashard interruptsare triggered by peripheral devices.- The interrupt number for
hard interruptsis provided by the interrupt controller; forsoft interrupts, the interrupt number is specified directly by the instruction, without needing an interrupt controller. hard interruptsare maskable, whilesoft interruptsare not maskable.- The
hard interrupthandler must ensure it completes its task quickly, so that the program execution does not wait for a long time; this is called the top half. soft interruptshandle the unfinished work ofhard interrupts, serving as a deferred execution mechanism, and belong to the bottom half.
Other Subsystems
- Schedule
- CFS (Completely Fair Scheduler)
- The default "fair" scheduler class; models an "ideal multi-tasking processor" where every runnable task gets an equal share of CPU.
- Each task accumulates a virtual runtime (
vruntimeinstruct sched_entity); the task with the smallestvruntimeis picked next. - Tasks are kept in a red-black tree keyed by
vruntime, so picking the next task and re-inserting after a timeslice are bothO(log n). SCHED_NORMAL/SCHED_BATCH/SCHED_IDLEtasks are all served by CFS.
- EEVDF (Earliest Eligible Virtual Deadline First)
- Introduced in kernel 6.6 as a new scheduling algorithm intended to eventually replace CFS.
- Each task carries a virtual deadline; the scheduler always runs the task whose deadline is earliest, giving stronger latency guarantees than pure fairness.
- A task that has used less of its time slice gets an earlier deadline, so interactive and latency-sensitive work is favored without a separate "interactive" heuristic.
- Real-time schedulers
SCHED_FIFOandSCHED_RRare fixed-priority real-time classes that always preempt CFS;SCHED_DEADLINEuses EDF with a runtime budget for hard real-time workloads.
- Runqueues and load balancing
- Per-CPU runqueue (
struct rq); periodic load balancing and idle balancing migrate tasks across runqueues to keep all cores busy. - Scheduling classes form a priority chain (stop → deadline → rt → fair → idle); each class decides whether to run its own tasks before deferring to lower classes.
- Per-CPU runqueue (
- Context switch and tick
context_switch()swaps page tables (switch_mm) and CPU register state (switch_to); the scheduler tick (scheduler_tick) updatesvruntimeand may setTIF_NEED_RESCHED.NO_HZ_IDLE/NO_HZ_FULLstop the periodic tick on idle or quiet CPUs to save power and reduce jitter.
- CFS (Completely Fair Scheduler)
- Memory
- Physical memory
- Memory is organized into NUMA nodes (
struct pglist_data), each node into zones (DMA, DMA32, Normal, HighMem) reflecting hardware addressing limits. - The smallest unit is the page (usually 4 KiB), tracked by
struct page(one per physical page, held inmem_map). - The buddy allocator hands out contiguous power-of-two page groups and coalesces freed buddies to fight external fragmentation.
- The slab allocator (
slub/slab/slob) caches frequently allocated kernel objects (task_struct,inode,dentry, …) to avoid buddy-level fragmentation and repeated init.
- Memory is organized into NUMA nodes (
- Virtual memory
- Each process has its own address space described by
struct mm_struct; contiguous logical regions are VMAs (struct vm_area_struct) with their own flags and file backing. - A multi-level page table (PGD → PUD → PMD → PTE) translates virtual to physical addresses; x86-64 and AArch64 typically use 4 levels, with 5-level support for larger address spaces.
- Demand paging: a first access triggers a page fault (
do_page_fault/handle_mm_fault), which maps a zero page, reads from swap, or maps a file. kmallocreturns physically contiguous memory (good for DMA);vmallocreturns virtually contiguous memory that may be physically scattered.- Huge pages (2 MiB / 1 MiB) and Transparent Huge Pages (THP) reduce TLB pressure and page-table walk cost for large mappings.
- Each process has its own address space described by
- Reclaim and OOM
- When free memory shrinks, kswapd reclaims page cache and anonymous pages; zswap / zram compress pages in RAM to cut swap I/O.
- If reclaim cannot free enough memory, the OOM killer selects a victim process (by a badness score) and kills it to keep the system alive.
- Physical memory
- IO
- VFS (Virtual File System)
- The VFS layer gives userspace a single
open/read/write/closeinterface regardless of the underlying filesystem. - Core objects:
struct superblock(a mounted FS),struct inode(a file's metadata),struct dentry(a directory-entry cache that speeds path lookup), andstruct file(an open file instance with its own offset andfile_operations). - The
file_operationstable (open,read,write,ioctl,mmap,release, …) is how a filesystem or device driver plugs its own behavior into the VFS.
- The VFS layer gives userspace a single
- Block layer
- File I/O and filesystem requests become bio structures (
struct bio), each describing one or more contiguous memory-buffer segments to read or write. - BIOs are merged and queued into a request queue; the blk-mq (multi-queue) framework maps submissions to per-CPU or hardware queues for modern fast storage.
- I/O schedulers / algorithms —
mq-deadline,kyber,bfq,none— reorder and merge requests to trade off throughput, latency, and fairness. - The page cache holds recently read file pages; dirty pages are written back to disk by periodic flush threads (
writeback).
- File I/O and filesystem requests become bio structures (
- Memory-mapped and direct I/O
mmapmaps a file directly into a process address space so reads/writes become memory accesses (demand-paged through the page cache).- Direct I/O (
O_DIRECT) bypasses the page cache and DMA-s straight from user buffers to the device, used by databases andqemu.
- VFS (Virtual File System)
- Network
sk_buff(socket buffer)struct sk_buffis the central packet descriptor: it carries the protocol headers, a scatter-gather list of data fragments, and metadata (timestamp, priority, ingress device).- SKBs are allocated from a slab cache and reference-counted; the same
sk_buffis cloned and handed down the stack layers without copying payload.
- NAPI and device polling
- NAPI (New API) starts with interrupt-driven packet receipt, then switches to a polling loop (
poll()) inside a single hard-IRQ to amortize interrupt overhead under high traffic. netif_napi_addregisters a driver's poll function;napi_scheduleraisesNET_RX_SOFTIRQto run it.
- NAPI (New API) starts with interrupt-driven packet receipt, then switches to a polling loop (
- Protocol stack and netfilter
- Ingress: L2 (
netif_receive_skb) → L3 (ip_rcv→ip_route_input) → L4 (tcp_v4_rcv/udp_rcv) → socket buffer → userspace. - Netfilter hooks (
NF_INET_PRE_ROUTING,LOCAL_IN,FORWARD,LOCAL_OUT,POST_ROUTING) are whereiptables/nftablesfilter, NAT, and mangle packets. - Egress:
dev_queue_xmithands a packet to the device; qdisc (queuing disciplines likefq_codel,htb) shape and pace outbound traffic.
- Ingress: L2 (
- eBPF / XDP
- XDP (eXpress Data Path) runs an eBPF program at the earliest point in the driver, before an
sk_buffis even allocated — used for DDoS mitigation, load balancing, and fast forwarding. - TC eBPF attaches to the traffic-control layer for richer in-stack processing.
- XDP (eXpress Data Path) runs an eBPF program at the earliest point in the driver, before an
- Driver
- Character devices
- A character device (
struct cdev) is accessed as a stream of bytes; the driver registers a major/minor number pair and anfile_operationstable. register_chrdev_regionreserves a static major/minor range;alloc_chdev_regionrequests a dynamic one.cdev_addmakes the device live.class_create+device_createpopulate sysfs (/dev,/sys/class/…) soudevcan create device nodes automatically.
- A character device (
- Device model and buses
- The kernel device model is a bus → device → driver tree: a driver (
struct device_driver) registers on a bus (struct bus_type); when a matching device is found,probe()is called. - Platform devices represent devices baked into a SoC (no discoverable bus); device tree (
*.dts) or ACPI describe their resources (MMIO ranges, IRQs). - PCI and USB are discoverable buses with their own core drivers that enumerate devices and match them to function drivers.
- The kernel device model is a bus → device → driver tree: a driver (
- Interrupts and bottom halves in drivers
- A driver requests an IRQ with
request_irq(or the threaded variantrequest_threaded_irq); the top half does the minimal ack + notify work, the rest is deferred. - Bottom-half mechanisms:
tasklet(runs in softirq context on the same CPU),workqueue(runs in process context, can sleep), andthreaded IRQ(a dedicated kernel thread per IRQ).
- A driver requests an IRQ with
- DMA and IOMMU
- DMA lets a device read/write RAM without CPU copies;
dma_alloc_coherentgives a device-accessible, cache-coherent buffer. - The IOMMU (VT-d, SMMU) remaps device-visible "IO virtual addresses" to physical pages, so a device can address scattered memory and is isolated from accessing unrelated RAM.
- DMA lets a device read/write RAM without CPU copies;
- Character devices