Linux Kernel Documentation Index

This page collects and organizes documentation about the Linux kernel, taken from many different sources. What is the kernel, how do you build it, how do you use it, how do you change it...

This is a work in progress, and probably always will be. Please let us know on the linux-doc mailing list (on vger.kernel.org) about any documentation you'd like added to this index, and feel free to ask about any topics that aren't covered here yet. This index is maintained by Rob Landley <rob@landley.net>, and tracked in this mercurial repostiory. The cannonical location for the page is here.



These are various upstream sources of documentation, many of which are linked into the linux kernel documentation index.

Building source packages is usually a three step process: configure, build, and install.

The Linux kernel is configured with the command "make menuconfig", built with the command "make", and installed either manually or with the command "make install".

For a description of the make options and targets, type make help.

The Linux kernel source code is distributed by kernel.org as tar archives. Grab the most recent "stable" release (using the tiny little letter F link) to grab a file of the form "linux-2.6.*.tar.bz2" from the Linux 2.6 releases directory. Then extract this archive with the command "tar xvjf linux-2.6.*.tar.bz2". (Type the command "man tar" for more information on the tar command.) Then cd into the directory created by extracting the archive.

To obtain other Linux kernel versions (such as development releases and kernels supplied by distributions) see Following Linux development.

To return your linux kernel source directory to its original (unconfigured) condition after configuring and building in it, either either delete the directory with "rm -r" and re-extract it from the tar archive, or run the command "make distclean".

The Linux configuration system is called Kconfig. The most common user interface for kconfig is menuconfig, an interactive terminal based menuing interface invoked through the makefiles via "make menuconfig". A simpler text based question and answer interface (which does not require curses support or a tty) is available as "make config". Graphical interfaces are available as "make xconfig" (based on QT) and "make gconfig" (based on GTK). For more information, see make help

The configuration interfaces present

By default, Linux builds for the same architecture the host system is running. This is called "native compiling". An x86 system building an x86 kernel, x86-64 building x86-64, or powerpc building powerpc are all examples of native compiling.

Building different binaries than the host runs is called cross compiling. Cross compiling is hard. The build system for the Linux kernel supports cross compiling via a two step process: 1) Specify a different architecture (ARCH) during the configure, make, and install stages. 2) Supply a cross compiler (CROSS_COMPILE) which can output the correct kind of binary code. An example cross compile command line (building the "arm" architecture) looks like:

make ARCH=arm menuconfig
make ARCH=arm CROSS_COMPILE=armv5l-

To specify a different architecture than the host, either define the "ARCH" environment variable or else add "ARCH=xxx" to the make command line for each of the make config, make, and make install stages. The acceptable values for ARCH are the names of the directories in the "arch" subdirectory of the Linux kernel source code, see Architectures for details. All stages of the build must use the same ARCH value, and building a second architecture in the same source directory requires "make distclean". (Just "make clean" isn't sufficient, things like the include/asm symlink need to be removed and recreated.)

To specify a cross compiler prefix, define the CROSS_COMPILE environment variable (or add CROSS_COMPILE= to each make command line). Native compiler tools, which output code aimed at the environment they're running in, usually have a simple name ("gcc", "ld", "strip"). Cross compilers usually add a prefix to the name of each tool, indicating the target they produce code for. To tell the Linux kernel build to use a cross compiler named "armv4l-gcc" (and corresponding "armv4l-ld" and "armv4l-strip") specify "CROSS_COMPILE=armv4l-". (Prefixes ending in a dash are common, and forgetting the trailing dash in CROSS_COMPILE is a common mistake. Don't forget to add the cross compiler tools to your $PATH.)

Advanced Boot Scripts

The Linux kernel runs programs in response to the exec syscall, which is called on a file. This file must have the executable bit set, and must be on a filesystem that implements mmap() and which isn't mounted with the "noexec" option. The kernel understands several different executable file formats, the most common of which are shell scripts and ELF binaries.

If the first two bytes of an executable file are the characters "#!", the file is treated as a script file. The kernel parses the first line of the file (until the first newline), and the first argument (immediately following the #! with no space) is used as absolute path to the script's interpreter, which must be an executable file. Any additional arguments on the first line of the file (separated by whitespace) are passed as the first arguments to that interpreter executable. The interpreter's next argument is the name of the script file, followed by the arguments given on the command line.

To see this behavior in action, run the following:

echo "#!/bin/echo hello" > temp
chmod +x temp
./temp one two three

The result should be:

hello ./temp one two three

This is how shell scripts, perl, python, and other scripting languages work. Even C code can be run as a script by installing the tinycc package, adding "#!/usr/bin/tcc -run" to the start of the .c file, and setting the executable bit on the .c file.

Most userspace programs access operating system functionality through a C library, usually installed at "/lib/libc.so.*". The C library wraps system calls, and provides implementations of various standard functions.

Because almost all other programming languages are implemented in C (including python, perl, php, java, javascript, ruby, flash, and just about everything else), programs written in other languages also make use of the C library to access operating system services.

The most common C library implementations for Linux are glibc and uClibc. Both are full-featured implementations capable of supporting a full-featured desktop Linux distribution.

The main advantage of glibc is that it's the standard implementation used by the largest desktop and server distributions, and has more features than any other implementation. The main advantage of uClibc is that it's much smaller and simpler than glibc while still implementing almost all the same functionality. For comparison, a "hello world" program statically linked against glibc is half a megabyte when stripped, while the same program statically linked against uClibc strips down to 7k.

Other commonly used special-purpose C library implementations include klibc and newlib.

Building a C library from source code requires a special set of Linux kernel header files, which describe the API of the specific version of the Linux kernel the C library will interface with. However, the header files in the kernel source code are designed to build the kernel and contain a lot of internal information that would only confuse userspace. These kernel headers must be "exported", filtering them for use by user space.

Modern Linux kernels (based on 2.6.19.1 and newer) export kernel headers via the "make headers_install" command. See exporting kernel headers for use by userspace for more information.

FHS spec

populating /dev from sysfs.

Often the first implementation of a concept gets replaced. Journaling != reiserfs, virtualization != xen, devfs gave way to udev... Don't let your excitement for the concept blind you to the possibility of alternate implementations.

RCU stands for "Read Copy Update". The technique is a lockless way to manage data structures (such as linked lists or trees) on SMP systems, using a specific sequence of reads and updates, plus a garbage collection step, to avoid the need for locks in both the read and the update paths.

RCU was invented by Paul McKenney, who maintains an excellent page of RCU documentation. The Linux kernel also contains some additional RCU Documentation.

RCU cannot be configured out of the kernel, but the kconfig symbol CONFIG_RCU_TORTURE_TEST controls the RCU Torture test module.

References:

The original Linux process scheduler was a simple design based on a goodness() function that recalculated the priority of every task at every context switch, to find the next task to switch to. This served almost unchanged through the 2.4 series, but didn't scale to large numbers of processes, nor to SMP. By 2001 there were calls for change (such as the OLS paper Enhancing Linux Scheduler Scalability), and the issue came to a head in December 2001.

In January 2002, Ingo Molnar introduced the "O(1)" process scheduler for the 2.5 kernel series, a design based on separate "active" and "expired" arrays, one per processor. As the name implied, this found the next task to switch to in constant time no matter how many processes the system was running.

Other developers (such as Con Colivas) started working on it, and began a period of extensive scheduler development. The early history of Linux O(1) scheduler development was covered by the website Kernel Traffic.

During 2002 this work included preemption, User Mode Linux support, new drops, runtime tuning, NUMA support, cpu affinity, scheduler hints, 64-bit support, backports to the 2.4 kernel, SCHED_IDLE, discussion of gang scheduling, more NUMA, even more NUMA). By the end of 2002, the O(1) scheduler was becoming the standard even in the 2.4 series.

2003 saw support added for hyperthreading as a NUMA variant, interactivity bugfix, starvation and affinity bugfixes, more NUMA improvements, interactivity improvements, even more NUMA improvements, a proposal for Variable Scheduling Timeouts (the first rumblings of what would later come to be called "dynamic ticks"), more on hyperthreading...

In 2004 there was work on load balancing and priority handling, and still more work on hyperthreading...

In 2004 developers proposed several extensive changes to the O(1) scheduler. Linux Weekly News wrote about Nick Piggin's domain-based scheduler and Con Colivas' staircase scheduler. The follow-up article Scheduler tweaks get serious covers both. Nick's scheduling domains were merged into the 2.6 series.

Linux Weekly News also wrote about other scheduler work:

In 2007, Con Colivas proposed a new scheduler, The Rotating Staircase Deadline Scheduler, which hit a snag. Ingo Molnar came up with a new scheduler, which he named the Completely Fair Scheduler, described in the LWN writeups Schedulers: the plot thickens, this week in the scheduling discussion, and CFS group scheduling.

The CFS scheduler was merged into 2.6.23.

The Real-Time Application Interface (OLS 2001, obsolete)

A pipe can be read from or written to, transmitting a sequence of bytes in order.

A file can do what a pipe can, and adds the ability to seek to a location, query the current location, and query the length of the file (all of which are an integer number off bytes from the beginning of the file).

A tty can do what a pipe can, and adds a speed (in bits per second) and cursor location (X and Y, with the upper left corner at 0,0). Oh, and you can make it go beep.

Note that you can't call lseek() on a tty and you can't call termios (man 3 termios) functions on a file. Each can be treated as a pipe.

http://www.linux-usb.org/USB-guide/x173.html http://www.linux-usb.org/USB-guide/c607.html http://www.linuxjournal.com/article/7466

Devfs was the first attempt to do a dynamic /dev directory which could change in response to hotpluggable hardware, by doing the seemingly obvious thing of creating a kernel filesystem to mount on /dev which would adjust itself as the kernel detected changes in the available hardware.

Devfs was an interesting learning experience, but turned out to be the wrong approach, and was replaced by sysfs and udev. Devfs was removed in kernel version 2.6.18. See the history of hotplug for details.

Linux NFS Version 4: Implementation and Administration (OLS 2001)

Hotpluggable devices and the Linux kernel (OLS 2001)

The history of hotplug

physical
  plip
  serial/slip/ppp
  ethernet
routing
  ipv4
  ipv6

MIPL Mobile IPv6 for Linux in HUT Campus Network MediaPoli (OLS 2001)

Linux Kernel SCTP: The Third Transport (OLS 2001)

TCPIP Network Stack Performance in Linux Kernel 2.4 and 2.5

EXPORT_SYMBOL() vs EXPORT_SYMBOL_GPL()

List of exported symbols.

Users, groups, files (rwx), signals.

The traditional Unix security model is too simple to satisfy the certification requirements of large corporate and governmental organizations, so several add-on security models have been implemented to increase complexity. There is some debate as to which of these (if any) are actually an improvement.

http://www.gentoo.org/proj/en/hardened/capabilities.xml

Meeting Critical Security Objectives with Security-Enhanced Linux (OLS 2001)

SE Debian: how to make NSA SE LInux work in a distribution (OLS 2002)

The Long Road to the Advanced Encryption Standard

alpha
arm
avr32
blackfin
cris
frv
h8300
i386
ia64
m32r
m68k
m68knommu
  Running Linux on a DSP: Exploiting the Computational Resources of a programmable DSP Micro-Processor with uClinux (OLS 2002)
mips
parisc
  Porting Drivers to HP ZX1
powerpc
  The Linux Kernel on iSeries (OLS 2001)
  PowerPC 64-bit Kernel Internals (OLS 2001)
  PowerPC implementation reference for QEMU
ppc
s390
sh
sh64
sparc
sparc64
um
  User-Mode Linux (OLS 2001)
  Making Linux Safe for Virtual Machines (OLS 2002)
v850
x86_64
  Porting Linux to x86-64 (OLS 2001)
xtensa

include/asm-generic
uml
http://www.linux-usb.org/USB-guide/book1.html Documentation/usb

PCIComm: A Linux Device Driver for Communication over PCI Shared Memory (OLS 2001)

Linux performance tuning using Powertweak (OLS 2001)

Linux releases from 0.0.1 through 2.4.x used no source control system, just release tarballs. Releases 2.5.0 through 2.6.12-rc2 used a proprietary source control system called BitKeeper. Releases 2.6.12-rc2 through the present use a source control system called git.

Early Linux development didn't use source control. Instead Linus would apply patches to his copy of the source, and periodically release tarball snapshots of his development tree with a hand-edited changelog file noting who contributed each patch he'd applied. Most of these patches were posted to the Linux Kernel Mailing List, and with a little effort could be fished out of the mailing list archives.

This worked for many years, but didn't scale as Linux development grew. Eventually the issue came to a head [link], and after some discussion Linus decided to use a proprietary distributed source control system called BitKeeper for the 2.5 development branch. Linux releases v2.5.0 through v2.6.12-rc2 were put out this way.

Linux development no longer uses BitKeeper, due to the sudden expiration of the "Don't piss off Larry license" under which BitKeeper was made available to the Linux community (more here). This prompted Linus to take a month off from Linux development to write his own distributed source control system, git. This is why the current source control history in the main git development repository goes back to 2.6.12-rc2. (The revision history from the BitKeeper era was later converted to git, but remains separate for historical reasons.)

Linus initially chose BitKeeper because he wanted a distributed source control system, and the open source alternatives available at the time were all centralized source control systems.

In a distributed source control system, every user has a complete copy of the project's entire revision history, which they can add their own changes to locally. A centralized source control system requires a single central location, with user accounts to control access and either locking the tree or rejecting attempts to apply out of date patches. A distributed source control system is instead designed to download and merge changes from many different repositories after they're checked in to those other repositories. The source control system handles almost all of this merging automatically, because it can trace the changes in each repository back to a common ancestor, and then use three-way merge algorithms to better understand the changes. (Patches don't indicate which version they apply to. A distributed source control system has more information avialable to it, and uses that information to automatically merge changes more effectively.)

This allows Linux subsystem maintainers to develop and test their own local versions, then send changes to Linus in large batches (without smearing together the individual patches they committed), and finally resync with Linus's repository to get everyone else's changes. Open source development is already distributed, so distributed source control is a better fit. In this development model, Linus's repository serves as a coordination point, but not a development bottleneck for anything except putting out releases (which come from Linus's repository).

Linus described the appeal of distributed source control, and his reasons for developing git, in the Google Video tech talk Linus Torvalds on git.

To get started with git, see git quickstart.

The linux kernel source is also available as a mercurial repository, another popular open source distributed source control system.

This paper still serves as a decent introduction to distributed source control: BitKeeper for Kernel Development (OLS 2002, obsolete)

  CATB
  http://vger.kernel.org/vger-lists.html
  http://www.tux.org/lkml/
  lwn, kernel traffic, kernelplanet.
  http://www.kernel.org/faq
    http://www.kernel.org/kdist/rss.xml
  git/mercurial
  Documentation/{CodingStyle,SubmitChecklist}
  The four layer (developer, maintainer, subsystem, linus) model.
  Politics
    Stable API nonsense
    Why reiser4 not in.