How to: Compile Linux kernel modules

by LinuxTitli · 22 comments

This is one the essential and important task. Many time we upgrade our kernel and some precompiled drivers won't work with Linux. Especially if you have weird hardware; then vendor may send you driver code aka C files to compile. Or even you can write your own Linux kernel driver. Compiling kernel driver is easy. Kernel 2.6.xx makes it even much more easier. Following steps are required to compile driver as module:

1) You need running kernel source code; if you don't have a source code download it from kernel.org. Untar kernel source code (tar ball) in /usr/src using tar command:
$ tar -zxvf kernel* -C /usr/src

To be frank kernel headers are more than sufficient to compile kernel modules / drivers. See how to install kernel headers under Debian / Ubuntu Linux or RHEL / CentOS / Fedora Linux.

2) Next go to your kernel module source code directory and simply create the Makefile file as follows (assuming your kernel module name is foo):
$ vi Makefile

3) Add following text to it:

obj-m = foo.o
KVERSION = $(shell uname -r)
all:
        make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
        make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

4) Compile module using make command (module build can be done by any user) :
$ make
It will finally creates the foo.ko module in current directory. You can see all actual compile command stored in .foo* files in same directory.

5) Once module compiled successfully, load it using insmod or modprobe command. You need to be root user or privileged user to run insmod:
# insmod foo.ko

Example: hello.c module

1) hello.c C source code. Copy following code and save to hello.c
$ mkdir demo; cd demo
$ vi hello.c

2)Add following c source code to it:

#include <linux/module.h>       /* Needed by all modules */
#include <linux/kernel.h>       /* Needed for KERN_INFO */
#include <linux/init.h>         /* Needed for the macros */

static int __init hello_start(void)
{
printk(KERN_INFO "Loading hello module...\n");
printk(KERN_INFO "Hello world\n");
return 0;
}

static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbye Mr.\n");
}

module_init(hello_start);
module_exit(hello_end);

This is an example modified from original source for demonstration purpose.

3) Save the file. Create new Makefile as follows:
$ vi Makefile
Append following make commands:

obj-m = hello.o
KVERSION = $(shell uname -r)
all:
        make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
        make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

4) Save and close the file.

5) Compile hello.c module:
$ make

6) Become a root user (use su or sudo) and load the module:
$ su -
# insmod hello.ko

Note you can see message on screen if you are logged in as root under run level 3.

7) Verify that module loaded:
# lsmod | less

8) See message in /var/log/message file:
# tail -f /var/log/message

9) Unload the module:
# rmmod hello

10) Load module when Linux system comes up. File /etc/modules use to load kernel boot time. This file should contain the names of kernel modules that are to be loaded at boot time, one per line. First copy your module to /lib/modules/$(uname -r)/kernel/drivers. Following are suggested steps:

(a) Create directory for hello module:
# mkdir -p /lib/modules/$(uname -r)/kernel/drivers/hello
(b) Copy module:
# cp hello.ko /lib/modules/$(uname -r)/kernel/drivers/hello/
(c) Edit /etc/modules file under Debian Linux:
# vi /etc/modules
(d) Add following line to it:
hello
(e) Reboot to see changes. Use lsmod or dmesg command to verify module loaded or not.
# cat /proc/modules
OR
# lsmod | less

See also:

  • Read man pages of lsmod, rmmod, modprobe, modules
  • Documentation located in your kernel source directory (for example /usr/src/linux-2.6.xx.xx/Documentation/) and README file located under kernel source code tree /usr/src/linux-2.6.xx.xx/README
  • Read TLDP.org tutorial online.

Featured Articles:

Want to read Linux tips and tricks, but don't have time to check our blog everyday? Subscribe to our daily email newsletter to make sure you don't miss a single tip/tricks. Subscribe to our weekly newsletter here!

{ 22 comments… read them below or add one }

1 Anonymous 08.23.05 at 10:33 am

Aha … intresting gone try this.

2 swift 05.04.07 at 3:28 am

hi when i compile this by running make file this type of erro occcur …what to do

make -f make
make -C /lib/modules/2.6.18-1.2798.fc6/build M=/home/mclamna modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-1.2798.fc6-i686′
scripts/Makefile.build:17: /home/mclamna/Makefile: No such file or directory
make[2]: *** No rule to make target `/home/mclamna/Makefile’. Stop.
make[1]: *** [_module_/home/mclamna] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.18-1.2798.fc6-i686′
make: *** [all] Error 2

3 shan 01.18.08 at 6:23 am

dis s wat i encountered wen using

CHK include/linux/version.h
CHK include/linux/utsrelease.h
HOSTCC scripts/basic/fixdep
In file included from /usr/include/bits/posix1_lim.h:153,
from /usr/include/limits.h:145,
from /usr/lib/gcc/i486-linux-gnu/4.1.2/include/limits.h:122,
from /usr/lib/gcc/i486-linux-gnu/4.1.2/include/syslimits.h:7,
from /usr/lib/gcc/i486-linux-gnu/4.1.2/include/limits.h:11,
from scripts/basic/fixdep.c:113:
/usr/include/bits/local_lim.h:36:26: error: linux/limits.h: No such file or directory
In file included from /usr/include/sys/socket.h:35,
from /usr/include/netinet/in.h:24,
from /usr/include/arpa/inet.h:23,
from scripts/basic/fixdep.c:115:
/usr/include/bits/socket.h:310:24: error: asm/socket.h: No such file or directory
scripts/basic/fixdep.c: In function ‘use_config’:
scripts/basic/fixdep.c:204: error: ‘PATH_MAX’ undeclared (first use in this function)
scripts/basic/fixdep.c:204: error: (Each undeclared identifier is reported only once
scripts/basic/fixdep.c:204: error: for each function it appears in.)
scripts/basic/fixdep.c:204: warning: unused variable ‘s’
scripts/basic/fixdep.c: In function ‘parse_dep_file’:
scripts/basic/fixdep.c:300: error: ‘PATH_MAX’ undeclared (first use in this function)
scripts/basic/fixdep.c:300: warning: unused variable ‘s’
make[1]: *** [scripts/basic/fixdep] Error 1
make: *** [scripts_basic] Error 2

4 Nitin 05.24.08 at 4:56 pm

Hi swift, I guess u have not created Makefile in ur present directory, plz make sure that makefile name is correct and its case sensitive, it should be ‘Makefile’.

5 Nitin 06.03.08 at 2:22 pm

Hi, This was very much helpful but now I’m stuck because i didn’t understand how this particular makefile is working, so i’m not able to write it for multiple files. Please could anyone explain how this makefile works with a example for multiple files.
Thanks,
Nitin.

6 john 06.06.08 at 7:27 pm

how to cross compile lkm for arm?

7 Mohammad 08.11.08 at 4:21 pm

Dear Vivek ,
Thanks alots for yr teaching.
i compile a new module on fedora core 6 and make it very good. but in fedora i dont know how to submit for when linux start up , can load automaticly. i didnot find /etc/modules in fedora.

8 touristguy87 11.04.08 at 6:19 am

I followed the instructions as written even copying and pasting the code, I got nada.

I was able to install the headers using
apt-get install linux-headers-$(uname -r)

then I copied and pasted the hello.c text and the Makefile from this page but I got nothing.
make: Nothing to be done for ‘all’.

I must be missing something

this is in Ubuntu 8.04

9 touristguy87 11.08.08 at 6:56 am

ok I got it somehow, honestly I am not sure how but I patched my install (now running kernel-headers 2.6.24-21 generic) and rebooted, sudo -i, just tried running make and it worked.

before I was getting “can’t find target ‘make’ error that seems so common. It now is working!!!

10 mangesh 11.20.08 at 10:49 am

how do I cross compile a module using kbuild. Please help

11 mix 01.07.09 at 2:53 am

The reason that make: Nothing to be done for ‘all’ is you should modify the Makefile, replace the space in each make command with tab.

12 kernelmodule 01.22.09 at 11:48 am

After executing the insmod the message is not being displayed…Can u pls guide me on whats goin wrong?

13 scrat 01.23.09 at 8:25 pm

Oh, big thanks, source of Makefile is very helpful.

14 Victor 05.18.09 at 4:36 pm

Hi,

I’m trying to compile your hello.c module in a Fedora Core 9 with a 2.6.27.21-78.2.41.fc9.i686 kernel. My gcc compiler is 4.3.0 20080428 (Red Hat 4.3.0-8) (GCC). My kernel-devel package is installed with my current kernel version.

When I try to compile I get the following:

root@leela:[~/pruebas-modulos]$ make
make -C /lib/modules/2.6.27.21-78.2.41.fc9.i686/build M=/root/pruebas-modulos modules
make[1]: se ingresa al directorio `/usr/src/kernels/2.6.27.21-78.2.41.fc9.i686′
Building modules, stage 2.
MODPOST 0 modules
make[1]: se sale del directorio `/usr/src/kernels/2.6.27.21-78.2.41.fc9.i686′

root@leela:[~/pruebas-modulos]$ ls
hello.c hello.o Makefile Module.markers modules.order Module.symvers
root@leela:[~/pruebas-modulos]$

As you can see I do not obtain the .ko file. I have searched across the web in order to understand why I am not getting my .ko file, but I am not able to find anything useful. I would appreciate if you could help me to find why the makefile is not working

Thanks in advance,
Víctor.

15 tonychen123@qq.com 06.05.09 at 4:25 am

Hey, check that you makefile if you make a mistake with “obj-m” with “obj_m”, I have the same problem as you do.
When I write “obj-m” instead of “obj_m”, everything goes good.

16 reveil 07.27.09 at 10:53 am

Be sure you have tabs instead of spaces in the Makefile. Obvious and common mistake but took me a few minutes to figure this out after copy-pasting.

17 shreyas karmahe 08.24.09 at 5:42 am

hi,
could u please tell me how can i install the kernel updates as I despirately need linux source code.

18 blaine 09.23.09 at 5:30 pm

Thank you for posting this. It is very hard to figure out how to just make a single module manually. This post should be ranked higher when searching “How to compile a single kernel module”. Self fulfilling prophecy, perhaps?

19 Adam 10.14.09 at 3:24 pm

Thanks, this ended a few hours of frustration.

20 Alok 11.04.09 at 1:41 pm

Hi
I have tried load module when Linux system comes up but it’s not displaying in
#cat /proc/modules
I have done these things successfully.
# mkdir -p /lib/modules/$(uname -r)/kernel/drivers/hello
# cp hello.ko /lib/modules/$(uname -r)/kernel/drivers/hello/
# vi /etc/modules

and Added “hello” word in next line.
any suggestion would be welcome

with regards
Alok

21 abhi 01.10.10 at 1:03 pm

Thanks a lot. Found this article v. useful

22 Arnab Chakraborty 01.17.10 at 12:07 pm

Hi,

I found the article very helpful. Unlike many other linux tutorials, this one worked (with me) within the first few attempts! Just one minor point:

I had to change
tail -f /var/log/message
to
tail -f /var/log/messages

Arnab.

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Previous post:

Next post: