Chapter 1: Introduction and Overview
Techniques that would be unthinkable in many textbook solutionscannot only be good, but are simply
required for a proper real-world working kernel. It’s the small path that keeps the balance between these
totally opposite faces of the kernel that makes the whole thing so interesting, challenging, and fun!
Having praised the kernel sources, there are a number of more sober issues distinct from userland
programs:
❑ Debugging the kernel is usually harder than debugging userland programs. While for the latter
a multitude of debuggers exist, this is much harder to realize for the kernel. Therearevarious
mechanisms to employ debuggers in kernel development as discussed in Appendix B, but these
require more effort than their userland counterparts.
❑ The kernel provides numerous auxiliary functions that resemble the standard C library found in
userspace, but things are much more frugal in the kernel domain.
❑ Errors in userland applications lead to a segmentation fault or a core dump, but kernel errors
will take the whole system down. Or, what is even worse: They will keep the kernel happily
running, but manifest themselves in a weird system crash hours after the error occurred. Because
debugging in kernel space is harder than for userland applications as mentioned above, it is
essential that kernel code receives more thoughtand judicious consideration than userland code
before it is brought into use.
❑ It must be taken into account that many architectures on which the kernel runs do not support
unaligned memory access without further ado. This also affects portability of data structures
across architectures because of padding that is inserted by the compiler. This issue is discussed
further in Appendix C.
❑ All kernel code must be protected against concurrency. Owing to the support of multiprocessor
machines, Linux kernel code must be both reentrant and thread-safe. That is, routines must allow
being executed simultaneously, and data must be protected against parallel access.
❑ Kernel code must work both on machines with little and big endianness.
❑ Most architectures do not allow performing floating-point calculations in the kernel without
further ado, so you need to find a way to do your calculations with integer types.
You will see how to deal with these issues in the further course of this book.
1.5 Some Notes on Presentation
Before we start to dive right into the kernel, I need to make some remarks on how I present the material,
and why I have chosen my particular approach.
Notice that this book is specifically aboutunderstandingthe kernel. Examples of how to write code have
intentionally and explicitly been left out, considering that this book is already very comprehensive and
voluminous. The works by Corbet et al. [CRKH05], Venkateswaran [Ven08], and Quade/Kunst [QK06]
fill in this gap and discuss how to create new code, especially for drivers, by countless practical examples.
While I discuss how the kernel build system, which is responsible to create a kernel that precisely suits
your needs works, I won’t discuss the plethora of configuration options in detail, especially because they
are mostly concerned with driver configuration. However, the book by Kroah-Hartman [KH07] can be
avaluableaidhere.