what happens when a kenrel module is loaded
Hello students welcome to free linux kernel development course online, in this lecture i will teach you what exactly happens when you load the kernel module, we will discuss what is printk() how printk() is different from printf() and we will se some other important topics related to linux kernel module development.
First let us see how to build a kernel module using makefile:
In linux kernel programming using make files for building modules is the standard approach, below is how a typical makefile will look like
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
example for a make file, and below are the command to compile the module, clean build files and the final output is kernel object file.
make
to compile linux kernel module
make clean
to clean the modules
hello.ko
final kernel object file
How to insert Kernel module
sudo insmod module_name.ko
sudo insmod hello.ko
example
sudo rmmod hello
to remove module
lsmod
to list modules
now you understood how to insert the modules, remove kenrel module and list the modules, i will explain what happens when a modules is inserted, so let us see what happens when you run insmod?
What Happens When You Run insmod?
so below is the sequence to understand what happens when a linux kernel module is inserted, basically this will give you flow of linux kernel module insertion.
step 1: init_module()
init_module()
User space program calls the systems call init_module(), this informs the kernel that a new module is being inserted.
step 2: sys_init_module()
sys_init_module()
kernel exectes the above function, this function is exeucted inside the kernel, so the init_module() is the systems call and that system call internally will this sys_init_module().
step 3: Permission check
here kernel will check for permissions, whether the user who is trying to insert module has relevant previleges or not, only root or sudo users can load the modules, others are restricted to load or insert the modules.
step 4: load_module()
load_module()
now the module is loaded into kernel by calling the load_module() function, this module performs multiple tasks then finally loaded into kernel space, below is the api that will copy the module from user space to kernel space.
copy_from_user()
for this task memory is temporarily allocated for the modules and then module is copied into kernel space.
step 5: ELF verification
Kernel verifies whether the nodule is valid ELF file or not , basiclly ELF denotes executable and linkable format, so if the kernel observes any discripancy in the ELF file then the module loading will fail.
Step 6: Offset generation
Now kernel generates offsets for the inserted kernel module and this offset generation includes symbols variables functions, and these are called as convenience variables.
STEP 7: Copy module arguments
if any arguments are passed to the odule they are copied into kernel memory when the module is loaded, memory for this arguments is also allocated.
Step8: Symbol Resolution
Kernel will resolve all the external symbols that are used in the module, if any symbols are not resolved then you will see related errors.
Step 9: Add module to module list
the module reference is added to doubly linked list of the loaded modules, kernel will maintain the doubly linked list data structure to store all the information about loaded kerel modules.
Step 10: Execute module_initi() function
finally the module_init() function is executed then the api which we passed as argument to this function will execute and you can see the output in the kernel logs that is in dmesg logs.
Return values:
when you run the module_init() function based on the status below values are returned.
| Return Value | Meaning |
|---|---|
| 0 | Module loaded successfully |
| negative value | Module loading failed |
if you see -i is returned then init function still executes , but module will not appear in lsmod. How ever you can see the logs in dmesg.
+--------------------------------------------------+
| User Space |
+--------------------------------------------------+
User runs command
sudo insmod module.ko
|
v
+----------------------+
| insmod Utility |
| (User Space Program) |
+----------------------+
|
v
init_module() System Call
|
v
+--------------------------------------------------+
| Kernel Space |
+--------------------------------------------------+
+---------------------------+
| sys_init_module() |
| Kernel Entry Function |
+---------------------------+
|
v
+---------------------------+
| Permission Check |
| (Only root / sudo user) |
+---------------------------+
|
v
+---------------------------+
| load_module() |
| Core Module Loader |
+---------------------------+
|
v
+---------------------------+
| Allocate Kernel Memory |
+---------------------------+
|
v
+---------------------------+
| copy_from_user() |
| Copy .ko from User Space |
| to Kernel Space |
+---------------------------+
|
v
+---------------------------+
| ELF Verification |
| Check valid ELF module |
+---------------------------+
|
v
+---------------------------+
| Offset Generation |
| (Functions / Symbols / |
| Variables) |
+---------------------------+
|
v
+---------------------------+
| Copy Module Args |
| Arguments → Kernel Mem |
+---------------------------+
|
v
+---------------------------+
| Symbol Resolution |
| Resolve external symbols |
+---------------------------+
|
v
+---------------------------+
| Add Module to Kernel List |
| (Doubly Linked List of |
| Loaded Modules) |
+---------------------------+
|
v
+---------------------------+
| module_init() Call |
| Execute Init Function |
+---------------------------+
|
v
+---------------------------+
| Return 0 → Success |
| Module Loaded in Kernel |
+---------------------------+
comple flow of linux kernel module insertion
How to create customer knerl module – how to give own name to kernel module
Till now we have seent that the module name is generally the file name, but we also have an option to user our own custom name by making some changes to the make file, this method is useful when you multiple source files are used, when you want to create some meaningfule module name, or you want to hide the internal file name. so let us see how it actually works.
Example: Assume if you have a file name ret1.c and generally ret1.ko will be generated but if you want to create something like ownname.ko then you should do below changes in Makefile.
obj-m := ownname.o
ownname-objs := ret-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
this will create a custom name.
obj-m := ownname.o
this will tell the kernel to generate the custom kernel with above name
ownname-objs := ret-1.o
This line specifies the object files that will be linked to create the module.
ret-1.c → ret-1.o
Then it gets linked to create:
ownname.ko
So the compilation flow is:
ret-1.c
|
v
ret-1.o
|
v
ownname.ko
So above is the compilation flow for custom module generation.
build the kenrel module
make
This will generate several files including:
ret-1.o
ownname.ko
Module.symvers
modules.order
ownname.ko is important file that we will insert into kernel.
Insert the Kernel Module
Load the module into the kernel using:
sudo insmod ownname.ko
Check if the module is loaded:
lsmod | grep ownname
you can see your module name
View Kernel Messages
To see messages printed using printk(): you can chec in dmesg that is in kernel logs you can give dmesg or dmesgg | tail.
