Stop 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 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: timer_delete
#include <linux/timer.h>
extern int timer_delete(struct timer_list *timer);
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 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 deactivate the 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");
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.
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 deactivate timer and stops it’s execution.
void timer_stop(void)
{
int ret = timer_delete(&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 1000
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 - deactivate a timer and stops it's execution */
69void timer_stop(void)
70{
71 int ret = timer_delete(&drv_var.my_timer);
72 if (ret)
73 pr_info("still in use\n");
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/stop_timer/tc1 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
CC [M] /home/test/Desktop/kernel_api/stop_timer/tc1/timer.o
MODPOST /home/test/Desktop/kernel_api/stop_timer/tc1/Module.symvers
CC [M] /home/test/Desktop/kernel_api/stop_timer/tc1/timer.mod.o
LD [M] /home/test/Desktop/kernel_api/stop_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/stop_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
[257621.785684] Inside timer_init function
[257621.785693] Driver loaded!
[257622.794683] Inside Timer Callback function
[257622.794690] timer_callback : data_a : 10
[257622.794695] timer_callback : data_b : 20
[257622.794698] timer_callback : data_c : a
[257622.794700] 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
[257654.203397] Inside timer_exit function
[257654.203403] Driver unloaded!
In this example let’s see how to deactivate the 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");
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.
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 deactivate timer and stops it’s execution.
void timer_stop(void)
{
int ret = timer_delete_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 1000
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 using timer_delete_sync,
69 * it will wait for the handler to finish
70 */
71void timer_stop(void)
72{
73 int ret = timer_delete_sync(&drv_var.my_timer);
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/stop_timer/tc2 modules
make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8'
CC [M] /home/test/Desktop/kernel_api/stop_timer/tc2/timer.o
MODPOST /home/test/Desktop/kernel_api/stop_timer/tc2/Module.symvers
CC [M] /home/test/Desktop/kernel_api/stop_timer/tc2/timer.mod.o
LD [M] /home/test/Desktop/kernel_api/stop_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/stop_timer/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
[257721.648087] Inside timer_init function
[257721.648099] Driver loaded!
[257722.666083] Inside Timer Callback function
[257722.666110] timer_callback : data_a : 10
[257722.666118] timer_callback : data_b : 20
[257722.666123] timer_callback : data_c : a
[257722.666127] 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
[257738.912800] Inside timer_exit function
[257738.912810] Driver unloaded!