Modify Timer
Topics in this section,
# |
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 modify the timer ?
How to stop the timer ?
How to use timer APIs ?
How to use below APIs ?
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);
Here is the function prototype of the API: timer_reduce
#include <linux/timer.h>
extern int timer_reduce(struct timer_list *timer, unsigned long expires);
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);
Here is the function prototype of the API: mod_timer_pending
#include <linux/timer.h>
extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
Here is the function prototype of the API: timer_shutdown
#include <linux/timer.h>
extern int timer_shutdown(struct timer_list *timer);
Here is the function prototype of the API: timer_shutdown_sync
#include <linux/timer.h>
extern int timer_shutdown_sync(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 modify the pending timer’s timeout using mod_timer_pending 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);
}
Setup the timer to call timer_callback() using timer_setup.
Modifies a timer’s timeout using mod_timer.
Modifies a pending timer’s timeout.
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));
if (mod_timer_pending(&drv_var.my_timer,jiffies + msecs_to_jiffies(TIMEOUT_PENDING))) {
pr_info("Modified pending timer's timeout\n");
}
}
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#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/fs.h>
5#include <linux/timer.h>
6#include <linux/jiffies.h>
7#include <linux/err.h>
8
9#define TIMEOUT 100
10#define TIMEOUT_PENDING 200
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Linux_usr");
14MODULE_DESCRIPTION("Timer");
15
16void timer_start(void);
17void timer_stop(void);
18
19struct my_drv_info {
20 struct timer_list my_timer;
21 int data_a;
22 int data_b;
23 char data_c;
24 char data_d[10];
25};
26
27struct my_drv_info drv_var;
28
29/* timer_callback - executes once the timer expires */
30static void timer_callback(struct timer_list *t)
31{
32 pr_info("Inside Timer Callback function\n");
33
34 struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
35 pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
36 pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
37 pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
38 pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
39}
40
41/* timer_start - setup the timer to call timer_callback() using timer_setup,
42 * modifies a timer's timeout using mod_timer,
43 * modifies a pending timer's timeout
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
54 mod_timer(&drv_var.my_timer,jiffies + msecs_to_jiffies(TIMEOUT));
55 if (mod_timer_pending(&drv_var.my_timer,jiffies + msecs_to_jiffies(TIMEOUT_PENDING))) {
56 pr_info("Modified pending timer's timeout\n");
57 }
58}
59
60/* timer_init - calls timer_start function,
61 * will be executed once the module is loaded into the linux kernel
62 */
63static int __init timer_init(void)
64{
65 pr_info("Inside timer_init function\n");
66 timer_start();
67 pr_info("Driver loaded!\n");
68 return 0;
69}
70
71/* timer_stop - Deletes pending timer and stops it's execution */
72void timer_stop(void)
73{
74 del_timer(&drv_var.my_timer);
75}
76
77/* timer_exit - calls timer_stop function,
78 * will be executed once the module is removed from the linux kernel
79 */
80static void __exit timer_exit(void)
81{
82 pr_info("Inside timer_exit function\n");
83 timer_stop();
84 pr_info("Driver unloaded!\n");
85}
86
87module_init(timer_init);
88module_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/modify_timer/tc1 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc1/timer.o
MODPOST /home/test/Desktop/kernel_api/modify_timer/tc1/Module.symvers
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc1/timer.mod.o
LD [M] /home/test/Desktop/kernel_api/modify_timer/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/modify_timer/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
[256964.707391] Inside timer_init function
[256964.707394] Modified pending timers timeout
[256964.707395] Driver loaded!
[256964.907495] Inside Timer Callback function
[256964.907511] timer_callback : data_a : 10
[256964.907518] timer_callback : data_b : 20
[256964.907523] timer_callback : data_c : a
[256964.907526] 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
[256969.993910] Inside timer_exit function
[256969.993917] Driver unloaded!
In this example let’s see how to reduce the timer’s timeout using timer_reduce 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.
Modifies a timer’s timeout using mod_timer.
Modifies a timer’s timeout if it would reduce the timeout using timer_reduce.
static void timer_callback(struct timer_list * t)
{
int ret;
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);
mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
ret = timer_reduce(&drv_var.my_timer, jiffies + reduce_timeout);
if (ret)
pr_info("timer reduced\n");
else
pr_info("failed to reduce timer\n");
}
Setup the timer to call timer_callback() using timer_setup.
Modifies a timer’s timeout using mod_timer.
void timer_start(void)
{
pr_info("reduced_timeout : %d\n", reduce_timeout);
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#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/fs.h>
5#include <linux/timer.h>
6#include <linux/jiffies.h>
7#include <linux/err.h>
8
9#define TIMEOUT 5000
10static unsigned int reduce_timeout = 10 * HZ;
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Linux_usr");
14MODULE_DESCRIPTION("Timer");
15
16void timer_start(void);
17void timer_stop(void);
18
19struct my_drv_info {
20 struct timer_list my_timer;
21 int data_a;
22 int data_b;
23 char data_c;
24 char data_d[10];
25};
26
27struct my_drv_info drv_var;
28
29/* timer_callback - executes once the timer expires,
30 * modifies a timer's timeout using mod_timer,
31 * modifies a timer's timeout if it would reduce the timeout using timer_reduce
32 */
33static void timer_callback(struct timer_list *t)
34{
35 int ret;
36 pr_info("Inside Timer Callback function\n");
37
38 struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
39
40 pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
41 pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
42 pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
43 pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
44
45 mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
46
47 ret = timer_reduce(&drv_var.my_timer, jiffies + reduce_timeout);
48 if (ret)
49 pr_info("timer reduced\n");
50 else
51 pr_info("failed to reduce timer\n");
52}
53
54/* timer_start - setup the timer to call timer_callback() using timer_setup,
55 * modifies a timer's timeout using mod_timer
56 */
57void timer_start(void)
58{
59 pr_info("reduced_timeout : %d\n", reduce_timeout);
60
61 drv_var.data_a = 10;
62 drv_var.data_b = 20;
63 drv_var.data_c = 'a';
64 strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));
65
66 timer_setup(&drv_var.my_timer, timer_callback, 0);
67 mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
68}
69
70/* timer_init - calls timer_start function,
71 * will be executed once the module is loaded into the linux kernel
72 */
73static int __init timer_init(void)
74{
75 pr_info("Inside timer_init function\n");
76 timer_start();
77 pr_info("Driver loaded!\n");
78
79 return 0;
80}
81
82/* timer_stop - Deletes pending timer and stops it's execution */
83void timer_stop(void)
84{
85 del_timer(&drv_var.my_timer);
86}
87
88/* timer_exit - calls timer_stop function,
89 * will be executed once the module is removed from the linux kernel
90 */
91static void __exit timer_exit(void)
92{
93 pr_info("Inside timer_exit function\n");
94 timer_stop();
95 pr_info("Driver unloaded\n");
96}
97
98module_init(timer_init);
99module_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/modify_timer/tc2 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc2/timer.o
MODPOST /home/test/Desktop/kernel_api/modify_timer/tc2/Module.symvers
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc2/timer.mod.o
LD [M] /home/test/Desktop/kernel_api/modify_timer/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/modify_timer/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
[257088.096561] Inside timer_init function
[257088.096568] reduced_timeout : 2500
[257088.096574] Driver loaded!
[257093.102709] Inside Timer Callback function
[257093.102747] timer_callback : data_a : 10
[257093.102755] timer_callback : data_b : 20
[257093.102758] timer_callback : data_c : a
[257093.102762] timer_callback : data_d : hello
[257093.102767] timer reduced
[257098.222688] Inside Timer Callback function
[257098.222731] timer_callback : data_a : 10
[257098.222738] timer_callback : data_b : 20
[257098.222742] timer_callback : data_c : a
[257098.222746] timer_callback : data_d : hello
[257098.222751] timer reduced
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
[257105.303191] Inside timer_exit function
[257105.303198] Driver unloaded
In this example let’s see how to deactivate the timer using timer_shutdown 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(&drv_var.my_timer, timer_callback, 0);
int ret = mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
if (ret)
pr_info("Timer firing failed\n");
}
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 deactivates timer and stops it’s execution
void timer_stop(void)
{
int ret;
ret = timer_shutdown(&drv_var.my_timer);
if (ret)
pr_info("still in use\n");
}
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#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/fs.h>
5#include <linux/timer.h>
6#include <linux/jiffies.h>
7#include <linux/err.h>
8
9#define TIMEOUT 100
10
11MODULE_LICENSE("GPL");
12MODULE_AUTHOR("Linux_usr");
13MODULE_DESCRIPTION("Timer");
14
15void timer_start(void);
16void timer_stop(void);
17
18struct my_drv_info {
19 struct timer_list my_timer;
20 int data_a;
21 int data_b;
22 char data_c;
23 char data_d[10];
24};
25
26struct my_drv_info drv_var;
27
28/* timer_callback - executes once the timer expires */
29static void timer_callback(struct timer_list *t)
30{
31 pr_info("Inside Timer Callback function\n");
32
33 struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
34
35 pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
36 pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
37 pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
38 pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
39}
40
41/* timer_start - setup the timer to call timer_callback() using timer_setup,
42 * modifies a timer's timeout using mod_timer
43 */
44void timer_start(void)
45{
46 drv_var.data_a = 10;
47 drv_var.data_b = 20;
48 drv_var.data_c = 'a';
49 strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));
50
51 timer_setup(&drv_var.my_timer, timer_callback, 0);
52 int ret = mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
53 if (ret)
54 pr_info("Timer firing failed\n");
55}
56
57/* timer_init - calls timer_start function,
58 * will be executed once the module is loaded into the linux kernel
59 */
60static int __init timer_init(void)
61{
62 pr_info("Inside timer_init function\n");
63 timer_start();
64 pr_info("Driver loaded!\n");
65 return 0;
66}
67
68/* timer_stop - deactivates timer and stops it's execution */
69void timer_stop(void)
70{
71 int ret;
72 ret = timer_shutdown(&drv_var.my_timer);
73
74 if (ret)
75 pr_info("still in use\n");
76}
77
78/* timer_exit - calls timer_stop function,
79 * will be executed once the module is removed from the linux kernel
80 */
81static void __exit timer_exit(void)
82{
83 pr_info("Inside timer_exit function\n");
84 timer_stop();
85 pr_info("Driver unloaded!\n");
86}
87
88module_init(timer_init);
89module_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/modify_timer/tc3 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc3/timer.o
MODPOST /home/test/Desktop/kernel_api/modify_timer/tc3/Module.symvers
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc3/timer.mod.o
LD [M] /home/test/Desktop/kernel_api/modify_timer/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/modify_timer/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
[257256.265603] Inside timer_init function
[257256.265612] Driver loaded!
[257256.369488] Inside Timer Callback function
[257256.369511] timer_callback : data_a : 10
[257256.369518] timer_callback : data_b : 20
[257256.369522] timer_callback : data_c : a
[257256.369526] 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
[257262.607341] Inside timer_exit function
[257262.607349] Driver unloaded!
In this example let’s see how to deactivate the timer using timer_shutdown 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(&drv_var.my_timer, timer_callback, 0);
int ret = mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
if (ret)
pr_info("Timer firing failed\n");
}
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 deactivates timer and stops it’s execution
void timer_stop(void)
{
int ret;
ret = timer_shutdown_sync(&drv_var.my_timer);
if (ret)
pr_info("still in use\n");
}
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#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/fs.h>
5#include <linux/timer.h>
6#include <linux/jiffies.h>
7#include <linux/err.h>
8
9#define TIMEOUT 100
10
11MODULE_LICENSE("GPL");
12MODULE_AUTHOR("Linux_usr");
13MODULE_DESCRIPTION("Timer");
14
15void timer_start(void);
16void timer_stop(void);
17
18struct my_drv_info {
19 struct timer_list my_timer;
20 int data_a;
21 int data_b;
22 char data_c;
23 char data_d[10];
24};
25
26struct my_drv_info drv_var;
27
28/* timer_callback - executes once the timer expires */
29static void timer_callback(struct timer_list *t)
30{
31 pr_info("Inside Timer Callback function\n");
32
33 struct my_drv_info *my_drv_info_ptr = from_timer(my_drv_info_ptr, t, my_timer);
34 pr_info("%s : data_a : %d\n", __func__, my_drv_info_ptr->data_a);
35 pr_info("%s : data_b : %d\n", __func__, my_drv_info_ptr->data_b);
36 pr_info("%s : data_c : %c\n", __func__, my_drv_info_ptr->data_c);
37 pr_info("%s : data_d : %s\n", __func__, my_drv_info_ptr->data_d);
38}
39
40/* timer_start - setup the timer to call timer_callback() using timer_setup,
41 * modifies a timer's timeout using mod_timer
42 */
43void timer_start(void)
44{
45 drv_var.data_a = 10;
46 drv_var.data_b = 20;
47 drv_var.data_c = 'a';
48 strncpy(drv_var.data_d, "hello", sizeof(drv_var.data_d));
49
50 timer_setup(&drv_var.my_timer, timer_callback, 0);
51 int ret = mod_timer(&drv_var.my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
52 if (ret)
53 pr_info("Timer firing failed\n");
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 - deactivates timer and stops it's execution */
68void timer_stop(void)
69{
70 int ret;
71 ret = timer_shutdown_sync(&drv_var.my_timer);
72
73 if (ret)
74 pr_info("still in use\n");
75}
76
77/* timer_exit - calls timer_stop function,
78 * will be executed once the module is removed from the linux kernel
79 */
80static void __exit timer_exit(void)
81{
82 pr_info("Inside timer_exit function\n");
83 timer_stop();
84 pr_info("Driver unloaded!\n");
85}
86
87module_init(timer_init);
88module_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/modify_timer/tc4 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc4/timer.o
MODPOST /home/test/Desktop/kernel_api/modify_timer/tc4/Module.symvers
CC [M] /home/test/Desktop/kernel_api/modify_timer/tc4/timer.mod.o
LD [M] /home/test/Desktop/kernel_api/modify_timer/tc4/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/modify_timer/tc4/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
[257311.387616] Inside timer_init function
[257311.387620] Driver loaded!
[257311.488936] Inside Timer Callback function
[257311.488942] timer_callback : data_a : 10
[257311.488944] timer_callback : data_b : 20
[257311.488945] timer_callback : data_c : a
[257311.488946] 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
[257323.354287] Inside timer_exit function
[257323.354288] Driver unloaded!