Timer : Periodic

  • In this program, you are going to learn

  • How to create the kernel timer ?

  • How to modify the timer’s timeout ?

  • A timer is a specialized type of clock used for measuring specific time intervals.

  • timer_setup used to initialize and set up a timer object.

timer_setup(&my_timer, timer_callback, 0);
  • mod_timer used to modify a timer’s timeout. This is a more efficient way to update the expires field of an active timer (if the timer is inactive it will be activated). For example,

mod_timer(&my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
  • del_timer used to stop a running timer and prevent it’s callback function from being executed. For example

del_timer(&my_timer);
  • To modify the timers timeout periodically, again we need to call the mod_timer inside the timer_callback.

static void timer_callback(struct timer_list * timer)
{
        pr_info("Timer Callback function Called [%d]\n", count++);
        mod_timer(&my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
}
  • Here is the part by part explanation of the source code.

  • Add the list of headers to the refer the APIs used in this source code.

#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 modules macro which gives information about the author, license and description.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux_usr");
MODULE_DESCRIPTION("Periodic Timer");
  • Initialize the functions and variables to be using in this program.

static struct timer_list my_timer;

static void timer_callback(struct timer_list *timer)
  • Create the module init function to execute when the module is loaded to kernel.

static int __init timer_init(void)
{
    pr_info("Hello world\n");

    timer_setup(&my_timer, timer_callback, 0);
    mod_timer(&my_timer, jiffies + msecs_to_jiffies(TIMEOUT));

    return 0;
}
  • Create the module exit function which executes once when the module is unloaded from the kernel.

static void __exit timer_exit(void)
{
    del_timer(&my_timer);
    pr_info("Good bye, world\n");
}
  • Create the timer APIs which will be executed once the timer is called.

static void timer_callback(struct timer_list *timer)
{
    pr_info("Timer Callback function Called [%d]\n", count++);

        mod_timer(&my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
}
  • Add the module init and exit functions to execute it once the module is loaded and unloaded.

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 count;
11
12static struct timer_list my_timer;
13
14MODULE_LICENSE("GPL");
15MODULE_AUTHOR("Linux_usr");
16MODULE_DESCRIPTION("Periodic Timer");
17
18static void timer_callback(struct timer_list *timer)
19{
20	pr_info("Timer Callback function Called [%d]\n", count++);
21
22	mod_timer(&my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
23}
24
25static int __init chardev_init(void)
26{
27	pr_info("Hello world\n");
28
29	timer_setup(&my_timer, timer_callback, 0);
30	mod_timer(&my_timer, jiffies + msecs_to_jiffies(TIMEOUT));
31
32	return 0;
33}
34
35static void __exit chardev_exit(void)
36{
37	del_timer(&my_timer);
38	pr_info("Good bye, world\n");
39}
40
41module_init(chardev_init);
42module_exit(chardev_exit);
1obj-m += timer.o
2all:
3	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
4clean:
5	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • Run make to compile the kernel module.

$ make
make -C /lib/modules/5.4.0-150-generic/build M=$HOME/kernel_timer modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-150-generic'
  CC [M]  $HOME/kernel_timer/timer.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC [M]  $HOME/kernel_timer/timer.mod.o
  LD [M]  $HOME/kernel_timer/timer.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-150-generic'
  • Check if timer.ko is generated or not using ls command.

$ ls -l
total 36
-rw-rw-r-- 1 test test  154 Feb 26 13:18 Makefile
-rw-rw-r-- 1 test test   47 Feb 26 13:18 modules.order
-rw-rw-r-- 1 test test    0 Feb 26 13:18 Module.symvers
-rw-rw-r-- 1 test test  820 Feb 26 13:18 timer.c
-rw-rw-r-- 1 test test 5880 Feb 26 13:18 timer.ko
-rw-rw-r-- 1 test test   47 Feb 26 13:18 timer.mod
-rw-rw-r-- 1 test test  919 Feb 26 13:18 timer.mod.c
-rw-rw-r-- 1 test test 3448 Feb 26 13:18 timer.mod.o
-rw-rw-r-- 1 test test 3320 Feb 26 13:18 timer.o
  • Run insmod command to load the module in kernel.

$ sudo insmod ./timer.ko
  • Check kernel messages to see if the module is loaded or not.

$ dmesg
[  404.787513] Hello world
[  409.821548] Timer Callback function Called [0]
[  414.941540] Timer Callback function Called [1]
[  420.061548] Timer Callback function Called [2]
[  425.181498] Timer Callback function Called [3]
[  430.301546] Timer Callback function Called [4]
[  435.421542] Timer Callback function Called [5]
[  440.541522] Timer Callback function Called [6]
[  445.661495] Timer Callback function Called [7]
[  450.781472] Timer Callback function Called [8]
[  455.901446] Timer Callback function Called [9]
[  461.021382] Timer Callback function Called [10]
  • Run rmmod to unload the kernel module.

$ sudo rmmod timer
  • Check the kernel messages to see if the module is unloaded or not.

$ dmesg
[  404.787513] Hello world
[  409.821548] Timer Callback function Called [0]
[  414.941540] Timer Callback function Called [1]
[  420.061548] Timer Callback function Called [2]
[  425.181498] Timer Callback function Called [3]
[  430.301546] Timer Callback function Called [4]
[  435.421542] Timer Callback function Called [5]
[  440.541522] Timer Callback function Called [6]
[  445.661495] Timer Callback function Called [7]
[  450.781472] Timer Callback function Called [8]
[  455.901446] Timer Callback function Called [9]
[  461.021382] Timer Callback function Called [10]
[  461.553199] Good bye, world

API

Learning

timer_setup

To initialize the timer

mod_timer

To modify a timer’s timeout

del_timer

To stop a running timer

msecs_to_jiffies

To convert milliseconds