Device drivers are parts of the operating system that facilitate usage of hardware devices via certain programming interface so that software applications can control and operate the devices. As each driver is specific to a particular operating system, one need separate Linux, Windows, or Unix device drivers to enable the use of your device on different computers.
Device drivers take on a special role in the Linux kernel. They are distinct “black boxes” that make a particular piece of hardware respond to a well-defined internal programming interface; they hide completely the details of how the device works. User activities are performed by means of a set of standardized calls that are independent of the specific driver; mapping those calls to device-specific operations that act on real hardware is then the role of the device driver. This programming interface is such that drivers can be built separately from the rest of the kernel and “plugged in” at runtime when needed. This modularity makes Linux drivers easy to write, to the point that there are now hundreds of them available.
Linux has helped to democratize operating systems. The Linux kernel remains a large and complex body of code, however, and would-be kernel hackers need an entry point where they can approach the code without being overwhelmed by complexity. Often, device drivers provide that gateway.
Linux Driver Architecture
The Linux driver model is different. For users, the goal is to provide the “Just Works” experience. The Linux model is that IHVs get the source code for their driver accepted into the mainline kernel. This entails a public peer review process to ensure that the driver code is of sufficient quality and does not have obvious bugs or security risks.
Linux has neither a stable binary driver ABI nor a stable source-code driver Application Programming Interface (API). That is, there is no guarantee that an interface provided in one version of the kernel will be available in the next version, and portions of the ABI and API change in every kernel release.
The Linux device driver architecture as compared to the Windows one is that Linux does not have a standard driver model or a clean separation into layers. Each device driver is usually implemented as a module that can be loaded and unloaded into the kernel dynamically.
Linux provides means for plug-and-play support and power management so that drivers can use them to manage devices correctly, but this is not a requirement.
Modules export functions they provide and communicate by calling these functions and passing around arbitrary data structures. Requests from user applications come from the filesystem or networking level, and are converted into data structures as necessary. Modules can be stacked into layers, processing requests one after another, with some modules providing a common interface to a device family such as USB devices.
Linux device drivers support three kinds of devices:
- Character devices which implement a byte stream interface.
- Block devices which host file systems and perform IO with multi byte blocks of data.
- Network interfaces which are used for transferring data packets through the network.
Linux also has a Hardware Abstraction Layer that acts as an interface to the actual hardware for the device drivers.
Device Driver Development Environment
Linux source code
Linux is an open-source operating system, thus the entire source code of Linux is the SDK for driver development. There is no formal framework for device drivers, but Linux kernel includes numerous subsystems that provide common services like driver registration. The interfaces to these subsystems are described in kernel header files.
Build system for device drivers
Linux uses Makefiles as a build system for both in-tree and out-of-tree device drivers. Linux build system is quite developed and usually a device driver needs no more than a handful of lines to produce a working binary. Developers can use any IDE as long as it can handle Linux source code base and run make, or they can easily compile drivers manually from terminal.
Linux documentation is not as descriptive, but this is alleviated with the whole source code of Linux being available to driver developers. The Documentation directory in the source tree documents some of the Linux subsystems, but there are multiple books concerning Linux device driver development and Linux kernel overviews, which are much more elaborate.
Linux does not provide designated samples of device drivers, but the source code of existing production drivers is available and can be used as a reference for developing new device drivers.
Linux has logging facilities that can be used to trace-debug driver code.
Linux supports interactive debugging by means of KDB and KGDB. Debugging support can be built into the kernel and enabled at boot time. After that one can either debug the system directly via a physical keyboard, or connect to it from another machine via a serial port. KDB offers a simple command-line interface and it is the only way to debug the kernel on the same machine. However, KDB lacks source-level debugging support. KGDB provides a more complex interface via a serial port. It enables usage of standard application debuggers like GDB for debugging Linux kernel just like any other userspace application.
Linux has achieved an unprecedented level of hardware support. It has done so using a development model that is quite different from the established Windows model, but that offers significant benefits in stability, capability, and security. Like the rest of the Linux OS, the driver model leverages the strengths of open source development to provide better code that improves over time. With several new initiatives from the kernel community and the Linux Foundation, and through cooperation from the relevant IHVs, Linux should soon be able to fully support the small number of remaining devices.
For more information about the Linux Device Driver Development, please drop an email to firstname.lastname@example.org