Linux Device Driver Programming Lecture 21- Building a linux kernel module

  • Post author:
  • Post category:Blog

 

Building a linux kernel module

 

 

In this article, let’s learn how to build a kernel module.

Kernel modules can be built in two ways: statically linked against the kernel image or as dynamically loadable modules.

We will be writing and using dynamically loadable kernel modules for most of the exercises. Let’s say you want to build a kernel module as a dynamically loadable kernel module.

Dynamically loadable kernel modules
Figure 1. Dynamically loadable kernel modules

 

One is In tree module, and another one is an Out of tree module.

 

What exactly is an In tree module?

In tree, modules means internal to the linux kernel tree.

For example, in the earlier articles, you actually ran a command modules, make modules to build all dynamically loadable kernel modules of the Linux kernel. All those modules are called as In tree modules. That means, they are internal to the linux kernel tree.

 

What exactly is an out of tree module?

It is external to the linux kernel tree. The module that we just wrote, our hello world module, it is an Out of tree module.

Loading Out of tree module taints the kernel. That is, kernel issues a warning saying Out of tree module has been loaded. This is just a warning from the kernel, and we can safely ignore this warning. You will see that when you load that module to the kernel.

 

Basically, out of tree means outside of the Linux kernel source tree. The modules which are already part of the Linux kernel are called In tree modules. That is approved by the kernel developers and maintainers.

When you write a module separately (which is not approved and may be buggy), build and link it against the running kernel, then it’s called as out of the tree module. Hence when you load an out of tree kernel module, kernel throws a warning message saying it got tainted. That is, a taint flag will be set in the kernel.

Let’s explore building a kernel module as Out of tree. Later will also explore In tree building.

 

Importance of the Kernel Build System (“kbuild”):

Modules are built using “kbuild” which is the build system used by the Linux kernel. Doesn’t matter whether it is a static module or dynamic module, modules are built using  “kbuild”, that is, the kernel build.

Modules must use “kernel build system” to stay compatible with changes in the build infrastructure and to pick up the right flags to GCC.

 

When you compile a user-level program, what do you do?

You use a compiler called GCC, and you use various compiler flags, you use various linker flags to compile your program, So the same procedure we have to follow here, but while building a kernel module, you need not worry about what kind of compiler switches or compiler arguments you have to use the compiler. You have to invoke the kernel build system, and the kernel build system will take care of using the right compiler switches to the compiler.

To build external modules, you must have a prebuilt kernel source available that contains the configuration and header files used in the build. Basically, we have already installed the kernel source. We will be building our module against that prebuilt kernel source.

This ensures that as the developer changes the kernel configuration, his custom driver is automatically rebuilt with the current kernel configuration. If you need more information about building a module using  “kbuild,” you can go through the kernel documentation at this path.

 

There are some important note I would like to mention, so please remember that when you are building an Out of tree module, you need to have a complete and pre-compiled kernel source tree on your system. This we have already done. We have downloaded the kernel source tree and built it. The reason is modules are linked against object files found in the kernel source tree. 

You cannot compile your module against one Linux kernel version and load it into the system, which is running kernel of a different version. The module load may not be successful, and even if it is successful, you will encounter runtime issues with the symbols.  That’s why the thumb rule is “Have a precompiled  Linux kernel source tree on your machine and build your module against that”. 

There are two ways to obtain a prebuilt kernel version. Download the kernel from your distributor and build it by yourself. This is what we did, or install the Linux- headers-of the target Linux kernel.

Let’s say you have an embedded system where the board is already running a Linux kernel of some different version. And now you have to write a driver for that board. What you do is, you try to get the kernel source of that running Linux kernel version.

So, if you don’t get the full Linux source, then at least try to download the Linux headers of the target Linux kernel version. And build your module against that. As I said, you cannot compile your module against one Linux kernel version and load it into the system which is running a different kernel version. Don’t try to do that.

That’s a reason why we downloaded the Linux kernel source from the beagle bone repository, compiled it, and updated the Linux kernel image in the target.

Now, the version of the target Linux kernel and version of the source that we have got in our system is the same. We are just going to build our module against the source what we have installed.

 

Let’s see the procedure to build an Out of tree kernel module(Figure 2).

Figure 2. Building a kernel module(out of tree)
Figure 2. Building a kernel module(out of tree)

 

And maybe in the next article, let’s explore building an In tree kernel module. Above command you have to use.

A very simple command, you just have to use make command, that’s it. Now the idea here is you have to trigger the top-level makefile of the Linux kernel source tree, that’s a key thing here. And to trigger top-level makefile of the Linux kernel source tree, we use -C switch with the make.

When you execute make -C, make first enters into the Linux kernel source tree, and it executes a top-level make file.

That’s how kernel build system triggers. And when the make invokes top-level make file, all the compiler switches, the dependency lists, version string, everything will be utilized to build your kernel module. When make invokes the top-level makefile, you then have to direct the top-level makefile to your local makefile or a local folder where you have kept your Out of tree module source.

And we direct the top-level make file to our local folder by using the variable M. M is equal to you have to give path to your module source. And after that, this command also includes target options. 

First, you have to use make -C, path to the Linux kernel tree to invoke the top-level makefile of the kernel source tree, and when make invokes the top-level makefile of the Linux kernel tree, the kernel build system triggers, and you have to use the variable M to direct the build flow to enter into your local folder where you have kept your module source file. 

 

This is a command syntax in short make -C kernel directory and M=path to the local module, and then you have to mention targets.

Figure 3. Command syntax
Figure 3. Command syntax

 

We will explore the targets later. Now, for the targets, you can use these options, as shown in Figure 4.

Building a linux kernel module
Figure 4. Target options

 

If you want to build a module, then use command modules. If you want to install the module, then use a command modules install. If you want to clean up all the generated files in the module directory, then use clean. And if you want to get any help, then you just use help command here. These are the different targets.

We have already used these targets. We have used modules, we have used modules_install, the same target option you can use with this command. 

 

Let’s see creating a local makefile as shown in Figure 5. As I said, the top-level makefile will invoke the local makefile. This you need to create by yourself. In the local makefile, you should define a kbuild variable like below.

Building a linux kernel module
Figure 5. Creating local Makefile

 

You have to use a kbuild variable called obj- you can use three different values here n,y, or m. And after that, you have to mention the module_name .o

 

Let’s understand how to create a local makefile.

In the local makefile you should define a kbuild variable like obj-<X> := <module_name>.o. You have to use the kbuild variable obj- and you have to use the appropriate option. And then equate that to your module_name .o. Here, ‘X‘ takes one of the values. It could be n, or it could be y, or it could be m. If it is n, that means do not compile the module. When your kbuild system visits the local folder, it reads the local makefile, and it reads this variable obj- it could be n,y, or m. If it is y, that means compile the module and link with the kernel image. That means, it’s a static module if it is y. If ‘X‘ is m, then compile as a dynamically loadable kernel module.

All you need to do is, you have to create a make file and write this statement obj-m := main.o (as in Figure 6).

Building a linux kernel module
Figure 6. Kbuild variable

 

Let’s say I have a kernel module source file main. c and I want to build it as a dynamically loadable kernel module, and then I would just mention obj-m := main.o. When the kernel build system sees this statement, the kbuild system will build main.o, that is, object file from main.c, and after linking, it will result in the kernel module, main. ko.

Remember that you should not mention main.c here. main.c is a source, our target is main.o object file. That’s why you have to write main.o.

So, the kernel build system creates the target that is main.o, and after linking, the kernel module main.ko will be generated.

I hope you get the idea and let’s try all these things practically on our hello world kernel module, and I will see you in the next article.

 

Get the Full Course on Linux Device Driver(LDD1) Here.

FastBit Embedded Brain Academy Courses

Click here: https://fastbitlab.com/course1

 

FastBitLab

The FastBit Embedded Brain Academy uses the power of internet to bring the online courses related to the field of embedded system programming, Real time operating system, Embedded Linux systems, etc at your finger tip with very low cost. Backed with strong experience of industry, we have produced lots of courses with the customer enrolment over 3000+ across 100+ countries.