The Linux source tree separates architecture-independent subsystems from architecture ports, public userspace interfaces, generated build state, tools, and tests. Directory names are a navigation aid rather than an execution model: Kconfig selects configuration, Kbuild selects objects, and the selected objects determine what reaches a particular kernel image.
Top-Level Subsystem Boundaries #
The principal source directories are:
| Path | Responsibility |
|---|---|
arch/ | Architecture ports, boot code, MMU and interrupt entry, and low-level ABI support. |
block/, fs/, mm/, net/ | The block layer; VFS and filesystem implementations; virtual and physical memory management; and networking stacks. |
kernel/, init/, ipc/, security/ | Core scheduling, locking, signals, tracing, and other kernel facilities; early initialization; IPC; and Linux Security Module infrastructure. |
drivers/, sound/, virt/ | Device drivers, the sound subsystem, and virtualization support such as KVM. A driver need not expose a struct file_operations; subsystem-specific buses and callbacks are also common. |
crypto/, lib/, io_uring/, rust/ | Shared cryptographic and library support, asynchronous I/O, and Rust kernel support. |
include/, Documentation/, scripts/ | Headers, maintained documentation, and Kbuild/Kconfig plus generation and maintenance utilities. |
tools/, samples/, usr/ | Userspace tools such as perf, example programs, and built-in initramfs generation. |
Other top-level material such as certs/ and LICENSES/ supports signing,
licensing, or build policy. A source checkout changes over time, so inspect its
top-level README, MAINTAINERS, and Documentation/ instead of assuming every
release contains the same directories.
Kbuild Aggregation and Final Linkage #
Kbuild reads Makefile or Kbuild files and evaluates obj-$(CONFIG_FOO) entries.
y selects a built-in object, m selects a loadable module, and an unset symbol
selects neither. As the build descends through selected directories, it combines
obj-y objects into a thin built-in.a archive. The archives and other selected
objects are later linked into vmlinux; modules follow a separate link path.
Order is significant because the Kbuild documentation
defines the archive and final-link behavior, including initialization ordering.
Consequently, a directory is not a self-contained “module” merely because it has a
built-in.a: configuration and parent Makefiles control whether the directory is
visited and whether its objects reach the final image.
Trace a feature through both configuration and build rules:
git grep -n 'CONFIG_FOO'
git grep -n 'obj-$(CONFIG_FOO)'Read the surrounding Kconfig and Makefile entries before drawing conclusions
from a symbol search, because conditional compilation, generated headers,
architecture overrides, and link order can select another implementation.
Header Families and the Userspace ABI #
Kernel-private, userspace-visible, architecture-specific, and generated headers are kept separate:
| Path | Purpose |
|---|---|
include/ | Architecture-independent kernel-internal headers. |
include/uapi/ | Architecture-independent userspace ABI headers. |
arch/<arch>/include/ | Architecture-specific kernel-internal headers. |
arch/<arch>/include/uapi/ | Architecture-specific userspace ABI headers. |
include/generated/ and arch/<arch>/include/generated/ | Build-generated headers. |
make headers_install exports a sanitized UAPI header set. Applications should use
the installed headers supplied by their operating system or toolchain, not arbitrary
internal headers from a kernel checkout; structures such as task_struct are not
stable userspace interfaces. The header-install documentation
defines the supported export operation.
Generated State and Output Trees #
Configuration writes .config and produces generated headers before compilation.
Kbuild can put generated files and objects in a separate output directory:
make O="$PWD/out" defconfig
make O="$PWD/out" -j"$(nproc)"An out-of-tree build keeps generated state out of the checkout, but the source and output trees remain coupled through configuration, generated headers, and dependency metadata. Reconfigure after moving or partially copying an output directory rather than relying on an incremental build’s old dependency state.
Finding Code and Preparing an Index #
MAINTAINERS records subsystem ownership and preferred patch-routing information.
Follow the affected subsystem’s process and documentation instead of treating the
tree as one centrally owned program; the
maintainer handbook
collects subsystem-specific guidance.
Start implementation discovery with declarations and subsystem documentation, then search definitions:
git grep -n 'SYSCALL_DEFINE.*openat'
git grep -n 'struct file_operations'An editor index benefits from deliberate exclusions because tools/, generated
output, and build products can obscure kernel-space results. For example:
{
"C_Cpp.default.includePath": ["${workspaceFolder}/include"],
"search.exclude": {
"**/tools/**": true,
"**/include/generated/**": true,
"**/out/**": true
}
}Do not exclude a path blindly when investigating a userspace tool or generated interface. The exclusion is an indexing choice, while the Kconfig and Kbuild path remains the evidence for what a kernel build contains.
Comments
Read or comment on GitHub (sign-in required to comment)