Chapter 2 • Free Linux kernel development course
The Linux Kernel Source Tree
How tens of millions of lines of C and Rust are organised — and why every kernel developer must understand this layout
~34 M
Lines of Code (2025)
7.0
Latest Stable Kernel
C + Rust
Primary Languages
Free
This Course
Topics covered in this free Linux kernel programming lecture
kernel.org download
kernel version Makefile
free Linux kernel development course
free Linux device drivers course
kernel source layout
Rust in Linux kernel
free embedded systems course
What You Will Learn
This lecture is part of EmbeddedPathashala’s free Linux kernel programming course — a structured, beginner-friendly path into Linux kernel development and Linux device driver writing. By the end of this lecture you will be able to:
- Explain what the Linux kernel source tree is and why its organisation matters
- Download the Linux kernel source from kernel.org using both tarball and git methods
- Read the exact kernel version directly from the source code
- Understand the first-level directory layout and what each area is responsible for
- Explain the significance of Rust being added to the kernel since version 6.1
📌 Prerequisites
Before this lecture you should have completed Lectures 1–7 in this free Linux kernel development course, covering basic Linux command-line usage, the role of the kernel, and how user space and kernel space are separated. Familiarity with the ls, cd, head, and grep commands is assumed.
What Is the Linux Kernel Source Tree?
The Linux kernel source tree is the complete, structured collection of source code files that — when compiled — produces the Linux kernel binary. Think of every capability Linux has: scheduling processes, managing memory, talking to storage devices, handling network packets, controlling a GPIO pin on an embedded board. Every single one of these capabilities is written in source code that lives inside this one folder hierarchy.
When developers talk about “the kernel source” they mean this tree. When companies ship embedded Linux products, a copy of this tree (sometimes modified) is what gets compiled for that product. Understanding where things live inside this tree is the starting point for all serious Linux kernel development, Linux device driver writing, and embedded Linux work.
💡 Real-World Analogy — The Architect’s Blueprint Set
Think of a large building under construction. The contractor has a complete set of blueprints — electrical plans, plumbing diagrams, structural drawings, interior layouts. Each type of plan is in its own labelled folder. The Linux kernel source tree works the same way. The finished building is the running kernel; the blueprint folder set is the source tree. You do not need to read every blueprint to walk inside the building, but a kernel developer absolutely must know which folder holds which plan.
How Big Is the Linux Kernel Source Tree?
The Linux kernel source tree has grown steadily since Linus Torvalds released version 0.01 in 1991. Here is how the size has changed across the versions most relevant to this free Linux kernel development course:
| Kernel Version | Year | Approx. Disk Size | Key Change |
|---|---|---|---|
| Linux 5.4 LTS | 2019 | ~1.0 GB | ~20 million SLOCs, long-term support |
| Linux 6.1 LTS | 2022 | ~1.2 GB | Rust language support added |
| Linux 6.6 LTS | 2023 | ~1.3 GB | EEVDF scheduler, more Rust drivers |
| Linux 7.0 (current) | 2025–26 | ~1.5+ GB | Rust fully stable, ~34 million+ SLOCs |
💡 Why Is the Compiled Kernel Much Smaller Than the Source?
The source tree contains code for every CPU architecture (x86, ARM, RISC-V, MIPS, and more), every supported device driver, all filesystems, and every optional feature. When you build a kernel you use a configuration file (.config) that selects only the features your specific system needs. Everything not selected is not compiled. The source is the complete universe of possibilities; the compiled image is just the chosen subset for one system.
How to Get the Linux Kernel Source — Two Methods
The official home for Linux kernel source code is kernel.org. Every stable, LTS, release-candidate, and mainline kernel version is published there. There are two practical ways to get the source onto your development machine.
Method 1 — Tarball Download (Recommended for Beginners)
A tarball is a compressed archive of the complete source tree for one specific kernel version. This is the easiest starting point for a free Linux kernel development course because it is a clean, known snapshot.
Downloading the Kernel Source as a Tarball
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz# It is good practice to verify the signature before extracting
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.sign# Extract the tarball into your home directory
tar -xvf linux-6.6.tar.xz# Enter the source tree
cd linux-6.6
# Confirm the top-level contents
ls
Method 2 — Git Clone (For Active Development)
If you plan to write patches, track kernel history, or switch between kernel versions regularly, cloning via git is the right approach. Be warned: the full clone includes the complete commit history going back to 2005, which makes it several gigabytes.
Cloning the Kernel Source with Git
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git# Shallow clone — just the latest commit, much faster (~200 MB)
git clone –depth=1 \
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git# After cloning, enter the tree
cd linux# Check which branch you are on
git log –oneline -5
| Aspect | Tarball | Git Clone |
|---|---|---|
| Download size | ~100–150 MB compressed | 3–4 GB (full) / ~200 MB (shallow) |
| Version switching | Download new tarball each time | git checkout v6.6 |
| Patch submission | Not practical | Native — git format-patch, git send-email |
| Best for | Learning, one-time builds, this course | Active kernel developers, upstreaming |
Reading the Kernel Version Directly from the Source
Once you have the Linux kernel source tree on disk, one of the first things you will want to do is confirm exactly which version you downloaded. You do not need to build anything — the version is declared right at the top of the root-level Makefile.
Reading the Version from the Top-Level Makefile
head -10 Makefile# Output for kernel 6.6:
# SPDX-License-Identifier: GPL-2.0
# VERSION = 6
# PATCHLEVEL = 6
# SUBLEVEL = 0
# EXTRAVERSION =
# NAME = Pinguino Sincero# Or use the built-in make target — no build required
make kernelversion
# Output: 6.6.0
Each variable in those first lines has a specific meaning:
How to Read a Linux Kernel Version Number
| | | |
VERSION | SUBLEVEL |
(6) PATCHLEVEL EXTRAVERSION
(6) (-rc2 or empty)VERSION = Major version. Changes extremely rarely (5 -> 6 took years).
PATCHLEVEL = Minor version. A new one releases roughly every 2 months.
SUBLEVEL = Stable patch number. Increments with each bug-fix release.
EXTRAVERSION= Empty on final stable release. “-rc1” through “-rc8” during
testing. Distros add their own suffix (e.g. “-generic”).So “6.6.35” = major 6, minor 6, stable patch 35.
And “6.6.0-rc4” = release candidate 4 before the 6.6 final release.
🎉 What is the NAME field?
Each kernel release gets a fun, often absurd nickname picked personally by Linus Torvalds. Kernel 5.4 was called “Kleptomaniac Octopus”. Kernel 6.1 was “Tantric Tasmanian Tiger”. Kernel 6.6 was “Pinguino Sincero”. These names have no technical meaning but they do make version discussions a bit more memorable.
First Look at the Linux Kernel Source Tree Layout
When you run ls inside the downloaded kernel source directory, you will see something like the listing below. We are looking at the root of the source tree — everything at the first level. Notice there are both directories (subsystems) and a handful of important files.
Root of the Linux 6.6 / 7.0 Kernel Source Tree
$ ls linux-6.6/
arch/ block/ certs/ crypto/ Documentation/
drivers/ fs/ include/ init/ io_uring/
ipc/ kernel/ lib/ LICENSES/ mm/
net/ rust/ samples/ scripts/ security/
sound/ tools/ usr/ virt/
COPYING CREDITS Kbuild Kconfig
Makefile README MAINTAINERS
Compared to older kernel 5.x sources, two brand-new top-level entries are visible here:
🚀 rust/ — New in kernel 6.1, stable in kernel 7.0
This directory did not exist in kernel 5.x. It contains the Rust programming language infrastructure for the kernel — the abstractions, bindings, and helper code that allow new kernel components to be written in Rust. As of Linux 7.0 (2025), Rust is no longer experimental. Rust-written drivers covering PCI enumeration, interrupt handling, DMA, and platform devices are fully production-grade.
⚡ io_uring/ — Promoted to top-level in Linux 5.1+
The io_uring subsystem is Linux’s modern high-performance asynchronous I/O interface. It uses shared ring buffers between user space and the kernel to allow applications to submit and receive I/O results without making a system call per operation. It has grown so central to Linux performance that it now occupies its own top-level directory.
First-Level Overview — How Directories Are Grouped
Even before you open any individual directory, you can group the root-level folders into clear categories. This mental model will guide you every time you need to find something in the Linux kernel source tree.
Linux Kernel Source Tree — Grouped by Purpose
kernel/ Core: scheduler, signals, locking, modules, cgroups, tracing
mm/ Memory management: pages, virtual memory, OOM killer
fs/ Filesystems: VFS abstraction + ext4, btrfs, FAT, NFS, f2fs
block/ Block I/O layer: page cache, I/O schedulers
ipc/ Inter-process communication: pipes, queues, semaphores
init/ Kernel startup — contains start_kernel() (the kernel’s main())GROUP 2 — HARDWARE AND DRIVERS
arch/ CPU-architecture-specific code: x86, arm64, riscv, mips
drivers/ Device drivers — the LARGEST directory in the whole tree
sound/ ALSA audio subsystem
virt/ Virtualisation: KVM hypervisorGROUP 3 — NETWORKING AND SECURITY
net/ Full TCP/IP networking stack + eBPF + netfilter
security/ LSM framework: SELinux, AppArmor, capabilities
crypto/ Cryptographic algorithms: AES, SHA, RSAGROUP 4 — MODERN ADDITIONS (not in older 5.x resources)
rust/ Rust language kernel infrastructure [NEW in 6.1]
io_uring/ Async I/O subsystem with ring buffers
GROUP 5 — BUILD, TOOLS, AND DOCUMENTATION
include/ Kernel headers (internal + user-exported uapi/)
scripts/ Build helpers: checkpatch.pl, get_maintainer.pl
tools/ User-space tools: perf, bpftool, selftests
samples/ Example code: kernel modules, eBPF, Rust examples
Documentation/ Official docs written by kernel developers themselves
The Rust Revolution — Biggest Change Since Kernel 5.x
Every older textbook or free Linux kernel programming course you find online will tell you “the Linux kernel is written in C.” That was 100% true until 2022. Starting with Linux 6.1, Rust became a second officially supported kernel language. This is the most significant structural change to the kernel in decades and every modern kernel developer needs to understand it.
Why did the kernel add Rust? The honest answer is safety. The single largest category of Linux kernel security vulnerabilities has always been memory safety bugs — buffer overflows, use-after-free errors, null pointer dereferences, and data races. C gives you full control over memory but provides zero compiler-enforced protection against these bugs. Rust’s type system and ownership model make entire categories of these bugs impossible to compile at all.
| Aspect | C in the kernel | Rust in the kernel |
|---|---|---|
| Memory safety | Developer’s responsibility entirely | Enforced by compiler at build time |
| Use-after-free bugs | Possible and common in drivers | Impossible to compile |
| Amount of kernel code | ~99% of existing code | Growing — new drivers, some subsystems |
| Status in kernel 7.0 | Dominant language, always needed | Fully stable and production-grade |
📌 Important for Students of This Free Linux Kernel Course
Learning C for kernel development is still absolutely essential. The vast majority of the kernel is C and will remain so for many years. Rust is an addition, not a replacement. The first thing this free embedded systems course covers is C-based kernel and driver writing. Rust becomes relevant once you are comfortable with the kernel model itself.
Useful Commands When Exploring the Kernel Source
Once you have the Linux kernel source tree on your system, these are the most practical commands for orientation and exploration:
Exploring the Kernel Source Tree — Essential Commands
du -sh linux-6.6/
# Typical output: 1.3G linux-6.6/# Count all C source files
find linux-6.6/ -name “*.c” | wc -l
# Typical output: ~35,000 files# Count Rust source files (modern kernels)
find linux-6.6/ -name “*.rs” | wc -l# Count all lines of code (needs the ‘cloc’ tool)
cloc linux-6.6/ –quiet
# Search for where a kernel function is declared
grep -rn “alloc_pages” linux-6.6/include/ –include=”*.h”
# Find which maintainer to contact for a source file
./scripts/get_maintainer.pl drivers/bluetooth/btusb.c
# Show only top-level directories (not files)
ls -d linux-6.6/*/
# Quick look at the build system’s view of the version
make kernelversion
🔎 Pro Tip — Use Elixir Cross-Reference Online
Instead of running grep locally across a 1.5 GB source tree, use elixir.bootlin.com. It is a free web-based cross-reference tool for the Linux kernel. You can search any function name, macro, or struct and instantly see every file where it is defined or used, across multiple kernel versions. It is invaluable for kernel learning and development.
Common Mistakes When Working with the Kernel Source Tree
- Running commands in the wrong directory. Many make commands (like
make menuconfig) must be run from the root of the kernel source tree, not from inside a subdirectory. If you get strange errors, check your current working directory first. - Modifying files directly and then trying to update. If you have edited source files and later want to apply a patch or pull updates with git, conflicts will occur. Keep track of any changes you make.
- Thinking you need to read all of it. No one reads all 34 million lines. Kernel work is focused — you work in one subsystem or one driver at a time. Knowing the layout tells you where to look, not that you must read everything.
- Using an outdated reference. Older books, blog posts, and courses that cover kernel 4.x or early 5.x do not mention rust/ or io_uring/ as top-level directories because they did not exist then. Always check which kernel version a resource is based on.
- Ignoring the Documentation/ directory. This is the most overlooked resource. The documentation inside Documentation/ is written by the kernel developers themselves and covers subsystem internals, driver writing guidelines, and coding standards — it is the authoritative source.
Key Takeaways from Lecture 8
✓ The Linux kernel source tree is the complete source of the entire kernel, hosted at kernel.org
✓ Download it as a tarball for learning or use git clone for active development work
✓ The exact kernel version is always readable from the top-level Makefile
✓ The source tree is grouped into core OS, hardware/drivers, networking, and build tooling
✓ Rust support was added in 6.1 and became fully stable in Linux 7.0 — C is still dominant
✓ The compiled kernel image is much smaller than the source because most code is excluded by configuration
Frequently Asked Questions
Q1. What is the Linux kernel source tree?
The Linux kernel source tree is the complete, hierarchically organised collection of source code that compiles into the Linux kernel. It contains code for every supported CPU architecture, device driver, filesystem, network protocol, and kernel subsystem. It is officially hosted at kernel.org and the entire history is managed in a Git repository.
Q2. Do I need to download the full git history to start kernel development?
No. For learning or building your first kernel, download the tarball from kernel.org — it is a compact, clean starting point. A git clone --depth=1 is the next step up. The full git clone (all history) is only needed when you are studying the evolution of specific code or preparing to upstream a patch and need access to git log, git blame, and the full commit history.
Q3. Why is there a NAME field in the Makefile like “Kleptomaniac Octopus”?
Linus Torvalds gives each kernel release a playful nickname. It has no technical meaning but it makes it easy to refer to a release informally. The name is set in the top-level Makefile under the NAME variable and is visible when you run head Makefile from the source root.
Q4. Should I learn Rust to contribute to the Linux kernel?
C is still the dominant kernel language and will remain so for years. You must learn C-based kernel programming to work effectively anywhere in the existing kernel tree. Rust knowledge becomes a differentiator for writing new drivers where memory safety is a priority. For students following this free Linux kernel development course, focus on C first — Rust will be introduced once you understand the kernel programming model.
Q5. What does EXTRAVERSION in the Makefile tell me?
EXTRAVERSION is a suffix appended after SUBLEVEL. For a release candidate it will be something like -rc4. For a final stable release it is empty. Linux distributions also add their own suffix here — Ubuntu kernels might show -generic and Raspberry Pi kernels might show -v8+. This is purely informational for version identification.
Q6. Is this Linux kernel development course really free?
Yes. EmbeddedPathashala provides this entire Linux kernel programming series, along with courses on Linux device drivers and embedded systems, completely free. The goal is to make high-quality technical education available to every student regardless of background or budget. All lectures, diagrams, and code examples are provided at no charge.
Q7. How do I find who maintains a particular driver or subsystem?
Use the script at scripts/get_maintainer.pl from the kernel source root. Pass it the path to any file and it reads the MAINTAINERS file to tell you exactly which person or team is responsible for that code, which mailing list to use for patches, and the status of that component. For example: ./scripts/get_maintainer.pl drivers/net/ethernet/intel/e1000e/e1000.h
Q8. Can I browse the kernel source without downloading it?
Yes, two excellent options: elixir.bootlin.com provides cross-referenced, searchable access to the kernel source across many versions. github.com/torvalds/linux is a read-only mirror of the official kernel repository and supports the familiar GitHub file browsing interface. Neither replaces having a local copy when you are ready to build and test changes.
Q9. What is io_uring and why does it have its own top-level directory now?
io_uring is Linux’s modern asynchronous I/O interface. It uses a pair of ring buffers shared between the kernel and user space — a submission queue where the application writes I/O requests, and a completion queue where the kernel writes results. Because both are memory-mapped, applications can submit many requests and collect results without a system call per operation, dramatically reducing I/O overhead for high-throughput workloads. It has grown so important that it now has its own top-level directory, separate from the older async I/O code.
Q10. What is the best way to search inside the kernel source tree?
For quick searches locally, use grep -rn "search_term" --include="*.c" from the source root. For symbol cross-referencing, use elixir.bootlin.com. For understanding a subsystem, start with Documentation/ — the relevant subdirectory almost always has a README or rst documentation file that explains the subsystem design. For example, Documentation/filesystems/ covers the VFS and individual filesystem internals.
