From here on, we enter the world of kernel programming. Chapter 2 introduces modularization, explaining the secrets of the art and showing the code for running modules. Chapter 3 talks about char drivers and shows the complete code for a memory-based device driver that can be read and written for fun. Using memory as the hardware base for the device allows anyone to run the sample code without the need to acquire special hardware.
Debugging techniques are vital tools for the programmer and are introduced in Chapter 4. Then, with our new debugging skills, we move to advanced features of char drivers, such as blocking operations, the use of select, and the important ioctl call; these topics are the subject of Chapter 5.
Next we focus on hardware. Chapter 8 describes the management of I/O ports and memory buffers that live on the device; after that comes interrupt handling, in Chapter 9. Unfortunately, not everyone will be able to run the sample code for these chapters, because some hardware support is actually needed to test the software interface to interrupts. We’ve tried our best to keep required hardware support to a minimum, but you still need to put your hands on the soldering iron to build your hardware “device.” The device is a single jumper wire that plugs into the parallel port, so we hope this is not a problem.
Chapter 10 offers some additional suggestions about writing kernel software and about portability issues.
In the second part of this book, we get more ambitious; thus, Chapter 11 starts over with modularization issues, going deeper into the topic.
Chapter 12 then describes how block drivers are implemented, outlining the aspects that differentiate them from char drivers. Following that, Chapter 13 explains what we left out from the previous treatment of memory management: mmap and direct memory access (DMA). At this point, everything about char and block drivers has been introduced.
The third main class of drivers is introduced next. Chapter 14 talks in some detail about network interfaces and dissects the code of the sample network driver.
A few features of device drivers depend directly on the interface bus where the peripheral fits, so Chapter 15 provides an overview of the main features of the bus implementations most frequently found nowadays, with a special focus on PCI and USB support offered in the kernel.
Finally, Chapter 16 is a tour of the kernel source: it is meant to be a starting point for people who want to understand the overall design, but who may be scared by the huge amount of source code that makes up Linux.