Writing a simple FreeBSD kernel module
I’ve been learning more about Operating Systems, specifically what’s going on behind the scenes. In parallel, I’ve been trying to learn some C.
Certainly I know more than most about Operating Systems already, though by most I mean among everyone in the world. That’s not a particularly high bar at all if you think about it for a second.
I’m comfortable writing scripts and small programs in Go and Python, but Operating Systems are build in ASM and C/C++ almost exclusively these days (shout-out to Redux though) and with most of the code examples in the more long-standing OS textbooks appearing in C, I have been pushed far enough to want to learn.
Writing a very basic kernel module seemed like low-hanging fruit, at least with FreeBSD in mind. So here’s how you can do it too.
Head on over to freebsd.org and grab the OS in whichever format suits you. This article was written using 11.1-RELEASE. Personally I am running Veertu on macOS Sierra and it runs fine like that. It doesn’t need to be a particularly beefy VM (assuming you’re using a VM), so you can afford to be stingy.
Get the FreeBSD source
The source is packaged such that you’ll probably want to extract it at the root directory; it’ll all end up in
/usr/src that way.
Grab it by running the commands below.
Write the module
Now for the fun bit. I’ll split this up so that I’m not just giving you code to copy paste.
First, include the necessary headers from the FreeBSD source. Of note here are the
module.h includes, the latter of which you should read over to learn more about what’s going on in this article.
Now we want to define our event handler. This is a function with a specific prototype akin to all other modules.
The only parameter we care about is
event_type, an enum defined in
<sys/module.h> which tells us which event was triggered to call the function.
Nice and easy, no? If we’re loading, say so; if we’re unloading, say so; if we’re doing something but neither loading nor unloading, return a ‘not supported’ error.
Next, you want to create your
struct is used when the module is being declared to the kernel in the next section. It defines the name of the module, the function to be called to handle various module events (e.g. load, unload) and a
void pointer which can contain extra information (haven’t learn exactly what yet!).
Finally, we want to use a special macro to register the module with the kernel;
All in all, you should have something like this.
To make things easier, steal this Makefile.
make load it and
make unload it!
And there you have it!
As with most powerful systems software, FreeBSD kernel modules are written in C. Using the kernel source and a little know-how shared by FreeBSD hackers, it has been easy for me to get to grips with the very basics of writing a loadable kernel module.