Open-source project
martinezjavier/ldd3 avatar
martinezjavier/ldd3

martinezjavier/ldd3: making the Linux Device Drivers 3 examples compile again

Linux Device Drivers 3 examples updated to work in recent kernels

2,604 stars943 forksCNOASSERTION

At a glance

What is it?
The LDD3 sample drivers stopped building years ago. This fork keeps them alive against recent kernels, and its value is mostly as a teaching aid for people already reading the book.
Who is it for?
Adopt martinezjavier/ldd3 if you are working through Linux Device Drivers 3 and need scull, sbull or snull to load on a kernel you can actually boot.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 34 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why the LDD3 examples stopped building

Linux Device Drivers 3 was published by O'Reilly, and its example drivers target the 2.6 kernel series. The README states the problem plainly: the book "is now a few years old and most of the example drivers do not compile in recent kernels." Kernel APIs used by driver code move. Registration functions get renamed, file_operations members change signature, and helpers that were exported in 2.6 are gone or replaced. A reader who downloads the original code from the O'Reilly examples page and runs make against a current kernel gets compiler errors, not a working module.

This repository is a maintenance fork, not a new driver framework. Its stated aim is narrow: "keep LDD3 example drivers up-to-date with recent kernels." The original code is still available at examples.oreilly.com/9780596005900, and the homepage for this project points there. So the audience is specific: someone with the book open, trying to follow a chapter, who needs the code to compile on a kernel from this decade.

What is in the tree: scull, sbull, snull and friends

The top-level Makefile lists the subdirectories that get built. They are the driver families the book walks through: skull, scull, scullc, scullp, sculld, scullv, short, shortprint, simple, tty, pci, usb, sbull, snull, plus lddbus and the misc-modules and misc-progs directories. Each is a separate module with its own Makefile, and the top-level target loops over them:

make
SUBDIRS =  misc-progs misc-modules \
           skull scull scullc scullp lddbus sculld scullv shortprint simple tty \
	   pci usb\
	   sbull snull short

The build rule is a shell loop, not a recursive make in the usual sense: for each name it runs $(MAKE) -C $$n and exits on the first failure. That detail matters in practice. If one module fails to compile against your kernel, the loop stops there and the later subdirectories never get built. You will not get a partial build of everything else. The include/ directory holds shared headers, and scull-shared/ holds code common to the scull variants, so the scull family is not a set of copies.

This layout is a deliberate choice to mirror the book's chapter order rather than to produce one installable artifact. There is no single kernel module at the end. You build a directory of .ko files and load the one the chapter you are reading is about.

Building the modules against your kernel

The README gives the compile procedure. You need a clone of this repository and a clone of a kernel tree, then you point KERNELDIR at the kernel source and run make. The README uses the Linus tree in its example, and it also mentions linux-next as the tree the drivers should compile against:

bash
$ git clone git://github.com/martinezjavier/ldd3.git
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ export KERNELDIR=/path/to/linux
$ cd ldd3
$ make

Set KERNELDIR to the path of the kernel tree you cloned, then run make from the ldd3 directory. Because the top-level rule stops at the first failing subdirectory, read the output rather than assuming a clean run. If a module fails, the error names the subdirectory, and you can cd into it and rerun make there while you work out which API changed.

For editor support, the README describes an Eclipse CDT setup that relies on a symlink named linux_source_cdt in the project directory pointing at the kernel headers. On a machine with kernel headers installed, the command given is:

bash
ln -s /usr/src/linux-headers-`uname -r`/ linux_source_cdt

The .project and .cproject files in the repository were set up for that layout. If you do not use Eclipse, the symlink is harmless but unnecessary. Note that the README does not document how to unload the modules, how to clean up device nodes, or how to roll back after loading a module that misbehaves; for that you are back to the book and to standard modprobe and rmmod behaviour.

The kernel versions this fork is actually known to build on

The README keeps a list titled "Latest Tested Kernel Builds." It is the most useful page in the repository and also the most limiting. The entries are Ubuntu 18.04 kernel 5.4.0-42-generic as of July 2020, Ubuntu 20.04 kernel 5.4.0-73-generic as of July 2021, Yocto poky warrior for qemu aarch64 at 5.0.19, Yocto poky hardknott for qemu aarch64 at 5.10.46, Buildroot 2019.05 at 4.9.16, Buildroot 2021.02 at 5.10, and Alpine 3.13 at 5.10.29-lts as of May 2021.

That list is a snapshot of what someone got working, not a support matrix. Nothing in the README claims the drivers build on every kernel after 5.10. The repository's last push was on 2026-08-27, so work has continued, but the tested-build list has not been extended in the README. Treat a kernel newer than the list as untested until you compile it yourself. If you are on a distribution kernel from 2024 or later, expect to spend time on compile errors in whichever module you need, and expect those errors to be the point of the exercise if you are reading the book.

Where ldd3 is the wrong tool

These are teaching modules. scull allocates memory and pretends to be a device; sbull simulates a block device backed by RAM; snull is a fake network interface. None of them drives real hardware, and none is written to the standards you would want in a shipped driver. If you need a working driver for a real PCI card or USB device, the pci/ and usb/ directories here show the shape of the registration calls, but you should be reading the kernel's own Documentation/ tree and the in-tree drivers for your subsystem instead.

There is a second, sharper limitation. The README's compile instructions assume you have a full kernel source tree and can build against it. If you only have distribution headers, some of these modules will not build, because they pull in kernel internals that headers alone do not expose. And because the top-level make stops at the first failure, a single bit-rotted module blocks the rest of the build. You can work around that by building subdirectories individually, but the README does not tell you to, and a newcomer running plain make may conclude the whole repository is broken when only one driver is.

How this differs from writing against the current kernel directly

The obvious alternative is to skip the book's code and start from the kernel source itself: the in-tree drivers under drivers/, plus Documentation/ and the sample code the kernel tree carries. That path gives you code that is maintained in lockstep with the kernel, because it is the kernel. The difference in approach is not quality, it is pedagogy. In-tree drivers are written for a specific piece of hardware and assume you already know the subsystem. The LDD3 examples are written to isolate one concept per chapter, which is why scull exists at all.

A second alternative is the original O'Reilly tarball. It is the same code before this fork's fixes, and the README's whole premise is that most of it no longer compiles. If you are on an old kernel, the original may be closer to what the book's text describes line by line, since the fork's edits change code the book quotes. If you are on anything modern, the fork is the only one of the two that has a chance of building.

The project's own issue tracker at github.com/martinezjavier/ldd3/issues is where the README directs bugs, comments and patches. That is the channel for a fix if a module breaks on your kernel.

Licence and what the repository does not state

The repository carries a LICENSE file at the top level, but the project metadata reports the licence as NOASSERTION, meaning no standard licence identifier was detected. The kernel's own licensing rules apply to any module you build against a kernel tree, and the original LDD3 example code carries its own terms from O'Reilly. If you intend to reuse any of this code outside personal study, read the LICENSE file and the original source's terms yourself; nothing in the README explains the licensing of the examples, and this article is not legal advice.

On upgrade cost: the README lists no releases and no changelog, so there is no versioned upgrade path. You track the master branch, and when a kernel API changes you find out at compile time. The Makefile's fail-fast loop means the first broken module is the only one you see until you fix it. Budget for that: a kernel upgrade is not a dependency bump here, it is a round of compile fixes in whichever subdirectories you actually use.

Editorial conclusion

Adopt martinezjavier/ldd3 if you are working through Linux Device Drivers 3 and need scull, sbull or snull to load on a kernel you can actually boot. Do not adopt it as production code: the modules are teaching samples, the tree is a collection of independent subdirectories with no shared build product, and the README lists tested kernels only up to 5.10.x. Before you start, verify three things: that KERNELDIR points at a kernel tree you can build against, that your kernel version is close to one of the tested builds listed in the README, and that the module you want (scull, sbull, snull, short, tty, usb) still exists in SUBDIRS in the top-level Makefile.

Frequently asked questions

What is martinezjavier/ldd3?

It is a fork of the Linux Device Drivers 3 example drivers, updated so they compile against recent kernels. The README says the book is now a few years old and most of the example drivers do not compile in recent kernels, and that the project aims to keep them up to date.

How do I compile the ldd3 example drivers?

Clone the repository and a kernel tree, export KERNELDIR to the path of that kernel source, then run make from the ldd3 directory. The README's example uses the Linus tree, and notes the drivers should compile against linux-next.

Which kernel versions are tested with these drivers?

The README's Latest Tested Kernel Builds list names Ubuntu 5.4.0-42-generic and 5.4.0-73-generic, Yocto poky warrior 5.0.19 and hardknott 5.10.46, Buildroot 4.9.16 and 5.10, and Alpine 5.10.29-lts. Nothing in the README claims support beyond those entries.

How does Linux handle device drivers?

That is a question about the kernel, not about this repository. The LDD3 example modules show the registration and file_operations patterns the book describes, but the README does not document how the kernel handles drivers in general.

Is the Linux kernel open source?

This repository does not address that question. The README only points at kernel trees to clone for building the examples, including the Linus tree and linux-next.

Official sources

  1. Issues
  2. martinezjavier/ldd3 on GitHub
  3. Project website
  4. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/martinezjavier-ldd3.svg)](https://hysenlabs.com/projects/martinezjavier-ldd3)