Not just yet. Soon, but not just yet, since there is still one more lesson worth of kernel fundamentals we need to cover before you write, build and load your first kernel module. And you'll be using what you learn in this lesson almost immediately with that first kernel module of yours, so take your time and digest all of what follows here. It's important.
Most readers -- even those new to kernel programming -- know that a Linux loadable kernel module (or kernel module, or loadable module, or module, or LKM, etc, etc) is simply a compiled object file that you can load into kernel space, at which point it's now just another part of the running kernel and provides some functionality that wasn't there before.
The benefits of loadable modules should be obvious. Anything which is running in kernel space takes up RAM, so the larger your kernel, the more RAM it's consuming. If you need some functionality only rarely, you can build that functionality as a loadable module and load it as needed, and unload it afterwards.
In addition, loadable modules give you the opportunity of writing, say, a new device driver, then loading it, testing it, identifying bugs, unloading it, fixing it, recompiling it, reloading it, and so on, all without rebooting your system. It should be obvious that this is the perfect vehicle for new device driver development. But one last point.
Many people use the phrases "module" and "device driver" interchangeably. Technically, that's a bit sloppy. While loadable modules are primarily used for device drivers, they can certainly be used for other purposes -- you'll see later in this course how to write and load modules that help you debug the kernel. So while we'll certainly be referring to device drivers constantly throughout the rest of this course, try to keep the above distinction in mind.
Almost certainly. In fact, it would be astonishing if it didn't since all modern Linux distros come with a massive number of loadable modules ready to go. But there are exceptions.
You could, if you wanted to, configure and build a kernel that had no module support whatsoever. From the kernel configuration menus you saw in the earlier lessons, here's the section related to loadable modules:
--- Enable loadable module support [ ] Forced module loading [*] Module unloading [ ] Forced module unloading [*] Module versioning support [*] Source checksum for all modules
I'm not going to spend any time explaining the above because it's highly unlikely you'll ever need to mess with it. In special cases where you're building a tiny embedded system, you might want to configure a kernel with everything built in and no module support whatsoever, but that's unusual and we won't discuss it any further, at least for now. Onward.
Because I like to be precise, let me explain the two different types of "names" we'll use to refer to kernel modules from now on.
First, there's what you might think of as the, say, simple name, such as
lzo, as in, "Of course you can't mount that USB stick, you haven't loaded the
vfat module, silly!" In this situation, the name
vfat clearly identifies a particular module, and this type of name is the proper form to use in a number of module-related commands.
On the other hand, at times, you'll need to refer to the actual filename containing the loadable module code, such as
vfat.ko, either as a relative pathname or possibly fully-qualified if you need to specify precisely where to find it. I mention this difference since some module commands expect to get a simple module name (like
vfat) and they'll take it from there, whereas others need a precise filename (like
vfat.ko). You'll be able to recognize the difference shortly.
And one more point. Readers who have been around since version 2.4 of the kernel might remember that loadable modules used to be stored in files with a normal object suffix of
.o. Nowadays, the file prefix is
.ko, short for "kernel object," otherwise known as a module.
For the rest of this lesson, we'll be working with the LKMs that correspond to your currently running kernel, and it won't make much difference if you're running your distro's official, latest kernel or the kernel you configured and built yourself. Either way, you should be able to run everything you see here, with the only difference probably being some version numbers or other irrelevancies. In my case, I'm running my hand-rolled kernel with the name
3.3.0-rday+ which is why you might see that name string popping up on occasion.
First, where are all the modules that already exist for your running kernel? You might remember that they're all under
/lib/modules/, in a separate subdirectory for each installed kernel. My system currently looks like this:
$ ls -1 /lib/modules 3.0.0-12-generic 3.0.0-13-generic 3.0.0-14-generic 3.0.0-15-generic 3.0.0-16-generic 3.0.0-17-generic 3.3.0-rc7 3.3.0-rday+ $
and I can see which kernel I'm running with:
$ uname -a Linux oneiric 3.3.0-rday+ ... snip ... $
so if I wanted to list all of the modules available for a particular kernel, I could run a simple
find command of the form:
$ cd /lib/modules/3.3.0-rday+ $ find . -name "*.ko" ./kernel/lib/ts_fsm.ko ./kernel/lib/crc-itu-t.ko ./kernel/lib/crc-ccitt.ko ./kernel/lib/raid6/raid6_pq.ko ./kernel/lib/libcrc32c.ko ./kernel/lib/bch.ko ./kernel/lib/crc7.ko ... lots snipped here ... $
Shortly, we'll be picking on some of these modules as we experiment loading and unloading them.
By the way, you can always get the version of the running kernel with the command
$ uname -r 3.3.0-rday+ $
which is handy since you can automate generating the name of the appropriate modules directory with either of
/lib/modules/`uname -r` or
/lib/modules/$(uname -r). This is useful to remember since it allows you to write, say, shell scripts that manipulate modules, knowing that no matter what kernel version you're running, you'll be accessing the appropriate modules directory.
Easy -- there's the
$ lsmod Module Size Used by nls_iso8859_1 12713 1 nls_cp437 16991 1 vfat 17461 1 fat 61230 1 vfat rfcomm 46622 8 bnep 18144 2 kvm_intel 132467 0 kvm 404372 1 kvm_intel ... etc etc ...
In fact, as the man page for
lsmod makes clear, "lsmod is a trivial program which nicely formats the contents of the /proc/modules [file], showing what kernel modules are currently loaded." So you could just as easily have done:
$ cat /proc/modules nls_iso8859_1 12713 1 - Live 0x0000000000000000 nls_cp437 16991 1 - Live 0x0000000000000000 vfat 17461 1 - Live 0x0000000000000000 fat 61230 1 vfat, Live 0x0000000000000000 rfcomm 46622 8 - Live 0x0000000000000000 bnep 18144 2 - Live 0x0000000000000000 kvm_intel 132467 0 - Live 0x0000000000000000 kvm 404372 1 kvm_intel, Live 0x0000000000000000 ... etc etc ...
I think you can see the obvious aesthetic advantage of
lsmod. We'll stick with that.
As a simple example of loading and unloading a single module, let's pick an example that we'll almost certainly have, regardless of which kernel we're running. From under the appropriate
/lib/modules directory, I'm going to experiment on the module that provides support for the Btrfs filesystem,
kernel/fs/btrfs/btrfs.ko (If you're doing this on a system that actually uses the Btrfs filesystem, then you'll need to select some other arbitrary module for the rest of this lesson.)
In a nutshell, run the following commands that verify that that module is not loaded, then load it, then check again:
$ lsmod | grep btrfs $ sudo modprobe btrfs $ lsmod | grep btrfs btrfs 683103 0 zlib_deflate 26914 1 btrfs libcrc32c 12644 1 btrfs $
Clearly, that module was loaded, and dragged a couple more modules along with it. And when you're done with it (and since you don't actually need it), simply unload it:
$ sudo modprobe -r btrfs $ lsmod | grep btrfs $
Yes, it's really that simple. Now some notes about the above.
First, you need root privilege to run
modprobe. Since we're running Ubuntu, we'll use the
sudo utility. If you're running a different distro, figure out what it takes.
Next, you'll notice that loading that single module automatically dragged in its two dependencies that were not yet loaded. That's how
modprobe works -- it examines the dependency information in the corresponding
modules.dep file for the running kernel where, in our case, it would eventually find something resembling the following:
... kernel/fs/btrfs/btrfs.ko: kernel/lib/zlib_deflate/zlib_deflate.ko kernel/lib/libcrc32c.ko ...
And, finally, there are a couple simpler (and older) utilities for loading and unloading modules --
rmmod -- but they aren't as sophisticated and don't handle dependencies, so we're going to avoid them for now. But they will suddenly become important when we start loading and unloading the modules we write. You'll see that in the next lesson.
If you just want to know about the attributes of a particular module, there's the terrific command
$ modinfo btrfs filename: /lib/modules/3.3.0-rday+/kernel/fs/btrfs/btrfs.ko license: GPL alias: devname:btrfs-control alias: char-major-10-234 srcversion: 48860D16F770F239F8DF2B7 depends: libcrc32c,zlib_deflate intree: Y vermagic: 3.3.0-rday+ SMP mod_unload modversions $
Note that since that's just an informational command, it doesn't require root privilege, and also note that it lists the module's dependencies.
In addition, it doesn't matter if the module is loaded or not,
modinfo works equally well. Feel free to check the man page for that command to see how specific you can be in what information you're asking for.
Up to now, everything laying the groundwork for finally writing our first loadable kernel module has been fairly straightforward. So let's push the envelope a bit to finish this lesson off and show you something you might not have seen before.
Future lessons are going to get into working in the kernel address space, and which symbols are available in that address space and which aren't, and how loading your module affects what gets added. Well, let's look at the kernel address space symbol table right now:
$ less /proc/kallsyms 0000000000000000 D irq_stack_union 0000000000000000 D __per_cpu_start 0000000000000000 D gdt_page 0000000000000000 d exception_stacks 0000000000000000 d tlb_vector_offset 0000000000000000 d cpu_loops_per_jiffy 0000000000000000 D xen_vcpu_info 0000000000000000 D xen_vcpu 0000000000000000 d idt_desc ... etc etc ...
That listing typically goes on for tens of thousands of lines, and represents the various types of symbols and their corresponding addresses in the kernel address space. We'll be digging into that output in far more detail in a later lesson.
At this point, we've covered everything you'll need to finally write, compile and load your very first LKM. And that's what's coming in the next lesson. You seriously don't want to miss that.