Start Timer =========== .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`Version Info ` * :ref:`Learnings in this section ` * :ref:`Explanation of timer APIs ` * :ref:`from_timer ` * :ref:`add_timer ` * :ref:`del_timer ` * :ref:`timer_setup ` * :ref:`mod_timer ` * :ref:`add_timer_on ` * :ref:`Explanation of miscellaneous APIs ` * :ref:`Module parameter APIs ` * :ref:`Driver entry point APIs ` * :ref:`Example 1: Start the timer using add_timer ` * :ref:`List of headers ` * :ref:`Module Macros ` * :ref:`Setting up the timer ` * :ref:`Timer Handler Function ` * :ref:`Timer Start Function ` * :ref:`Timer Init Function ` * :ref:`Timer Stop Function ` * :ref:`Timer Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and load the module ` * :ref:`Example 2: Start the timer using add_timer_on ` * :ref:`List of headers ` * :ref:`Module Macros ` * :ref:`Setting up the timer ` * :ref:`Timer Handler Function ` * :ref:`Timer Start Function ` * :ref:`Timer Init Function ` * :ref:`Timer Stop Function ` * :ref:`Timer Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and load the module ` .. _p1_timerstart_0: .. tab-set:: .. tab-item:: Version Info =============================== ======================================= # Version =============================== ======================================= Ubuntu Ubuntu 22.10 Kernel 6.8.0 =============================== ======================================= .. _p1_timerstart_1: .. tab-set:: .. tab-item:: Learnings in this section * In this program, you are going to learn .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to create timer ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to start the timer ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to set up the timer ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to stop the timer ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use timer APIs ? * `from_timer `_ * `add_timer `_ * `del_timer `_ * `timer_setup `_ * `mod_timer `_ * `add_timer_on `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use below APIs ? * `MODULE_LICENSE `_ * `MODULE_DESCRIPTION `_ * `MODULE_AUTHOR `_ * `module_init `_ * `module_exit `_ .. _p1_timerstart_2: .. tab-set:: .. tab-item:: Explanation of timer APIs .. _p1_timerstart_3: .. tab-set:: .. tab-item:: from_timer * Here is the function prototype of the API: `from_timer `_ .. code-block:: c #include #define from_timer(var, callback_timer, timer_fieldname) .. _p1_timerstart_4: .. tab-set:: .. tab-item:: add_timer * Here is the function prototype of the API: `add_timer `_ .. code-block:: c #include extern void add_timer(struct timer_list *timer); .. _p1_timerstart_5: .. tab-set:: .. tab-item:: del_timer * Here is the function prototype of the API: `del_timer `_ .. code-block:: c #include static inline int del_timer(struct timer_list *timer); .. _p1_timerstart_7: .. tab-set:: .. tab-item:: timer_setup * Here is the function prototype of the API: `timer_setup `_ .. code-block:: c #include #define timer_setup(timer, callback, flags) .. _p1_timerstart_8: .. tab-set:: .. tab-item:: mod_timer * Here is the function prototype of the API: `mod_timer `_ .. code-block:: c #include extern int mod_timer(struct timer_list *timer, unsigned long expires); .. _p1_timerstart_9: .. tab-set:: .. tab-item:: add_timer_on * Here is the function prototype of the API: `add_timer_on `_ .. code-block:: c #include extern void add_timer_on(struct timer_list *timer, int cpu); .. _p1_timerstart_12: .. tab-set:: .. tab-item:: Explanation of miscellaneous APIs .. _p1_timerstart_13: .. tab-set:: .. tab-item:: Module parameter APIs * Here is the prototype of module paramter APIs .. code-block:: c #include #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, .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("usr"); MODULE_DESCRIPTION("Timer"); .. _p1_timerstart_14: .. tab-set:: .. tab-item:: Driver entry point API's * Here is the prototype of the Driver entry point API's .. code-block:: c #include #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 .. code-block:: c module_init(task_init); module_exit(task_exit); .. _p1_timerstart_15: .. tab-set:: .. tab-item:: Example 1: Start the timer using add_timer * In this example let's see how to start the timer using add_timer and execute it. .. _p1_timerstart_16: .. tab-set:: .. tab-item:: List of headers * Include the follow header files(.h) to refer the API being used for the execution. .. code-block:: c #include #include #include #include #include #include #include .. _p1_timerstart_17: .. tab-set:: .. tab-item:: Module macros * Add the following module macros to display information about the license, author and description about the module. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("usr"); MODULE_DESCRIPTION("Timer"); .. _p1_timerstart_18: .. tab-set:: .. tab-item:: Setting up the timer * Setting up the timer which we are going to create and use in this example .. code-block:: c timer_setup(&drv_var.my_timer, timer_callback, 0); .. _p1_timerstart_19: .. tab-set:: .. tab-item:: Timer Handler Function * This function executes once the timer expires. .. code-block:: c 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); mod_timer(&my_drv_info_ptr->my_timer, jiffies + msecs_to_jiffies(TIMEOUT)); } .. _p1_timerstart_20: .. tab-set:: .. tab-item:: Timer Start Function * This function setup the timer to call timer_callback() using timer_setup. * Starts timer using add_timer. .. code-block:: c 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); add_timer(&drv_var.my_timer); } .. _p1_timerstart_21: .. tab-set:: .. tab-item:: Timer Init Function * This function calls timer_start function, will be executed once the module is loaded into the linux kernel. .. code-block:: c static int __init timer_init(void) { pr_info("Inside timer_init function\n"); timer_start(); pr_info("Driver loaded!\n"); return 0; } .. _p1_timerstart_22: .. tab-set:: .. tab-item:: Timer Stop Function * This function deletes pending timer and stops it's execution. .. code-block:: c void timer_stop(void) { del_timer(&drv_var.my_timer); } .. _p1_timerstart_23: .. tab-set:: .. tab-item:: Timer Exit Function * This function calls timer_stop function, will be executed once the module is removed from the linux kernel. .. code-block:: c static void __exit timer_exit(void) { pr_info("Inside timer_exit function\n"); timer_stop(); pr_info("Driver unloaded!\n"); } .. _p1_timerstart_24: .. tab-set:: .. tab-item:: Driver entry points * Add the driver entry points which will be executed once the module is inserted or removed from the kernel. .. code-block:: c module_init(timer_init); module_exit(timer_exit); .. _p1_timerstart_25: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: timer.c .. literalinclude:: start_timer/tc1/timer.c :language: c :linenos: .. _p1_timerstart_26: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: start_timer/tc1/Makefile :language: c :linenos: .. _p1_timerstart_27: .. tab-set:: .. tab-item:: Compile and load the module * Run make to compile the kernel source and generate the .ko image. .. code-block:: shell $ make make -C /lib/modules/6.8.0/build M=/home/test/Desktop/kernel_api/start_timer/tc1 modules make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8' CC [M] /home/test/Desktop/kernel_api/start_timer/tc1/timer.o MODPOST /home/test/Desktop/kernel_api/start_timer/tc1/Module.symvers CC [M] /home/test/Desktop/kernel_api/start_timer/tc1/timer.mod.o LD [M] /home/test/Desktop/kernel_api/start_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. .. code-block:: shell $ 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. .. code-block:: shell $ modinfo timer.ko filename: /home/test/Desktop/kernel_api/start_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. .. code-block:: shell $ sudo insmod ./timer.ko * check if the module is loaded or not using lsmod command. .. code-block:: shell $ 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. .. code-block:: shell $ sudo dmesg [257437.535046] Inside timer_init function [257437.535054] Driver loaded! [257437.535998] Inside Timer Callback function [257437.536001] timer_callback : data_a : 10 [257437.536005] timer_callback : data_b : 20 [257437.536007] timer_callback : data_c : a [257437.536009] timer_callback : data_d : hello [257442.540044] Inside Timer Callback function [257442.540085] timer_callback : data_a : 10 [257442.540094] timer_callback : data_b : 20 [257442.540100] timer_callback : data_c : a [257442.540104] timer_callback : data_d : hello * remove the module from kernel using rmmod command. .. code-block:: shell $ 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. .. code-block:: shell $ lsmod | grep timer * Check for kernel messages from exit function using dmesg command. .. code-block:: shell $ sudo dmesg [257452.054507] Inside timer_exit function [257452.054517] Driver unloaded! .. _p1_timerstart_28: .. tab-set:: .. tab-item:: Example 2: Start the timer using add_timer_on * In this example let's see how to start the timer using add_timer_on and execute it. .. _p1_timerstart_29: .. tab-set:: .. tab-item:: List of headers * Include the follow header files(.h) to refer the API being used for the execution. .. code-block:: c #include #include #include #include #include #include #include .. _p1_timerstart_30: .. tab-set:: .. tab-item:: Module macros * Add the following module macros to display information about the license, author and description about the module. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("usr"); MODULE_DESCRIPTION("Timer"); .. _p1_timerstart_31: .. tab-set:: .. tab-item:: Setting up the timer * Setting up the timer which we are going to create and use in this example .. code-block:: c timer_setup(&drv_var.my_timer, timer_callback, 0); .. _p1_timerstart_32: .. tab-set:: .. tab-item:: Timer Handler Function * This function executes once the timer expires. .. code-block:: c 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); } .. _p1_timerstart_33: .. tab-set:: .. tab-item:: Timer Start Function * This function setup the timer to call timer_callback() using timer_setup. * Starts timer using add_timer_on. .. code-block:: c void timer_start(void) { int cpu = 0; 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); add_timer_on(&drv_var.my_timer, cpu); } .. _p1_timerstart_34: .. tab-set:: .. tab-item:: Timer Init Function * This function calls timer_start function, will be executed once the module is loaded into the linux kernel. .. code-block:: c static int __init timer_init(void) { pr_info("Inside timer_init function\n"); timer_start(); pr_info("Driver loaded!\n"); return 0; } .. _p1_timerstart_35: .. tab-set:: .. tab-item:: Timer Stop Function * This function deletes pending timer and stops it's execution. .. code-block:: c void timer_stop(void) { del_timer(&drv_var.my_timer); } .. _p1_timerstart_36: .. tab-set:: .. tab-item:: Timer Exit Function * This function calls timer_stop function, will be executed once the module is removed from the linux kernel. .. code-block:: c static void __exit timer_exit(void) { pr_info("Inside timer_exit function\n"); timer_stop(); pr_info("Driver unloaded!\n"); } .. _p1_timerstart_37: .. tab-set:: .. tab-item:: Driver entry points * Add the driver entry points which will be executed once the module is inserted or removed from the kernel. .. code-block:: c module_init(timer_init); module_exit(timer_exit); .. _p1_timerstart_38: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: timer.c .. literalinclude:: start_timer/tc2/timer.c :language: c :linenos: .. _p1_timerstart_39: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: start_timer/tc2/Makefile :language: c :linenos: .. _p1_timerstart_40: .. tab-set:: .. tab-item:: Compile and load the module * Run make to compile the kernel source and generate the .ko image. .. code-block:: shell $ make make -C /lib/modules/6.8.0/build M=/home/test/Desktop/kernel_api/start_timer/tc2 modules make[1]: Entering directory '/home/test/Desktop/kernel_api/linux-6.8' CC [M] /home/test/Desktop/kernel_api/start_timer/tc2/timer.o MODPOST /home/test/Desktop/kernel_api/start_timer/tc2/Module.symvers CC [M] /home/test/Desktop/kernel_api/start_timer/tc2/timer.mod.o LD [M] /home/test/Desktop/kernel_api/start_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. .. code-block:: shell $ 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. .. code-block:: shell $ modinfo timer.ko filename: /home/test/Desktop/kernel_api/start_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. .. code-block:: shell $ sudo insmod ./timer.ko * check if the module is loaded or not using lsmod command. .. code-block:: shell $ 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. .. code-block:: shell $ sudo dmesg [257507.421232] Inside timer_init function [257507.421243] Driver loaded! [257507.423480] Inside Timer Callback function [257507.423492] timer_callback : data_a : 10 [257507.423499] timer_callback : data_b : 20 [257507.423502] timer_callback : data_c : a [257507.423504] timer_callback : data_d : hello * remove the module from kernel using rmmod command. .. code-block:: shell $ 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. .. code-block:: shell $ lsmod | grep timer * Check for kernel messages from exit function using dmesg command. .. code-block:: shell $ sudo dmesg [257549.931569] Inside timer_exit function [257549.931573] Driver unloaded!