Linux-Device-Driver walks LDD3 examples forward to a 7.2 kernel inside a patched QEMU
Advanced examples of Linux Device Drivers (LDD3) and detailed manual for running examples in QEMU which is patched with virtual PCI, USB, serial devices. I am actively composing a new book about Driver Development in Linux Kernel.
At a glance
- What is it?
- Linux-Device-Driver is a set of kernel module examples numbered in learning order, from a hello world module to procfs, ioctl, pipes, poll, PCI and USB skeletons, together with a QEMU build patched with virtual PCI, USB and serial devices. The current baseline is Linux 7.2.x on Fedora 44, and the tutorial checkout is deliberately separate from the runtime workspace.
- Who is it for?
- Adopt Linux-Device-Driver if you are learning kernel module development and want working code that matches a current kernel rather than the 2.6-era API in the book, since the examples were rewritten and the QEMU image gives you virtual hardware for the parallel port and bus exercises without owning the hardware.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A numbered sequence of 25 module examples, not a library
The repository is a tutorial, and its structure is a curriculum. The examples directory holds kernel module examples and userspace test programs, and the numbered directories preserve the learning sequence: 01_hello_world, 02_module_parameters, 03_scull_basic, 04_proc_fs_basic, 05_proc_fs_iterator, 06_completion, 07_ioctl, 08_pipe_simple_sleep, 09_pipe_advanced_sleep, 10_poll, 11_asynchronous_notification, 12_seeking, 13_jit, 14_jiq, 15_short_ioport, 16_short_port_remap, 17_short_mmio, 18_short_irq, 19_short_irq_probe, 20_pci_skel, 21_usb_skel, 22_lddbus, 23_simple, 24_zero_copy and 25_async_io. There is also an rbtree directory, described as a supplemental example.
The sequence teaches a specific progression. The first two cover module scaffolding and module parameters, then the scull character device from the book, then the procfs interface with a simple version and an iterator version, then completion for kernel-side waiting, then ioctl. The middle block is the hardest part of driver development: the two sleep variants, poll, asynchronous notification and seeking. The jit and jiq examples sit next to each other, which is the point, since they contrast two different ways of spending a delay: burning CPU while waiting versus yielding it to other work. Then the hardware-facing block, short I/O port access, port remapping, memory-mapped I/O, interrupt handling and interrupt probing, before the bus skeletons for PCI and USB, an lddbus example, and the performance-oriented last three.
Building one example is a directory change and a make:
cd examples/01_hello_world
makeThat simplicity depends on the environment variable, which is the one piece of setup the whole project needs before anything compiles.
KERNELDIR is the only thing you must set before building
Before you build anything, the README asks you to set the KERNELDIR environment variable to the Linux kernel source directory and export it to your local shell:
export KERNELDIR=/path/to/kernel/source/The reason is given plainly: this environment variable is mainly used in the Makefile to determine which kernel source tree the drivers are built against. That is worth understanding because it explains why there is no kernel version in the build files. The module is compiled against whatever tree you point at, so the Makefile does not need to know the version, and you get a module built for your tree rather than for a pinned one.
The trade is that the version check moves from the build system to the reader. The README states the current test baseline as kernel Linux 7.2.x and host system Fedora release 44, Forty Four, and then says directly that other kernel versions and host distributions are not tested. A single untested combination is a much narrower claim than a version range, and in a kernel module project the combination of kernel version, compiler version and distribution patches is exactly what determines whether a module loads.
The other structural point is the separation between the tutorial and the runtime. The tutorial checkout is separate from the runtime workspace, referred to as LDD_ROOT, and the README directs you to the workspace setup at docs/00_preface/00_dir_tree.md to create the workspace and install the helper scripts. The repository layout has three top-level directories with distinct roles: docs/ for tutorial chapters in reading order, examples/ for the kernel module examples and userspace test programs, and tools/ for workspace scripts, the QEMU patch and tool tests.
That tools/ directory is the part that separates this from a book code dump. It holds a QEMU patch, which means the virtual machine used for the exercises is not stock QEMU.
The patched QEMU exists because the parallel port is gone
The README explains the hardware problem with a piece of honesty that is worth repeating. The examples are excerpted from Linux Device Drivers, Third Edition, and LDD3 was first published in 2005 against Kernel 2.6.10. Since then the APIs and data structures have changed drastically.
The specific obstacle was hardware rather than API. The parallel port, used as the example device in the I/O operations chapters, can be barely found in any computer now. The author's response was to move those examples into a QEMU virtual machine, described as a generic and open source machine emulator and virtualizer, in which a virtual parallel port device is implemented for convenient debugging.
The repository description puts it more precisely: the project contains a detailed manual for running the examples in QEMU which is patched with virtual PCI, USB and serial devices. So the patch supplies the devices the curriculum needs. The PCI and USB skeleton examples in 20_pci_skel and 21_usb_skel need a bus to enumerate, and the serial device covers the port exercises, none of which exist on a laptop or in a cloud instance.
That is the real contribution of the QEMU patch. Without it you would need physical hardware to complete the sequence, which is why so many driver tutorials stop at the character device and never reach the bus enumeration chapters. With it, the entire 25-example sequence runs on one machine.
The trade is that you are running a modified emulator. The tools/ directory is described as holding workspace scripts, the QEMU patch and tool tests, and the tool tests are there precisely because a patched build is a thing that can regress.
The author is also working on a book about driver development in the Linux kernel, and the README frames the repository as the opening of that project, with the examples serving as the tour that precedes the book.
What the LDD3 lineage means for how much of the code you should trust
Two things follow from the book's provenance, and they point in opposite directions.
The first is that the examples are a mix of two sources. The README says some of the examples are excerpted from LDD3, authored by Jonathan Corbet, Alessandro Rubini and Greg Kroah-Hartman, and the other examples are written by the author to illustrate some important data structures or details. So the sequence is not a single coherent codebase with one author's style; it is the book's canonical examples plus additional examples to fill the gaps, and the gap-filling examples are the ones most likely to reflect current kernel practice.
The second is the migration story. The author notes that LDD3 is still an excellent book to reference for the development of a Linux device module, and that it remains online with a PDF available on request from lwn.net. But because of its age some of the APIs and data structures have drastically changed. The author rewrote all the examples for a newer kernel, and the README names the version at the time as 5.10, released in December 2020. The repository now targets 7.2.x, so the code has been carried forward since then.
For a reader this is the interesting tension. The book remains the better explanation of why a mechanism exists, because the prose and the code were written together by people who knew the kernel. The repository is the better source for how that mechanism looks now. Neither replaces the other, and the repository is explicit that it is a study and sharing project rather than a production driver.
One maintenance note belongs here. The README carries a line apologising for the delay in maintaining this project, sincerely, near the top. The last push was on 2026-10-22, so work is happening, but the project itself flags the gap, and a sequence of 25 examples against a moving kernel target will accumulate drift that only the author can resolve.
Where this repository stops being the right place to learn
Three limits, and the first is about the kernel version itself.
The first is that the baseline is a moving target that has already moved twice. The examples were rewritten for 5.10 in December 2020, and the current target is 7.2.x. Any specific API in the sequence can be valid for 7.2 and stale for whatever your distribution ships, and the README is explicit that other kernel versions are not tested. Learning from an example that no longer compiles teaches you the shape of the mechanism and then sends you to the current kernel documentation to fix the details, which is a worse starting point than reading current code directly.
The second is that the environment is narrow. A single kernel on a single distribution, Fedora 44, with a patched QEMU built from tools/. Building the patched emulator is work in itself, and the workspace setup lives in a separate LDD_ROOT with its own helper scripts and its own directory tree. A reader on a different distribution, or on a kernel that differs from 7.2.x, has to translate the build instructions into their own environment before the first example compiles.
The third is that this is not the kernel's own documentation, and it is not a reference implementation either. It is a teaching sequence with a supplemental rbtree example, an apology about maintenance delays, and no releases. The GPL-2.0 licence means the code can be reused and modified under its terms, which is the right licence for the examples it is, and it also means any substantial reuse carries that licence into the derived work.
The alternative approach is to work from the kernel source tree itself. The samples/ directory in a kernel checkout contains the maintained versions of the same kinds of code, and they are updated by the kernel maintainers as the APIs change, so a reader who wants current idioms is better served there than in a tutorial pinned to one release. The difference in approach is that the kernel samples are minimal and current, with little narrative, while this repository gives you a sequenced path with an emulator that provides the hardware the exercises need, and that is the trade: a curriculum with a cost, against reference code without one.
Editorial conclusion
Adopt Linux-Device-Driver if you are learning kernel module development and want working code that matches a current kernel rather than the 2.6-era API in the book, since the examples were rewritten and the QEMU image gives you virtual hardware for the parallel port and bus exercises without owning the hardware. Do not adopt it as a reference for production driver code, since it is a teaching sequence with a note apologising for delayed maintenance and a baseline limited to one kernel on one distribution. Verify first that your kernel source tree matches the 7.2.x baseline and that KERNELDIR points at it, that the patched QEMU build from tools/ is what you run the examples in, since the parallel port exercises do not work on ordinary hardware, that you have read the workspace setup in docs/00_preface/00_dir_tree.md before creating LDD_ROOT, and that the license terms of GPL-2.0 suit whatever you intend to reuse.
Frequently asked questions
How do I build the Linux-Device-Driver examples?
Set the KERNELDIR environment variable to your kernel source directory and export it, then change into an example directory and run make. The Makefile uses KERNELDIR to decide which kernel source tree the drivers are built against.
What kernel version and distribution do these driver examples target?
The README lists the current test baseline as kernel Linux 7.2.x on host system Fedora release 44, and states that other kernel versions and host distributions are not tested.
Why does the project ship a patched QEMU?
The parallel port used for the I/O examples is barely found on real computers now, so the examples were moved into QEMU with a virtual parallel port device. The repository description adds that the patched QEMU includes virtual PCI, USB and serial devices, and the patch lives in the tools/ directory.
What is the LDD_ROOT workspace in Linux-Device-Driver?
It is the runtime workspace, kept separate from the tutorial checkout. The README points at the workspace setup in docs/00_preface/00_dir_tree.md to create it and install the helper scripts.
Which kernel topics do the numbered examples cover?
The sequence runs from 01_hello_world and 02_module_parameters through scull, procfs, completion, ioctl, the sleep and poll and notification examples, seeking, jit and jiq, I/O port and port remap and MMIO and IRQ examples, the PCI and USB skeletons, lddbus, and finally simple, zero_copy and async_io, with rbtree as a supplemental example.
Can I use these driver examples in my own project?
The repository is licensed under the GNU General Public License, version 2, which permits reuse and modification of the example code under those terms. Check how that fits your own licensing before copying substantial parts into a project.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/d0u9-linux-device-driver)Was this useful?