Initialize and Setup

#

Version

Ubuntu

Ubuntu 22.10

Kernel

6.8.0

  • In this program, you are going to learn

  • How to create timer ?

  • How to start the timer ?

  • How to set up the timer ?

  • How to stop the timer ?

  • Here is the function prototype of the API: from_timer

#include <linux/timer.h>

#define from_timer(var, callback_timer, timer_fieldname)
  • Here is the function prototype of the API: add_timer

#include <linux/timer.h>

extern void add_timer(struct timer_list *timer);
  • Here is the function prototype of the API: del_timer

#include <linux/timer.h>

static inline int del_timer(struct timer_list *timer);
#include <linux/timer.h>

void init_timer_key(struct timer_list *timer, void (*func)(struct timer_list *), unsigned int flags, const char *name, struct lock_class_key *key);
  • Here is the function prototype of the API: timer_setup

#include <linux/timer.h>

#define timer_setup(timer, callback, flags)
  • Here is the function prototype of the API: mod_timer

#include <linux/timer.h>

extern int mod_timer(struct timer_list *timer, unsigned long expires);
#include <linux/timer.h>

#define timer_setup_on_stack(timer, callback, flags)
#include <linux/timer.h>

static inline int del_timer_sync(struct timer_list *timer);
#include <linux/timer.h>

extern void destroy_timer_on_stack(struct timer_list *timer);
  • Here is the prototype of module paramter APIs

#include <linux/module.h>

#define MODULE_LICENSE(_license) MODULE_FILE MODULE_INFO(license, _license)
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
  • where

    • MODULE_LICENSE: tells the kernel what license is used by our module.

    • MODULE_AUTHOR: denotes the author of this kernel module.

    • MODULE_DESCRIPTION: gives a basic idea about what the kernel module does.

    • These information can be found when modinfo command is used which lists out all these above mentioned information.

  • Here is the example of how to use the Module parameter APIs,

MODULE_LICENSE("GPL");
MODULE_AUTHOR("usr");
MODULE_DESCRIPTION("Timer");
  • Here is the prototype of the Driver entry point API’s

#include <linux/module.h>

#define module_init(x)      __initcall(x);
#define module_exit(x)      __exitcall(x);
  • where

    • module_init: driver initialization entry point which will be called at module insertion time.

    • module_exit: driver exit entry point which will be called during the removal of module.

    • x:
      • function to be run at module insertion for module_init function.

      • function to be run when driver is removed for module_exit function.

  • Here is an example of how to use the driver entry point API’s

module_init(task_init);
module_exit(task_exit);
  • In this example let’s see how to create timer using DEFINE_TIMER and execute it.

  • Include the follow header files(.h) to refer the API being used for the execution.

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/err.h>
  • Add the following module macros to display information about the license, author and description about the module.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("usr");
MODULE_DESCRIPTION("Timer");
  • Declare and initialize the timer which we are going to create and use in this example

init_timer_key(&drv_var.my_timer,timer_callback,0,TIMER_NAME,key);
  • This function executes once the timer expires.

static void timer_callback(struct timer_list * t)
{
        pr_info("Inside Timer Callback function\n");

        struct my_drv_info * my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
        pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
        pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
        pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
        pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
}
  • Initializes timer using init_timer_key

  • Start a timer using add_timer.

void timer_start(void)
{
        static struct lock_class_key * key = NULL;

        drv_var.data_a = 10;
        drv_var.data_b = 20;
        drv_var.data_c = 'a';
        strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));

        init_timer_key(&drv_var.my_timer,timer_callback,0,TIMER_NAME,key);
        add_timer(&drv_var.my_timer);
}
  • This function calls timer_start function, will be executed once the module is loaded into the linux kernel.

static int __init timer_init(void)
{
        pr_info("Inside timer_init function\n");
        timer_start();
        pr_info("Driver loaded!\n");
        return 0;
}
  • This function deletes pending timer and stops it’s execution.

void timer_stop(void)
{
        del_timer(&drv_var.my_timer);
}
  • This function calls timer_stop function, will be executed once the module is removed from the linux kernel.

static void __exit timer_exit(void)
{
        pr_info("Inside timer_exit function\n");
        timer_stop();
        pr_info("Driver unloaded!\n");
}
  • Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

module_init(timer_init);
module_exit(timer_exit);
 1/* init_timer_key */
 2
 3#include <linux/init.h>
 4#include <linux/kernel.h>
 5#include <linux/module.h>
 6#include <linux/fs.h>
 7#include <linux/timer.h>
 8#include <linux/jiffies.h>
 9#include <linux/err.h>
10
11#define TIMEOUT 5000 
12#define TIMER_NAME "my_timer"
13
14MODULE_LICENSE("GPL");
15MODULE_AUTHOR("Linux_usr");
16MODULE_DESCRIPTION("One Shot Timer");
17
18void timer_start(void);
19void timer_stop(void);
20
21struct my_drv_info {
22	struct timer_list my_timer;
23	int data_a;
24	int data_b;
25	char data_c;
26	char data_d[10];
27};
28
29struct my_drv_info drv_var;
30
31/* timer_callback - executes once the timer expires */
32static void timer_callback(struct timer_list *t)
33{
34	pr_info("Inside Timer Callback function\n");
35	
36	struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
37	pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
38	pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
39	pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
40	pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
41}
42
43/* timer_start - initializes timer using init_timer_key,
44 * start a timer using add_timer
45 */
46void timer_start(void)
47{
48	static struct lock_class_key *key = NULL;
49
50        drv_var.data_a = 10;
51        drv_var.data_b = 20;
52        drv_var.data_c = 'a';
53        strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));
54
55        init_timer_key(&drv_var.my_timer,timer_callback,0,TIMER_NAME,key);
56        add_timer(&drv_var.my_timer);
57}
58
59/* timer_init - calls timer_start function,
60 * will be executed once the module is loaded into the linux kernel
61 */
62static int __init timer_init(void)
63{
64	pr_info("Inside timer_init function\n");
65	timer_start();
66	pr_info("Driver loaded!\n");
67	return 0;
68}
69
70/* timer_stop - Deletes pending timer and stops it's execution */
71void timer_stop(void)
72{
73	del_timer(&drv_var.my_timer);
74}
75
76/* timer_exit - calls timer_stop function,
77 * will be executed once the module is removed from the linux kernel
78 */
79static void __exit timer_exit(void)
80{
81	pr_info("Inside timer_exit function\n");
82	timer_stop();
83	pr_info("Driver unloaded!\n");
84}
85
86module_init(timer_init);
87module_exit(timer_exit);
1obj-m += timer.o
2
3all:
4	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • Run make to compile the kernel source and generate the .ko image.

$ make
make -C /lib/modules/6.8.0/build M=/home/test/Desktop/kernel_api/initialize_setup_kernel/tc1 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
  CC [M]  /home/test/Desktop/kernel_api/initialize_setup_kernel/tc1/timer.o
  MODPOST /home/test/Desktop/kernel_api/initialize_setup_kernel/tc1/Module.symvers
  CC [M]  /home/test/Desktop/kernel_api/initialize_setup_kernel/tc1/timer.mod.o
  LD [M]  /home/test/Desktop/kernel_api/initialize_setup_kernel/tc1/timer.ko
make[1]: Leaving directory '/home/test/Desktop/kernel_api/linux-6.8'
  • Check if the .ko is generated or not using ls command.

$ ls -l
total 376
-rw-rw-r-- 1 test test    155 Jul 19 14:57 Makefile
-rw-rw-r-- 1 test test     73 Jul 19 15:03 modules.order
-rw-rw-r-- 1 test test      0 Jul 19 15:03 Module.symvers
-rw-rw-r-- 1 test test   2143 Jul 19 14:57 timer.c
-rw-rw-r-- 1 test test 178696 Jul 19 15:03 timer.ko
-rw-rw-r-- 1 test test     73 Jul 19 15:03 timer.mod
-rw-rw-r-- 1 test test   1066 Jul 19 15:03 timer.mod.c
-rw-rw-r-- 1 test test 149232 Jul 19 15:03 timer.mod.o
-rw-rw-r-- 1 test test  30880 Jul 19 15:03 timer.o
  • Run modinfo command to get the information about the kernel module.

$ modinfo timer.ko
filename:       /home/test/Desktop/kernel_api/initialize_setup_kernel/tc1/timer.ko
description:    Timer
author:         Linux_usr
license:        GPL
srcversion:     11588D0D1B327CC872264E3
depends:
retpoline:      Y
name:           timer
vermagic:       6.8.0 SMP preempt mod_unload modversions
  • insert the module using insmod command.

$ sudo insmod ./timer.ko
  • check if the module is loaded or not using lsmod command.

$ lsmod | grep timer
timer                  12288  0
  • check for the kernel messages from init function and thread function once the module is loaded and thread is created.

$ sudo dmesg
[256521.831119] Inside timer_init function
[256521.831124] Driver loaded!
[256521.838670] Inside Timer Callback function
[256521.838673] timer_callback : data_a : 10
[256521.838677] timer_callback : data_b : 20
[256521.838679] timer_callback : data_c : a
[256521.838681] timer_callback : data_d : hello
  • remove the module from kernel using rmmod command.

$ sudo rmmod timer
  • check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.

$ lsmod | grep timer
  • Check for kernel messages from exit function using dmesg command.

$ sudo dmesg
[256542.863732] Inside timer_exit function
[256542.863740] Driver unloaded!
  • In this example let’s see how to set up the timer using timer_setup and execute it.

  • Include the follow header files(.h) to refer the API being used for the execution.

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/err.h>
  • Add the following module macros to display information about the license, author and description about the module.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("usr");
MODULE_DESCRIPTION("Timer");
  • Setting up the timer which we are going to create and use in this example

timer_setup(&drv_var.my_timer, timer_callback, 0);
  • This function executes once the timer expires.

static void timer_callback(struct timer_list * t)
{
        pr_info("Inside Timer Callback function\n");

        struct my_drv_info * my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
        pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
        pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
        pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
        pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
}
  • This function setup the timer to call timer_callback() using timer_setup.

  • Modifies a timer’s timeout using mod_timer.

void timer_start(void)
{
        drv_var.data_a = 10;
        drv_var.data_b = 20;
        drv_var.data_c = 'a';
        strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));

        timer_setup(&drv_var.my_timer, timer_callback, 0);
        mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
}
  • This function calls timer_start function, will be executed once the module is loaded into the linux kernel.

static int __init timer_init(void)
{
        pr_info("Inside timer_init function\n");
        timer_start();
        pr_info("Driver loaded!\n");
        return 0;
}
  • This function deletes pending timer and stops it’s execution.

void timer_stop(void)
{
        del_timer(&drv_var.my_timer);
}
  • This function calls timer_stop function, will be executed once the module is removed from the linux kernel.

static void __exit timer_exit(void)
{
        pr_info("Inside timer_exit function\n");
        timer_stop();
        pr_info("Driver unloaded!\n");
}
  • Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

module_init(timer_init);
module_exit(timer_exit);
 1/* timer_setup */
 2
 3#include <linux/init.h>
 4#include <linux/kernel.h>
 5#include <linux/module.h>
 6#include <linux/fs.h>
 7#include <linux/timer.h>
 8#include <linux/jiffies.h>
 9#include <linux/err.h>
10
11#define TIMEOUT 1000 
12
13MODULE_LICENSE("GPL");
14MODULE_AUTHOR("Linux_usr");
15MODULE_DESCRIPTION("Timer");
16
17void timer_start(void);
18void timer_stop(void);
19
20struct my_drv_info {
21	struct timer_list my_timer;
22	int data_a;
23	int data_b;
24	char data_c;
25	char data_d[10];
26};
27
28struct my_drv_info drv_var;
29
30/* timer_callback - executes once the timer expires */
31static void timer_callback(struct timer_list *t)
32{
33	pr_info("Inside Timer Callback function\n");
34	
35	struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
36	pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
37        pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
38        pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
39        pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
40}
41
42/* timer_start - setup the timer to call timer_callback() using timer_setup,
43 * modifies a timer's timeout using mod_timer
44 */
45void timer_start(void)
46{
47	drv_var.data_a = 10;
48        drv_var.data_b = 20;
49        drv_var.data_c = 'a';
50        strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));
51
52        timer_setup(&drv_var.my_timer, timer_callback, 0);
53        mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
54}
55
56/* timer_init - calls timer_start function,
57 * will be executed once the module is loaded into the linux kernel
58 */
59static int __init timer_init(void)
60{
61	pr_info("Inside timer_init function\n");
62	timer_start();
63	pr_info("Driver loaded!\n");
64	return 0;
65}
66
67/* timer_stop - Deletes pending timer and stops it's execution*/
68void timer_stop(void)
69{
70	del_timer(&drv_var.my_timer);
71}
72
73/* timer_exit - calls timer_stop function,
74 * will be executed once the module is removed from the linux kernel
75 */
76static void __exit timer_exit(void)
77{
78	pr_info("Inside timer_exit function\n");
79	timer_stop();
80	pr_info("Driver unloaded!\n");
81}
82
83module_init(timer_init);
84module_exit(timer_exit);
1obj-m += timer.o
2
3all:
4	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • Run make to compile the kernel source and generate the .ko image.

$ make
make -C /lib/modules/6.8.0/build M=/home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc2 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
  CC [M]  /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc2/timer.o
  MODPOST /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc2/Module.symvers
  CC [M]  /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc2/timer.mod.o
  LD [M]  /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc2/timer.ko
make[1]: Leaving directory '/home/test/Desktop/kernel_api/linux-6.8'
  • Check if the .ko is generated or not using ls command.

$ ls -l
total 376
-rw-rw-r-- 1 test test    155 Jul 19 14:57 Makefile
-rw-rw-r-- 1 test test     73 Jul 19 15:03 modules.order
-rw-rw-r-- 1 test test      0 Jul 19 15:03 Module.symvers
-rw-rw-r-- 1 test test   2143 Jul 19 14:57 timer.c
-rw-rw-r-- 1 test test 178696 Jul 19 15:03 timer.ko
-rw-rw-r-- 1 test test     73 Jul 19 15:03 timer.mod
-rw-rw-r-- 1 test test   1066 Jul 19 15:03 timer.mod.c
-rw-rw-r-- 1 test test 149232 Jul 19 15:03 timer.mod.o
-rw-rw-r-- 1 test test  30880 Jul 19 15:03 timer.o
  • Run modinfo command to get the information about the kernel module.

$ modinfo timer.ko
filename:       /home/test/Desktop/kernel_api/initialize_setup_kernel/tc2/timer.ko
description:    Timer
author:         Linux_usr
license:        GPL
srcversion:     11588D0D1B327CC872264E3
depends:
retpoline:      Y
name:           timer
vermagic:       6.8.0 SMP preempt mod_unload modversions
  • insert the module using insmod command.

$ sudo insmod ./timer.ko
  • check if the module is loaded or not using lsmod command.

$ lsmod | grep timer
timer                  12288  0
  • check for the kernel messages from init function and thread function once the module is loaded and thread is created.

$ sudo dmesg
[256798.753734] Inside timer_init function
[256798.753742] Driver loaded!
[256799.760700] Inside Timer Callback function
[256799.760720] timer_callback : data_a : 10
[256799.760729] timer_callback : data_b : 20
[256799.760735] timer_callback : data_c : a
[256799.760741] timer_callback : data_d : hello
  • remove the module from kernel using rmmod command.

$ sudo rmmod timer
  • check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.

$ lsmod | grep timer
  • Check for kernel messages from exit function using dmesg command.

$ sudo dmesg
[256810.134798] Inside timer_exit function
[256810.134801] Driver unloaded!
  • In this example let’s see how to set up the timer using timer_setup and execute it.

  • Include the follow header files(.h) to refer the API being used for the execution.

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/err.h>
  • Add the following module macros to display information about the license, author and description about the module.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("usr");
MODULE_DESCRIPTION("Timer");
  • Setting up the timer which we are going to create and use in this example

timer_setup(&drv_var.my_timer, timer_callback, 0);
  • This function executes once the timer expires.

static void timer_callback(struct timer_list * t)
{
        pr_info("Inside Timer Callback function\n");

        struct my_drv_info * my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
        pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
        pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
        pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
        pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
}
  • This function setup the timer to call timer_callback() using timer_setup_on_stack.

  • Modifies a timer’s timeout using mod_timer.

void timer_start(void)
{
        drv_var.data_a = 10;
        drv_var.data_b = 20;
        drv_var.data_c = 'a';
        strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));

        timer_setup_on_stack(&drv_var.my_timer, timer_callback, 0);
        mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
}
  • This function calls timer_start function, will be executed once the module is loaded into the linux kernel.

static int __init timer_init(void)
{
        pr_info("Inside timer_init function\n");
        timer_start();
        pr_info("Driver loaded!\n");
        return 0;
}
  • This function deletes a pending timer and wait for a running callback using del_timer_sync.

  • Destroy the timer using destroy_timer_on_stack.

void timer_stop(void)
{
        del_timer_sync(&drv_var.my_timer);
        destroy_timer_on_stack(&drv_var.my_timer);
}
  • This function calls timer_stop function, will be executed once the module is removed from the linux kernel.

static void __exit timer_exit(void)
{
        pr_info("Inside timer_exit function\n");
        timer_stop();
        pr_info("Driver unloaded!\n");
}
  • Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

module_init(timer_init);
module_exit(timer_exit);
 1/* timer_setup_on_stack */
 2
 3#include <linux/init.h>
 4#include <linux/kernel.h>
 5#include <linux/module.h>
 6#include <linux/fs.h>
 7#include <linux/timer.h>
 8#include <linux/jiffies.h>
 9#include <linux/err.h>
10
11#define TIMEOUT 1000 
12
13MODULE_LICENSE("GPL");
14MODULE_AUTHOR("Linux_usr");
15MODULE_DESCRIPTION("Timer");
16
17void timer_start(void);
18void timer_stop(void);
19
20struct my_drv_info {
21	struct timer_list my_timer;
22	int data_a;
23	int data_b;
24	char data_c;
25	char data_d[10];
26};
27
28struct my_drv_info drv_var;
29
30/* timer_callback - executes once the timer expires */
31static void timer_callback(struct timer_list *t)
32{
33	pr_info("Inside Timer Callback function\n");
34
35	struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
36	pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
37	pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
38	pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
39	pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
40}
41
42/* timer_start - setup the timer to call timer_callback() using timer_setup_on_stack,
43 * modifies a timer's timeout using mod_timer
44 */
45void timer_start(void)
46{
47	drv_var.data_a = 10;
48        drv_var.data_b = 20;
49        drv_var.data_c = 'a';
50        strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));
51
52        timer_setup_on_stack(&drv_var.my_timer, timer_callback, 0);
53        mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
54}
55
56/* timer_init - calls timer_start function,
57 * will be executed once the module is loaded into the linux kernel
58 */
59static int __init timer_init(void)
60{
61	pr_info("Inside timer_init function\n");
62	timer_start();
63	pr_info("Driver loaded!\n");
64	return 0;
65}
66
67/* timer_stop - deletes a pending timer and wait for a running callback using del_timer_sync,
68 * destroy the timer using destroy_timer_on_stack
69 */
70void timer_stop(void)
71{
72	del_timer_sync(&drv_var.my_timer);
73	destroy_timer_on_stack(&drv_var.my_timer);
74}
75
76/* timer_exit - calls timer_stop function,
77 * will be executed once the module is removed from the linux kernel
78 */
79static void __exit timer_exit(void)
80{
81	pr_info("Inside timer_exit function\n");
82	timer_stop();
83	pr_info("Driver unloaded!\n");
84}
85
86module_init(timer_init);
87module_exit(timer_exit);
1obj-m += timer.o
2
3all:
4	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • Run make to compile the kernel source and generate the .ko image.

       $ make
       make -C /lib/modules/6.8.0/build M=/home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc3 modules
       make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
         CC [M]  /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc3/timer.o
         MODPOST /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc3/Module.symvers
         CC [M]  /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc3/timer.mod.o
         LD [M]  /home/test/Desktop/kernel_api/readme/initialize_setup_kernel/tc3/timer.ko
       make[1]: Leaving directory '/home/test/Desktop/kernel_api/linux-6.8'


* Check if the .ko is generated or not using ls command.
$ ls -l
total 376
-rw-rw-r-- 1 test test    155 Jul 19 14:57 Makefile
-rw-rw-r-- 1 test test     73 Jul 19 15:03 modules.order
-rw-rw-r-- 1 test test      0 Jul 19 15:03 Module.symvers
-rw-rw-r-- 1 test test   2143 Jul 19 14:57 timer.c
-rw-rw-r-- 1 test test 178696 Jul 19 15:03 timer.ko
-rw-rw-r-- 1 test test     73 Jul 19 15:03 timer.mod
-rw-rw-r-- 1 test test   1066 Jul 19 15:03 timer.mod.c
-rw-rw-r-- 1 test test 149232 Jul 19 15:03 timer.mod.o
-rw-rw-r-- 1 test test  30880 Jul 19 15:03 timer.o
  • Run modinfo command to get the information about the kernel module.

$ modinfo timer.ko
filename:       /home/test/Desktop/kernel_api/initialize_setup_kernel/tc3/timer.ko
description:    Timer
author:         Linux_usr
license:        GPL
srcversion:     11588D0D1B327CC872264E3
depends:
retpoline:      Y
name:           timer
vermagic:       6.8.0 SMP preempt mod_unload modversions
  • insert the module using insmod command.

$ sudo insmod ./timer.ko
  • check if the module is loaded or not using lsmod command.

$ lsmod | grep timer
timer                  12288  0
  • check for the kernel messages from init function and thread function once the module is loaded and thread is created.

$ sudo dmesg
[256878.615288] Inside timer_init function
[256878.615300] Driver loaded!
[256879.632313] Inside Timer Callback function
[256879.632339] timer_callback : data_a : 10
[256879.632346] timer_callback : data_b : 20
[256879.632351] timer_callback : data_c : a
[256879.632355] timer_callback : data_d : hello
  • remove the module from kernel using rmmod command.

$ sudo rmmod timer
  • check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.

$ lsmod | grep timer
  • Check for kernel messages from exit function using dmesg command.

$ sudo dmesg
[256885.285473] Inside timer_exit function
[256885.285482] Driver unloaded!