What are kernel modules?
Kernel modules are piece of code, that can be loaded and unloaded from kernel on demand.
Kernel modules offers an easy way to extend the functionality of the base kernel without having to rebuild or recompile the kernel again. Most of the drivers are implemented as a Linux kernel modules. When those drivers are not needed, we can unload only that specific driver, which will reduce the kernel image size.
The kernel modules will have a .ko extension. On a normal linux system, the kernel modules will reside inside /lib/modules/<kernel_version>/kernel/ directory.
Earlier we discussed how to compile a kernel from the source.
This tutorial explains how to write a Kernel module using a simple Hello World example.
I. Utilities to Manipulate Kernel Modules
1. lsmod – List Modules that Loaded Already
lsmod command will list modules that are already loaded in the kernel as shown beblow.
# lsmod Module Size Used by ppp_deflate 12806 0 zlib_deflate 26445 1 ppp_deflate bsd_comp 12785 0 ..
2. insmod – Insert Module into Kernel
insmod command will insert a new module into the kernel as shown below.
# insmod /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko # lsmod | grep "squash" squashfs 35834 0
3. modinfo – Display Module Info
modinfo command will display information about a kernel module as shown below.
# modinfo /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko filename: /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko license: GPL author: Phillip Lougher description: squashfs 4.0, a compressed read-only filesystem srcversion: 89B46A0667BD5F2494C4C72 depends: intree: Y vermagic: 3.5.0-19-generic SMP mod_unload modversions 686
4. rmmod – Remove Module from Kernel
rmmod command will remove a module from the kernel. You cannot remove a module which is already used by any program.
# rmmod squashfs.ko
5. modprobe – Add or Remove modules from the kernel
modprobe is an intelligent command which will load/unload modules based on the dependency between modules. Refer to modprobe commands for more detailed examples.
II. Write a Simple Hello World Kernel Module
1. Installing the linux headers
You need to install the linux-headers-.. first as shown below. Depending on your distro, use apt-get or yum.
# apt-get install build-essential linux-headers-$(uname -r)
2. Hello World Module Source Code
Next, create the following hello.c module in C programming language.
#include <linux/module.h> // included for all kernel modules #include <linux/kernel.h> // included for KERN_INFO #include <linux/init.h> // included for __init and __exit macros MODULE_LICENSE("GPL"); MODULE_AUTHOR("Lakshmanan"); MODULE_DESCRIPTION("A Simple Hello World module"); static int __init hello_init(void) { printk(KERN_INFO "Hello world!\n"); return 0; // Non-zero return means that the module couldn't be loaded. } static void __exit hello_cleanup(void) { printk(KERN_INFO "Cleaning up module.\n"); } module_init(hello_init); module_exit(hello_cleanup);
Warning: All kernel modules will operate on kernel space, a highly privileged mode. So be careful with what you write in a kernel module.
3. Create Makefile to Compile Kernel Module
The following makefile can be used to compile the above basic hello world kernel module.
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
Use the make command to compile hello world kernel module as shown below.
# make make -C /lib/modules/3.5.0-19-generic/build M=/home/lakshmanan/a modules make[1]: Entering directory `/usr/src/linux-headers-3.5.0-19-generic' CC [M] /home/lakshmanan/a/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/lakshmanan/a/hello.mod.o LD [M] /home/lakshmanan/a/hello.ko make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-19-generic'
The above will create hello.ko file, which is our sample Kernel module.
4. Insert or Remove the Sample Kernel Module
Now that we have our hello.ko file, we can insert this module to the kernel by using insmod command as shown below.
# insmod hello.ko # dmesg | tail -1 [ 8394.731865] Hello world! # rmmod hello.ko # dmesg | tail -1 [ 8707.989819] Cleaning up module.
When a module is inserted into the kernel, the module_init macro will be invoked, which will call the function hello_init. Similarly, when the module is removed with rmmod, module_exit macro will be invoked, which will call the hello_exit. Using dmesg command, we can see the output from the sample Kernel module.
Please note that printk is a function which is defined in kernel, and it behaves similar to the printf in the IO library. Remember that you cannot use any of the library functions from the kernel module.
Now you have learned the basics to create your own Linux Kernel module.
Comments on this entry are closed.
Hi,
Thanks.
Very useful article
Thanks again
Very nice explaination
Good article, but one slight adjustment:
You suggest creating the file helloworld.c, but specify hello.o in the Makefile. My code wouldn’t compile because of this – I had to put “obj-m += helloworld.o” in the Makefile before it would work.
Once I figured that out, Bob’s your uncle, thanks for posting this.
Simply incredible article!
Thanks.
really very useful, your website it’s wonderful. i learning a lot. thanks
Great article!!
One suggestion would be maybe a 1 paragraph to describe when you would write a kernel module vs running the same code in user space.
This is great, all this geek stuff just keeps getting better. Thank you!
Awesome article !! Thanks for sharing such stuff.
Superb explanation
Thanks, looks useful.
Great Article, but I have to agree with Bob. An explanation when you would write a kernel module instead of creating a program in user space would be a good idea.
Great…keep it up!!!!
I’ve tried on two Ubuntu boxes and both have build-essentials and linux-headers (linux-headers-2.6.32-45-generic) installed but no linux/module.h available. I can see it in /usr/src/linux-headers-2.6.32-45-generic/include/linux/module.h but …
Never mind, or, rather, I have a Makefile problem – running:
$ make -C /lib/modules/$(uname -r)/build M=${PWD} modules
works just fine.
Thanks.
Hi
Just make sure you have tabs in the makefile, or you’ll get
“make: Nothing to be done for `all’ ”
e.g
all:
make −C /lib/modules/$(shell uname −r)/build M=$(PWD) modules
clean:
make −C /lib/modules/$(shell uname −r)/build M=$(PWD) clean
i am executing the make command on cent os i am getting error like
make -C /lib/modules/2.6.32-358.el6.i686/build M=/root modules
make: *** /lib/modules/2.6.32-358.el6.i686/build: No such file or directory. Stop.
make: *** [all] Error 2
any help ?
Hi,thanks for the article. I have one doubt,while trying out various things I found that when I comment out module_init and module_exit, the code works fine still and the module gets loaded. But you have said those two are used to call the entry and exit funcs. HOW DID IT WORK THEN??
Also,I am not using init_module or cleanup_module(pre-defined ones..)
PLZ CLARIFY… 🙂
@DEV
When you do insmod, the module will be loaded into kernel, but the entry function will not be called, and without that there is no use of a module. In my opinion, kernel module without module_init will be of no use.
Only when you do module_init, the entry function will be called, and the module can start performing its operations.
Hi, yeah got it figured already when I looked for the logs… there was no entry without those two… Thanks. 🙂
Nice article,
but it needs “shell uname” changed “uname”, and $(PWD) to `pwd`. Because PWD may not have been set by user in shell.
above suggestion is for doing compilation without makefile OR shell specific settings. As many users have posted about makefile doing nothing.
Thanx. It helped !
how to clear the eror all is up to data.while running make i am getting this error plz help me how to solve this error……i am using 3.13.1 kernel version……while updating headres it giving some errors.how to clear these errors
Hello sir,
I have one doubt, please ans my doubt. why u used __init and __exit why you not use _init and _exit. is there any standard to write like that or simply you have taken example.
heyy.. frineds. I am a newbie here for kernel programming. Unfortunately getting this error.
cc makefile.c -o makefile
makefile.c:1:4: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘-’ token
obj-m += hello.o
^
make: *** No targets specified and no makefile found. Stop.
@Taral
Er, you need to reread the article
cc makefile.c -o makefile
isn’t correct – there isn’t a makefile.c there’s a hello.c. You use “make” and the makefile as a “recipe” to handle the details of compling the hello.c C code into an executable. You’ll have two text files in your dir makefile and hello.c and then you just type “make”, it read makefile and then handles the calling “cc” to do the actual compile.
Hi ,
If i am to compile the Kernel Module for say beaglebone how do i do it? What would the makefile need to look like?
Thanks!
realy helpfull
thanks
Now, thats what I call a smooth howto.
Thanks
Hi All,
After I do the insmod hello.ko, I get the following message:-
insmod: error inserting ‘hello.ko’: -1 Operation not permitted.
Please advice on what needs to be done or where I went wrong.
hello anand,
probably you tried to insmod as an unprivileged user
Thanks Lakshmanan. This helped a lot.
Cheers!
What happens if you change the name of Makefile to compile your kernel module? It does not work in that case.
Really great explanation . Helped me well ! Thanks
Hi Lakshmanan!
Great article for people to get into kernel programming.
Just 1 remark:
There’s no reason to use the __init and __exit macro’s in loadable modules and it only makes your code unnecessarily complex 🙂
These have no effect for modules and are only to cleanup memory after builtin drivers.
Source: Kernel documentation
This demonstrates a feature of kernel 2.2 and later. Notice the change in the definitions of the init and cleanup functions. The __init macro causes the init function to be discarded and its memory freed once the init function finishes for built-in drivers, but not loadable modules. If you think about when the init function is invoked, this makes perfect sense.
The __exit macro causes the omission of the function when the module is built into the kernel, and like __exit, has no effect for loadable modules. Again, if you consider when the cleanup function runs, this makes complete sense.
awesome..sir very usefull
Useful blog. Thanks
Thanks bro! Great article! Helped a lot! 🙂
Books could not help but your article could…. Thanks a lot
This is good article for beginners to understand the kernel module.
Great, thanks.
Very Helpful.The Example and steps are very well explained.Keep Writing For Teaching us:).
Thank You.
On Ubuntu 15.10 you can see “module verification failed: signature and/or required key missing – tainting kernel”. To solve this problem just add “CONFIG_MODULE_SIG=n” at the top of Makefile.
Also after insmod command you probably will not see your HelloWorld printk in init function. I solved this by changing log level of printk on KERN_DEBUG
kernel programming looking cool….. but I have to learn many thing before compiling kernel…..