Linux Kernel Module Programming — Simplest example
Today lets talk about, How to write a simple Linux kernel module. Lets write a simple hello world
module, and try to understand all the basic things defined in that program. For this guide, I assume you have basic understanding about.
- C programming language
- Makefiles
As you already know, we use C — Programming language to write Linux kernel modules. But we can not use normal C syntax for some cases in kernel module programs. All official guide can be found here. Please go through it if you are not familiar.
This is one of the basic hello-world
type Linux kernel module.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sachith Muhandiram");
MODULE_DESCRIPTION("Simple first Linux module");
MODULE_VERSION("1.0.0");static int __init initHelloWorld(void){
printk(KERN_INFO "Hello, this is my first kernel module \n");
return 0;
}static void __exit exitHelloWorld(void){
printk(KERN_INFO "Exit Hello world module\n");
}module_init(initHelloWorld);
module_exit(exitHelloWorld);
Lets get start with header files we included for this, why and what they do.
Makefile to generate respective kernel module.
obj-m += hello.oall:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Lets start with header files we included.
linux/init.h
No wonder about its name and functionality, this header file include all things related to __init
part. This provides you detailed guide about how it works.
linux/module.h
This is where module_init
and module_exit
are defined. module_init
tells the kernel what is the entry point to our program and also only one module_init
call for the program we write. As official comment says
module_init() will either be called during do_initcalls() (if * builtin) or at module insertion time (if a module)
module_exit
does the opposite, when we call rmmod module
, this will be trigger and this calls to our __exit
function. Only one module_exit
for a program. If the driver is statically compiled into the kernel, module_exit()
has no effect. (official doc)
linux/kernel.h
This is where all the workload happening features are listed.
Macros
Above we have defined 4 macros. Those are mainly used for identifying our module. Here one most the most important macro is MODULE_LICENSE(“GPL”);
,if we do not define this, we wont be able to use any other system libraries running under GPL
license. For this simplest sample, this wont be a big issue, but when we develop a kernel driver etc, this could be a big issue. So always remember to keep GPL
license if you need to get GPL
licensed libraries.
Also if you release your module, then you must select appropriate licensing to your module, and in that case you would have to use static linking to GPL
licensed libraries. For more about GPL-license.
Other three macros are just basics, used to identify our module.
__init functionName(param)
This is the initialization point for the module. This feature is enabled kernel 2.2
. Compiler treats this function in a special way and add this at the beginning of the executable file.
Linux kernel will allocate memory for each __init
and free memory used by this after __init
function finishes for buildin drivers, for loadable modules, it keeps till we unload the module. (we use second method). More information please refer this.
This and __exit
functions are also macros. init
returns 0 to kernel if success.
__exit functionName(param)
This macro is used to free up resources hold by a module. Similar to init
functionality. This works as a cleanup for loadable module we wrote, build-in device drivers do not need exit
function to cleanups.
module_init(functionName)
This is the entry point to our kernel module. We define our desired entry function as a parameter. This tells kernel what our module’s functionality and setup kernel to run module’s functionalities when kernel needs.
This register our functionality to kernel. After this function completes, our module does nothing till kernel requests to do something.
module_exit(functionName)
This is the opposite of module_init
. It unregister our module functionality from kernel. This is get called when rmmod ourModule
is called.
printk(KERNEL_LOGLEVEL,”msg”,ARG)
This is basically for logging kernel info, it has different logging levels. INFO
,WARN
,EMERG
, ALERT
, CRIT
, ERR
etc. You can see all details such as what are default numbers assigned to these macros etc from this.
Also this makes sure our message is printed to /var/log/messages
.
Here I wont describe how Makefile
. When we run make
it creates all necessory modules,libraries for our module.
To add our module to kernel, we use insmod ./hello.ko
(as our makefile creates outputs as hello
. This .ko
is the file holds our module.
When this is loaded, you wont see anything to terminal. As described earlier, its printed to kernel log. dmesg -w
will show our module is loaded. and it will have a record saying Hello, this is my first kernel module
To remove our module from kernel, we use rmmod hello
, here we do not need to provide any file extension, just use our module name. This will invoke module_exit
function.
I think this is enough for today, I highly recommend you to read programming guide book I have included in references.
References:
Linux Kernel Module Programming Guide