Howto: Build Linux Kernel Module Against Installed Kernel w/o Full Kernel Source Tree

by Vivek Gite · 42 comments

Recently I received a question via email:

How do I build Linux kernel module against installed or running Linux kernel? Do I need to install new kernel source tree from kernel.org?

To be frank you do not need a new full source tree in order to just compile or build module against the running kernel i.e an exploded source tree is not required to build kernel driver or module. The instruction outlined below will benefit immensely to a developer and power user.

Linux Kernel headers

This is essential because if you just want to compile and install driver for new hardware such as Wireless card or SCSI device etc. With following method, you will save the time, as you are not going to compile entire Linux kernel.

Please note that to work with this hack you just need the Linux kernel headers and not the full kernel source tree. Install the linux-kernel-headers package which provides headers from the Linux kernel. These headers are used by the installed headers for GNU glibc and other system libraries as well as compiling modules. Use following command to install kernel headers:
# apt-get install kernel-headers-2.6.xx.xx.xx

Replace xx.xx with your actual running kernel version (e.g. 2.6.8.-2) and architecture name (e.g. 686/em64t/amd64). Use uname -r command to get actual kernel version name. Please note that above command will only install kernel headers and not the entire kernel source-code tree.

A more generic (recommend) and accurate way is as follows:
# apt-get install kernel-headers-$(uname -r)

All you need to do is change Makefile to use current kernel build directory. You can obtain this directory name by typing following command:
$ ls -d /lib/modules/$(uname -r)/build
Sample output:

/lib/modules/2.6.27-7-generic/build

Let, say you have .c source code file called hello.c. Now create a Makefile as follows in the directory containing hello.c program / file:
$ vi Makefile
Append following text:

obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

Save and close the file. Type the following command to build the hello.ko module:
$ make

To load Linux kernel module type the command:
# modprobe hello

A complete example

Create test directory (you can download following Makefile and .c file here):
$ mkdir ~/test
$ cd ~/test

Create hello.c kernel module file:

#include
<linux/module.h>
#include
<linux/kernel.h>
 
int init_module(void)
{
	printk(KERN_INFO "init_module() called\n");
	return 0;
}
 
void cleanup_module(void)
{
	printk(KERN_INFO "cleanup_module() called\n");
}
 

Create a Makefile:

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

To build kernel module enter:
$ make
Sample output:

make -C /lib/modules/2.6.27-7-generic/build M=/tmp/test2 modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.27-7-generic'
  CC [M]  /tmp/test2/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /tmp/test2/hello.mod.o
  LD [M]  /tmp/test2/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.27-7-generic'

Run ls command to see newly build kernel module:
$ ls
Sample output:

hello.c  hello.ko  hello.mod.c	hello.mod.o  hello.o  Makefile	Module.markers	modules.order  Module.symvers

hello.ko is kernel module file. To see information about module, enter:
$ modinfo hello.ko
Sample output:

filename:       hello.ko
srcversion:     4F856ABA1F3290D5F81D961
depends:
vermagic:       2.6.27-7-generic SMP mod_unload modversions 586 

To load kernel module, enter:
$ sudo insmod hello.ko
OR
$ sudo modprobe hello
To list installed Linux kernel module, enter:
$ lsmod
$ lsmod | grep hello

To remove hello Linux kernel module, enter:
$ rmmod hello
This module just logs message to a log file called /var/log/messages (/var/log/syslog), enter:
$ tail -f /var/log/messages
Sample output:

Nov  5 00:36:36 vivek-desktop kernel: [52488.923000] init_module() called
Nov  5 00:36:50 vivek-desktop kernel: [52503.065252] cleanup_module() called

Download above examples in zip format

See a detailed and completeexample with C source code about Compiling Linux kernel module for more information.

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!

{ 1 trackback }

links for 2007-02-15 « Where Is All This Leading To?
02.15.07 at 12:31 am

{ 41 comments… read them below or add one }

1 chesss 09.03.06 at 9:12 pm

would this work with suspend2 patching as well?

2 Anonymous 09.04.06 at 1:09 am

This is untrue, /lib/modules/$(shell uname -r)/build is a symlink to the source tree. Title is misleading, you always need the at least the headers to build kernel modules.

3 zhangmaike 09.04.06 at 2:28 am

on my system, /lib/modules/KERNELVERSION/build is a symlink to the corresponding full source tree.

4 nixcraft 09.07.06 at 12:22 pm

Yes you need kernel headers but not source code from kernel.org (45+ MB tar ball). So title and post is correct.

5 nixcraft 09.07.06 at 12:23 pm

You should have mentioned your distro name. I have tested this on Red Hat, Cent OS, FC and Debian and it works perfectly.

On some distro it makes a soft link to kernel header to /usr/src/version but you don\’t need source code. Just delete rest of linux kernel source code (except for headers). And try out this hack

6 s.kartikeyan 09.08.06 at 2:14 am

probably kernel-devel*.rpm is required in addition to makefile
using /lib/modules.

7 Jon Eastwood 01.30.07 at 12:12 pm

You are 100% correct – you require the kernel headers
whereas the source code from kernel.org is not required.

8 Frank 06.04.07 at 9:58 pm

Here’s one for you… I have a network interface that I need to re-compile every time the kernel is updated. This is for the realtek 8169 NIC.
Any way to automate this task on a yum update of a kernel?

If you are running the target kernel, then you should be able to do :

# make clean modules (as root or with sudo)
# make install
# depmod -a
# insmod ./src/r8169.ko

You can check whether the driver is loaded by using following commands.

# lsmod | grep r8169
# ifconfig -a

If there is a device name, ethX, shown on the monitor, the linux
driver is loaded. Then, you can use the following command to activate
the ethX.

# ifconfig ethX

,where X=0,1,2,…

If I go though this process on the local box after a kernel upgrade, I’m good to go, but it sucks that I have to do this..

Thanks,
Frank.

9 Alexander Mestiashvili 06.20.07 at 12:48 pm

this Makefile did not work for me .
i used this one


obj-m += hello-1.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

10 Daniel 10.26.07 at 10:06 pm

This is not clear enough for linux beginners. I am so sad that google placed this page so high in rankings.

Maybe you should try to make it a bit easier to understand (give more details or explain why you do that ‘hello.c’ thing).

Sincerely,
Dan

11 vivek 10.26.07 at 10:16 pm

Daniel,

You need to see hello.c (module) example here.

HTH

12 almassian 02.18.08 at 11:19 am

I don’t know how can I built a makefile?!
where should I define the PWD??!
please help me, I’m a beginner :D :-p

13 Alien Glow 09.18.08 at 5:40 am

I fumbled every time trying to install kernel modules on Debian. Though someone might find this useful. I have picked this bits from different sources.

Compile and install a Kernel Module in Debian
KVER=$(uname -r | sed ’s,-.*,,g’)

aptitude install linux-headers-$(uname -r) linux-source-$KVER build-essential
cd /usr/src
tar jxf linux-source-$KVER.tar.bz2
ln -s /usr/src/linux-source-$KVER /lib/modules/$(uname -r)/source

Download the required module source and unpack it
Enter module source directory
make
make install
To make the module visible to your running kernel, you may like to run
depmod -a
modprobe modulename

14 touristguy87 11.04.08 at 5:49 pm

SOP is to follow the instructions line by line from beginning to end to make sure that they actually work before posting them as a “guide”.

There are too many holes here.

a) you don’t need to know exactly what verion of the kernel you have, $(uname -r) takes care of that for you.

b) what’s the difference beween $(uname -r) and $(shell uname -r)?

c) what about includes like #include etc that I see on the reference pages, here?

“See a detailed and complete example with C source code – how to Compiling Linux kernel module for more information.”

That code doesn’t work either. I can’t get the includes to work. If I hardcode them then they just reference other header files that don’t link properly because they have includes written the same way. I can’t even get that example to build.

15 touristguy87 11.04.08 at 5:52 pm

that is to say
#include

..where exactly is this file?

It’s in /lib/modules/$(uname -r)/build/include right? (I found it, I’m doing this from memory at 3am last night) ok so I hardcode that into the #include above and then I just get a bunch of errors saing that linux/whatever.h can’t be found so clearly in that header file are similar #includes.

I modified the PATH variable to include /lib/modules…include and that still doesn’t work. I guess that I’ll figure this out later and post a solution.

16 vivek 11.04.08 at 6:52 pm

touristguy87,

Under Ubuntu Linux 8.x install the following package (following will almost install every kernel source code file):

sudo apt-get install linux-headers-$(uname -r) linux-libc-dev kernel-package

Once done create hello.c as follows:
mkdir ~/hello
cd ~/hello

Create hello.c:

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
	printk(KERN_INFO "init_module() called\n");
	return 0;
}

void cleanup_module(void)
{
	printk(KERN_INFO "cleanup_module() called\n");
}

Create Makefile (note tabs are important):

obj-m += hello.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Type following to build:
make
Sample output from my Ubuntu 8.10 box:

make -C /lib/modules/2.6.27-7-generic/build M=/tmp modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.27-7-generic'
  CC [M]  /tmp/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /tmp/hello.mod.o
  LD [M]  /tmp/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.27-7-generic'

HTH

17 touristguy87 11.06.08 at 6:04 pm

ok then I would just remove this part from the above:

# apt-get install kernel-headers-2.6.xx.xx.xx

as to just use $(uname -r) is much better

also any comments about having to change to the “build” directory

and note that you have to use $(shell uname -r) in the makefile.

likewise do you need linux-libc-dev or not, it sounds redundant…

and there is now a zip file with the programs, and two other links as examples.

this one is probably redundant now except for it points to the original instructions on how to do this…and a lot more.

http://www.tldp.org/LDP/lkmpg/2.6/html/hello2.html

http://www.cyberciti.biz/tips/compiling-linux-kernel-module.html

thanks

18 touristguy87 11.07.08 at 4:12 am

ok also

obj := vs obj +=

at the top it is the former, the working code seems to be the latter

Here I also see
http://www.cyberciti.biz/tips/compiling-linux-kernel-module.html

obj-m = foo.o
KVERSION = $(shell uname -r)

and the orignal source:
http://www.tldp.org/LDP/lkmpg/2.6/html/hello2.html

has +=

this is pretty simple code once you’ve looked at it for 2 hours ;)

I think the main thing is that it has to point to $(uname -r)/build but you have to use $(shell uname -r) in the makefile -C part.

anyway I see plenty of variation in the basic syntax among the 5 or 6 examples on those 3 links.

19 vivek 11.07.08 at 7:03 am

Use method which works for you. There is also 3rd method but I don’t wanna confuse you with more stuff. Yes, linux-libc-dev is not required until and unless you are going to play more with low level device driver and other stuff requiring functions from libc.

HTH

20 touristguy87 11.08.08 at 7:03 am

I got it, somehow. I don’t know how.

I was getting the “can’t find target ‘make’ error”…I updated my system and rebooted and just tried make on a whim and it worked.

I used $(shell uname -r) in the Make file and += for the labels

also I removed the function-calls from the code.See the original example here:

http://www.tldp.org/LDP/lkmpg/2.6/html/hello2.html

21 sathish 11.13.08 at 9:36 am

what is use of .mod.o and .mod.c files , the Makefile which is present in o.s is creating , what info those files are having

22 instruc 01.06.09 at 5:14 pm

Great content tips .All you need to do is customize them with your own …Thank you…

23 ycdtosa 01.19.09 at 11:42 am

if build is missing (even after installing headers) this might help:

ln -s /usr/src/linux-headers-$(uname -r) /lib/modules/$(uname -r)/build

24 kyle Locke 01.29.09 at 7:30 am

Thanks. Its what I was searchin for.

25 anon 02.05.09 at 5:12 pm

Anonymous 09.04.06 at 1:09 am wrote:
>This is untrue, /lib/modules/$(shell uname -r)/build is a symlink to the source tree.

build is a symlink to the build environment. Since source trees are build environments too, the build symlink can also point to them. But where just a plain build env without source is present, build points to a directory which merely has
total 556
drwxr-xr-x 6 root root 110 Feb 4 12:24 .
drwxr-xr-x 4 root root 27 Jan 30 21:39 ..
drwxr-xr-x 3 root root 16 Feb 4 12:24 arch
drwxr-xr-x 5 root root 55 Feb 4 12:24 include
drwxr-xr-x 2 root root 16 Feb 4 12:24 include2
drwxr-xr-x 6 root root 116 Feb 4 12:24 scripts
-rw-r–r– 1 root root 89994 Jan 30 21:42 .config
-rw-r–r– 2 root root 530 Jan 30 21:43 Makefile
-rw-r–r– 1 root root 474571 Jan 30 21:39 Module.symvers

26 m.h 02.24.09 at 8:11 am

about the first module “hello.c ” , I had a problem ,
I installed my kernel headers but after “make” I was recieved this message …
Nothing to be done for ‘default’
and the second one as well ….
Nothing to be done for ‘all’

what shall I do ?

27 kim gomez 06.15.09 at 4:13 am

It was interesting to read trough :-) keep up the good work and thanks for all the tips.

28 kim gomez 06.15.09 at 4:16 am

Can you provide more information on this, or do you have some resources you can share where i can get more of such stuff?

29 sharath 08.14.09 at 2:47 pm

THANK YOU VERY MUCH FOR HELPING BEGINNERS

30 saju 08.17.09 at 1:17 pm

ERROR-1:
periyar:/home/saju/Desktop/hello-linux-module# apt-get install kernel-headers-$(uname -r)
Reading package lists… Done
Building dependency tree
Reading state information… Done
E: Couldn’t find package kernel-headers-2.6.26-1-686
——————————————–
ERROR-2 in Debian Lenny.
periyar:/home/saju/Desktop/hello-linux-module# make
make -C /lib/modules/2.6.26-1-686/build M=/home/saju/Desktop/hello-linux-module modules
make: *** /lib/modules/2.6.26-1-686/build: No such file or directory. Stop.
make: *** [all] Error 2

31 Vivek Gite 08.17.09 at 2:25 pm

install kernel-headers package using yum (Fedora / RHEL CentOS) or apt-get (Debian/Ubuntu).

32 saju 08.18.09 at 10:04 am

I solved first Error by #apt-get install linux-headers
But the second error not solved . Please help

periyar:/home/saju/Desktop/hello-linux-module# make
make -C /lib/modules/2.6.26-1-686/build M=/home/saju/Desktop/hello-linux-module modules
make[1]: Entering directory `/lib/modules/2.6.26-1-686/build’
make[1]: *** No rule to make target `modules’. Stop.
make[1]: Leaving directory `/lib/modules/2.6.26-1-686/build’
make: *** [all] Error 2

33 Benno 09.10.09 at 3:15 am

Great tutorial. Thanks!

34 Rohit 10.14.09 at 7:19 pm

Its a wonderful introduction to a fresher to Linux.
Thanks I was frustated when I found that makefile should be “Makefile” !!!!!!!!

35 Joe 10.15.09 at 9:00 am

What if the hello.c is actually a hello.cpp ? How do we do the Makefile for that?

36 baskar 11.24.09 at 11:22 pm

I tried this on CentOS5.4 and I cannot proceed after this:

[cuser@localhost test]$ make
make -C /lib/modules/2.6.18-164.el5/build M=/home/cuser/test modules
make: *** /lib/modules/2.6.18-164.el5/build: No such file or directory. Stop.
make: *** [all] Error 2

But, I do have kernel-devel and kernel-headers.

[cuser@localhost test]$ yum search kernel-headers kernel-devel
Loaded plugins: fastestmirror
============================ Matched: kernel-devel =============================
kernel-devel.x86_64 : Development package for building kernel modules to match
: the kernel.

=========================== Matched: kernel-headers ============================
kernel-headers.x86_64 : Header files for the Linux kernel for use by glibc
[cuser@localhost test]$

Could you help? If I figure this out, I can install the Broadcom BCM4312 wireless driver for Linux by Broadcom where I have the same issue.

Thanks a lot

37 Viper 12.11.09 at 1:34 am

Ubuntu 9.10 x64

headers, source, module-assistant, build-essential, all installed.

Typing “make -C /lib/modules/$(uname -r)/build M=$(pwd) modules”
Get the following error:

make: Entering directory `/usr/src/linux-headers-2.6.31-16-generic’
make: *** No rule to make target `para’. Stop.
make: Leaving directory`/usr/src/linux-headers-2.6.31-16-generic’

Typing just “make”, adds
make: *** [default] Error 2
to the above

Any comment?

38 touristguy87 12.12.09 at 7:57 am

a) read all of the above
b) make sure that your OS is fully up to date

Trust me, this does work.

39 Viper 12.12.09 at 11:52 am

All was read. OS is up to date.

But I solved it. Problem was the folder had a space in the name. Replaced with an underscore and it worked.

40 netbrat 02.05.10 at 10:24 pm

help me how should i get rid of this error

sudo make
make -C /lib/modules/2.6.31-19-generic/build M= modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.31-19-generic’
CHK include/linux/version.h
CHK include/linux/utsrelease.h
SYMLINK include/asm -> include/asm-x86
make[2]: *** No rule to make target `kernel/bounds.c’, needed by `kernel/bounds.s’. Stop.
make[1]: *** [prepare0] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-2.6.31-19-generic’
make: *** [all] Error 2

41 Sumathi Gopal 02.09.10 at 7:20 am

Thank you for this. It worked like a charm. I’m on a Ubuntu laptop with 2.6.28-11 kernel installation; no kernel source code.

-sumathi

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: