What is Linux Kernel Source Tree Layout-Best Embedded Linux Training Online

PREV_LEC NEXT_LEC

Linux Kernel Source Tree Layout
Free Embedded Linux Course — Chapter 4: Porting And Configuring The Kernel
Part of: Free Linux Device Drivers Course
Level: Beginner
Reading Time: ~11 min

The Linux kernel source tree contains millions of lines of code across tens of thousands of files — intimidating the first time you open it. This lecture in our free linux kernel development course gives you a practical map of the top-level directories, so you always know roughly where to look for a given piece of functionality instead of grepping the entire tree blindly.

kernel source tree
drivers directory
arch directory
kernel documentation
device driver location
free embedded systems course

What You Will Learn

The purpose of each top-level kernel source directory
Where driver code lives versus architecture-specific code
How to quickly locate the code for a given subsystem
Why serial port drivers live outside the arch tree
Practical commands for exploring a fresh checkout

Prerequisites

A cloned or extracted kernel source tree on disk (covered in the previous lecture of this free linux development course) and basic command-line navigation skills.

Why the Layout Matters

A recent mainline kernel contains well over 70,000 files and tens of millions of lines of code across C source, headers, and assembly. Nobody memorizes all of it — what experienced kernel developers actually have is a mental map of where things generally live, built from the tree’s consistent top-level organization. Learn this map once and it applies to every kernel version and every architecture you’ll ever work with.

Exploring the Top Level

Start any new kernel tree the same way — list the top-level directories:

$ cd ep-linux
$ ls -1
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
Makefile
Kconfig
COPYING
...

The directories that matter most for day-to-day embedded and driver work are a smaller subset. Here’s what each one actually contains:

Directory Contents
arch/ Architecture-specific code — one subdirectory per CPU architecture (arm64, x86, riscv, …)
Documentation/ Kernel documentation in reStructuredText — always check here first for a subsystem’s official docs
drivers/ Device drivers, organized into subdirectories by device class (tty, net, gpio, i2c, …)
fs/ Filesystem implementations (ext4, btrfs, overlayfs, VFS core, …)
include/ Kernel header files, including the ones exposed to user space and needed by a cross toolchain
init/ Kernel start-up / boot sequence code
kernel/ Core scheduler, locking primitives, timers, power management, tracing infrastructure
mm/ Memory management — page allocator, virtual memory, swap
net/ Network protocol stacks (TCP/IP, netfilter, Bluetooth core, …)
scripts/ Build-time tooling, including the device tree compiler dtc
tools/ Standalone user-space tools shipped with the kernel, such as perf
Top-Level Kernel Source Tree Map
linux/
├── arch/ architecture-specific (arm64, x86, riscv…)
├── Documentation/ official docs, check first
├── drivers/ device drivers by class
├── fs/ filesystems
├── include/ kernel + toolchain headers
├── init/ boot-time startup code
├── kernel/ scheduler, locking, timers, PM
├── mm/ memory management
├── net/ networking stacks
├── scripts/ build tooling (incl. dtc)
└── tools/ user-space tools (incl. perf)

The Key Insight: Drivers vs Architecture Code

The single most common confusion for newcomers is guessing that a peripheral driver lives under arch/$ARCH/ because that’s “where the SoC-specific stuff is.” In reality, the arch/ tree only holds code that’s central to bringing up and running that CPU architecture itself — boot entry points, low-level interrupt handling, machine descriptors, and similar plumbing.

An actual device driver — a serial port controller, an I2C bus driver, a GPIO expander — lives under drivers/, organized by device class, not by which SoC it happens to run on. A UART driver for an ARM SoC and a UART driver for a RISC-V SoC both live side-by-side under drivers/tty/serial/, not scattered across different arch/ subtrees.

# finding a serial driver — correct place to look
$ ls drivers/tty/serial/ | grep -i imx

# NOT here — arch/ holds boot/platform plumbing, not device drivers
$ ls arch/arm64/mach-*   # this pattern doesn't even exist on modern arm64

Practical Exercise: Locating a Subsystem

Say you need to find the GPIO framework core. A quick, targeted search beats an unfocused grep across the entire multi-million-line tree:

$ ls drivers/gpio/ | head
$ ls Documentation/driver-api/gpio/

Expected output gives you both the implementation directory and its official documentation in one pass — exactly the pattern to repeat for any subsystem: check Documentation/ for the concept, then the matching drivers/<class>/ directory for real implementations to read as examples.

Real-World Use Case: Onboarding to an Unfamiliar Codebase

When you join a project with an existing vendor kernel fork, the fastest way to get oriented isn’t reading it front-to-back — it’s using this same top-level map to jump straight to the areas relevant to your task. Bringing up a new sensor driver? Go straight to drivers/iio/ or drivers/hwmon/ depending on its class, check Documentation/ for the relevant subsystem binding docs, and use existing drivers in that directory as your template.

Common Mistakes and Troubleshooting

  • Searching arch/ for device driver code — you’ll rarely find it there on a modern kernel; go to drivers/ instead.
  • Ignoring Documentation/ — it’s frequently more current and authoritative than blog posts or older books, and it’s already sitting right there in the tree you cloned.
  • Grepping the whole tree for every question — a targeted look in the right top-level directory is faster and teaches you the layout; blind full-tree greps get slower as the codebase grows.
  • Assuming directory names are architecture-specific when they’re class-specific — drivers/gpio/, for instance, holds GPIO controller drivers for every architecture, not one.

Best Practices

  • Always check Documentation/ before diving into implementation code for an unfamiliar subsystem.
  • Use drivers/<class>/ as your default search location for any actual peripheral driver.
  • Reserve arch/$ARCH/ searches for boot, low-level interrupt, or machine-descriptor questions.
  • Use existing drivers in the same class directory as working references when writing something new.

Summary / Key Takeaways

  • The kernel source tree’s top-level layout is consistent across versions and architectures — learn it once.
  • drivers/ holds device drivers organized by class; arch/ holds architecture plumbing, not peripheral drivers.
  • Documentation/ is the first place to check for any subsystem’s official explanation.
  • Targeted searches in the right directory beat blind full-tree greps.

Conclusion

Once you can navigate the tree confidently, the kernel stops feeling like an impenetrable multi-million-line codebase and starts feeling like a well-organized project you can find your way around in seconds. The next lecture in this free linux kernel development course moves on to the configuration system — Kconfig and Kbuild — that decides which of this code actually ends up in your build.

Frequently Asked Questions

Why isn’t my board’s driver under arch/arm64/?

Because arch/ only contains architecture-level plumbing, not device drivers. Actual peripheral drivers live under drivers/, organized by device class rather than by SoC or architecture.

Is Documentation/ always up to date?

It’s actively maintained alongside the code and generally the most reliable first stop, though like any large project some corners lag behind — cross-check against the actual source when something seems off.

How many files are actually in a modern kernel tree?

It varies by release, but recent mainline kernels run well into the tens of thousands of files and tens of millions of lines across C, headers, and assembly — checking your specific checkout with a tool like cloc gives an exact count.

Where do I find the device tree compiler source?

The dtc tool lives under scripts/dtc/ in the kernel tree.

What’s the difference between fs/ and drivers/?

fs/ contains filesystem implementations and the virtual filesystem (VFS) core; drivers/ contains the code that talks to hardware devices. A block device driver lives in drivers/, while the filesystem that sits on top of it lives in fs/.

Continue the Free Linux Kernel Development Course

Next up: understanding Kconfig and Kbuild, the kernel’s configuration system.

PREV_LEC NEXT_LEC

 

Leave a Reply

Your email address will not be published. Required fields are marked *