Linux Kernel Modules: Getting started

Published 22-Feb-202120 min
image

About The Linux Kernel Modules Series

As part of my research I had a number of situations where the Linux Kernel's functionality was just not enough. Thankfully, the developers foresaw these situations and thus we got the chance to extend the kernel using kernel modules. Kernel modules are relatively straightforward to write once you get the hang of it. Even though the kernel writing process has barely changed since 2007 when this guide was published. The kernels have advanced a bit and I am planning to give a new, updated and summarised version in the following.

Before you start

Disclaimer:

Kernel Development can be difficult and error-prone. Bugs are not easy to catch as a lot of the debugging tools are only available in user-space land. Moreover, catching and fixing bugs in the kernel takes more time as often a bug could mean an OS crash.

While useful in some cases, getting things right in the krenel-space land can be more trouble than it is worth. So, if you plan on doing kernel development for any other reason than sheer curiosity, I advise you to first consider whether there is not a more suitable user-space alternative that can be used.
For example, some network transport protocol extensions only used to work for TCP and were best designed in the kernel. However, many of these proposals can now be implemented in QUIC. QUIC is network transport protocol and can often be used to achieve similar tasks as TCP. QUIC has been accepted as an IETF standard with RFC 9000 in 2021.

Introduction

In this article I will cover the basics of what a kernel module is, how to write a kernel module, how to compile a kernel module, how to load and unload kernel modules. Before I finish the article I will a few more advanced notes and real examples, based on my work. I plan to revisit that section before the conclusion and may eventually create a follow-up article based on the content of that section if it becomes big enough to live as a standalone article.

What Is a Kernel Module

A kernel module is a piece of software that interacts directly with the core Operating System components and is executed directly into the kernel-space. This means that some basic operations such as division or outputting text to the standard output are performed differently.

Writing Your First Kernel Module

Disclaimer: When working with kernel modules, or any other piece of software that runs in the kernel-land, any unintended behaviour could result in a segmentation faults and stack overflows. This could leave your machine in a corrupted state that will require a reboot or reformatting of the operating system.
I recommend that at all times during development you use a virtual machine to avoid accidentally corrupting your main operating system.

The writing part of creating a kernel module is relatively easy, perhaps the easiest thing in the process. To write a kernel module, you need to:

  • Import the correct headers
  • Write your kernel code
  • Apply the relevant API hooks and link your module with the operating system, or otherwise make the host OS aware of how to use your module
I will explain how each of the steps above translates to the code of the de-facto standard "Hello world" example that many introductionary kernel development guides like to use. The code for the example is as follows:
TODO

Let us look at the specific pieces of the code and see how they relate to the steps above.

TODO

Now, let us save that module in a directory of your choice, I will save it to /home/mihail/kernel-dev-example/my_module.c. Next, we will look at how to compile the code we just saved.

Compiling Your First Kernel Module

To compile a kernel module, TODO

Using Your First Kernel Module

Loading Your Kernel Module

To load a kernel module TODO

Unloading Your Kernel Module
Introducing Changes to Your Kernel Module

Advanced Examples

Final Words

That is it... Thanks for following along, and I hope I have helped you in your first kernel module writing journey. The kernel module that we did here is not particularly useful but I hope I managed to demystify the basics of the process a bit. For more advanced example, take a look at the complete tutorial here. If I can find the time: I pledge to write an advanced guide that takes a look at extending the TCP stack.