Create Dynamic Work =================== .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`Version Info ` * :ref:`Learnings in this program ` * :ref:`Explanation of Workqueue APIs ` * :ref:`create_workqueue ` * :ref:`INIT_WORK ` * :ref:`queue_work ` * :ref:`destroy_workqueue ` * :ref:`INIT_WORK_ONSTACK ` * :ref:`INIT_DELAYED_WORK ` * :ref:`queue_delayed_work ` * :ref:`cancel_delayed_work_sync ` * :ref:`INIT_DELAYED_WORK_ONSTACK ` * :ref:`INIT_DEFERRABLE_WORK ` * :ref:`schedule_delayed_work ` * :ref:`cancel_delayed_work ` * :ref:`INIT_RCU_WORK ` * :ref:`queue_rcu_work ` * :ref:`flush_workqueue ` * :ref:`Example 1 : Creating a workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initializing work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 2 : Creating a workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initializing work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 3 : Creating a workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initializing work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 4 : Creating a workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initializing work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 5 : Creating a workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initializing work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 6 : Creating a workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initializing work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` .. _create_dynamic_workqueue_0: .. tab-set:: .. tab-item:: Version Info =============================== ======================================= # Version =============================== ======================================= Ubuntu Ubuntu 22.10 Kernel 6.8.0 =============================== ======================================= .. _create_dynamic_workqueue_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 workqueue ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to allocate the work to the queue ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use Workqueue APIs ? * `create_workqueue `_ * `INIT_WORK `_ * `queue_work `_ * `destroy_workqueue `_ * `INIT_WORK_ONSTACK `_ * `INIT_DELAYED_WORK `_ * `queue_delayed_work `_ * `cancel_delayed_work_sync `_ * `INIT_DELAYED_WORK_ONSTACK `_ * `INIT_DEFERRABLE_WORK `_ * `schedule_delayed_work `_ * `cancel_delayed_work `_ * `INIT_RCU_WORK `_ * `queue_rcu_work `_ * `flush_workqueue `_ .. 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 `_ .. _create_dynamic_workqueue_2: .. tab-set:: .. tab-item:: Explanation of workqueue APIs .. _create_dynamic_workqueue_3: .. tab-set:: .. tab-item:: create_workqueue * Here is the function prototype of the API: `create_workqueue `_ .. code-block:: c #include #define create_workqueue(name) * Here is an example of how to use the API, .. code-block:: c my_workqueue = create_workqueue(WQ_NAME); .. _create_dynamic_workqueue_4: .. tab-set:: .. tab-item:: INIT_WORK * Here is the function prototype of the API: `INIT_WORK `_ .. code-block:: c #include #define INIT_WORK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_WORK(&my_work_1,workqueue_func_1); .. _create_dynamic_workqueue_5: .. tab-set:: .. tab-item:: queue_work * Here is the function prototype of the API: `queue_work `_ .. code-block:: c #include static inline bool queue_work(struct workqueue_struct *wq, struct work_struct *work); * Here is an example of how to use the API, .. code-block:: c queue_work(my_workqueue,&my_work_1); .. _create_dynamic_workqueue_6: .. tab-set:: .. tab-item:: destroy_workqueue * Here is the function prototype of the API: `queue_work `_ .. code-block:: c #include extern void destroy_workqueue(struct workqueue_struct *wq); * Here is an example of how to use the API, .. code-block:: c destroy_workqueue(my_workqueue); .. _create_dynamic_workqueue_7: .. tab-set:: .. tab-item:: INIT_WORK_ONSTACK * Here is the function prototype of the API: `INIT_WORK_ONSTACK `_ .. code-block:: c #include #define INIT_WORK_ONSTACK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1); INIT_WORK_ONSTACK(&my_work_2,workqueue_func_2); .. _create_dynamic_workqueue_8: .. tab-set:: .. tab-item:: INIT_DELAYED_WORK * Here is the function prototype of the API: `INIT_DELAYED_WORK `_ .. code-block:: c #include #define INIT_DELAYED_WORK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_DELAYED_WORK(&my_work_1,workqueue_func_1); INIT_DELAYED_WORK(&my_work_2,workqueue_func_2); .. _create_dynamic_workqueue_9: .. tab-set:: .. tab-item:: queue_delayed_work * Here is the function prototype of the API: `queue_delayed_work `_ .. code-block:: c #include static inline bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay); * Here is an example of how to use the API, .. code-block:: c queue_delayed_work(my_workqueue,&my_work_1,msecs_to_jiffies(100)); queue_delayed_work(my_workqueue,&my_work_2,msecs_to_jiffies(300)); .. _create_dynamic_workqueue_10: .. tab-set:: .. tab-item:: cancel_delayed_work_sync * Here is the function prototype of the API: `cancel_delayed_work_sync `_ .. code-block:: c #include extern bool cancel_delayed_work_sync(struct delayed_work *dwork); * Here is an example of how to use the API, .. code-block:: c cancel_delayed_work_sync(&my_work_1); cancel_delayed_work_sync(&my_work_2); .. _create_dynamic_workqueue_11: .. tab-set:: .. tab-item:: INIT_DELAYED_WORK_ONSTACK * Here is the function prototype of the API: `INIT_DELAYED_WORK_ONSTACK `_ .. code-block:: c #include #define INIT_DELAYED_WORK_ONSTACK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_DELAYED_WORK_ONSTACK(&my_work,workqueue_func); .. _create_dynamic_workqueue_12: .. tab-set:: .. tab-item:: INIT_DEFERRABLE_WORK * Here is the function prototype of the API: `INIT_DEFERRABLE_WORK `_ .. code-block:: c #include #define INIT_DEFERRABLE_WORK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_DEFERRABLE_WORK(&my_work,workqueue_func); .. _create_dynamic_workqueue_13: .. tab-set:: .. tab-item:: schedule_delayed_work * Here is the function prototype of the API: `schedule_delayed_work `_ .. code-block:: c #include static inline bool schedule_delayed_work(struct delayed_work *dwork, unsigned long delay); * Here is an example of how to use the API, .. code-block:: c schedule_delayed_work(&my_work,msecs_to_jiffies(100)); .. _create_dynamic_workqueue_14: .. tab-set:: .. tab-item:: cancel_delayed_work * Here is the function prototype of the API: `cancel_delayed_work `_ .. code-block:: c #include extern bool cancel_delayed_work(struct delayed_work *dwork); * Here is an example of how to use the API, .. code-block:: c cancel_delayed_work(&my_work); .. _create_dynamic_workqueue_15: .. tab-set:: .. tab-item:: INIT_RCU_WORK * Here is the function prototype of the API: `INIT_RCU_WORK `_ .. code-block:: c #include #define INIT_RCU_WORK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_RCU_WORK(&my_work,workqueue_func); .. _create_dynamic_workqueue_16: .. tab-set:: .. tab-item:: queue_rcu_work * Here is the function prototype of the API: `queue_rcu_work `_ .. code-block:: c #include extern bool queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork); * Here is an example of how to use the API, .. code-block:: c queue_rcu_work(my_workqueue,&my_work); .. _create_dynamic_workqueue_17: .. tab-set:: .. tab-item:: flush_workqueue * Here is the function prototype of the API: `flush_workqueue `_ .. code-block:: c #include #define flush_workqueue(wq) * Here is an example of how to use the API, .. code-block:: c flush_workqueue(my_workqueue); .. _create_dynamic_workqueue_18: .. tab-set:: .. tab-item:: Example 1 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_dynamic_workqueue_19: .. 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 .. _create_dynamic_workqueue_20: .. 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("Linux_usr"); MODULE_DESCRIPTION("Example of INIT_WORK"); .. _create_dynamic_workqueue_21: .. tab-set:: .. tab-item:: Initializing work * Initialize the work which we are going to use in this example .. code-block:: c INIT_WORK(&my_work_1,workqueue_func_1); INIT_WORK(&my_work_2,workqueue_func_2); .. _create_dynamic_workqueue_22: .. tab-set:: .. tab-item:: Workqueue Handler Function * This workqueue_func_1 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(1000); } } * This workqueue_func_2 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_2(struct work_struct *work) { pr_info("Inside workqueue_func_2\n"); } .. _create_dynamic_workqueue_23: .. tab-set:: .. tab-item:: Queue Start Function * This function creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { my_work_queue = create_workqueue(WQ_NAME); INIT_WORK(&my_work_1,workqueue_func_1); INIT_WORK(&my_work_2,workqueue_func_2); queue_work(my_work_queue,&my_work_2); queue_work(my_work_queue,&my_work_1); } .. _create_dynamic_workqueue_24: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _create_dynamic_workqueue_25: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { destroy_workqueue(my_workqueue); } .. _create_dynamic_workqueue_26: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _create_dynamic_workqueue_27: .. 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(queue_init); module_exit(queue_exit); .. _create_dynamic_workqueue_28: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc1.c .. literalinclude:: create_dynamic_work/INIT_WORK/tc1.c :language: c :linenos: .. _create_dynamic_workqueue_29: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_dynamic_work/INIT_WORK/Makefile :language: c :linenos: .. _create_dynamic_workqueue_30: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 384 -rw-rw-r-- 1 test test 151 Aug 2 11:47 Makefile -rw-rw-r-- 1 test test 76 Aug 2 12:48 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:48 Module.symvers -rw-rw-r-- 1 test test 2040 Aug 2 11:47 tc1.c -rw-rw-r-- 1 test test 180944 Aug 2 12:48 tc1.ko -rw-rw-r-- 1 test test 76 Aug 2 12:48 tc1.mod -rw-rw-r-- 1 test test 1103 Aug 2 12:48 tc1.mod.c -rw-rw-r-- 1 test test 149280 Aug 2 12:48 tc1.mod.o -rw-rw-r-- 1 test test 33112 Aug 2 12:48 tc1.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc1.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 1812.726131] Inside queue_init function [ 1812.726612] Inside workqueue_func_2 [ 1812.726979] Inside workqueue_func_1 [ 1813.754717] Inside workqueue_func_1 [ 1814.778711] Inside workqueue_func_1 [ 1815.802723] Inside workqueue_func_1 [ 1816.826704] Inside workqueue_func_1 [ 1817.850705] Inside workqueue_func_1 [ 1818.874707] Inside workqueue_func_1 [ 1819.898722] Inside workqueue_func_1 [ 1820.922729] Inside workqueue_func_1 [ 1821.946714] Inside workqueue_func_1 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc1 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 1835.094347] Inside queue_exit function .. _create_dynamic_workqueue_31: .. tab-set:: .. tab-item:: Example 2 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_dynamic_workqueue_32: .. 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 .. _create_dynamic_workqueue_33: .. 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("Linux_usr"); MODULE_DESCRIPTION("Example of INIT_WORK_ONSTACK"); .. _create_dynamic_workqueue_34: .. tab-set:: .. tab-item:: Initializing work * Initialize the work which we are going to use in this example .. code-block:: c INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1); INIT_WORK_ONSTACK(&my_work_2,workqueue_func_2); .. _create_dynamic_workqueue_35: .. tab-set:: .. tab-item:: Workqueue Handler Function * This workqueue_func_1 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(1000); } } * This workqueue_func_2 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_2(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_2\n"); i++; msleep(1000); } } .. _create_dynamic_workqueue_36: .. tab-set:: .. tab-item:: Queue Start Function * This function creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { my_workqueue_1 = create_workqueue(WQ_NAME_1); my_workqueue_2 = create_workqueue(WQ_NAME_2); INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1); INIT_WORK_ONSTACK(&my_work_2,workqueue_func_2); queue_work(my_work_queue,&my_work_2); queue_work(my_work_queue,&my_work_1); } .. _create_dynamic_workqueue_37: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _create_dynamic_workqueue_38: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { destroy_workqueue(my_workqueue); destroy_workqueue(my_workqueue_2); } .. _create_dynamic_workqueue_39: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _create_dynamic_workqueue_40: .. 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(queue_init); module_exit(queue_exit); .. _create_dynamic_workqueue_41: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc2.c .. literalinclude:: create_dynamic_work/INIT_WORK_ONSTACK/tc2.c :language: c :linenos: .. _create_dynamic_workqueue_42: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_dynamic_work/INIT_WORK_ONSTACK/Makefile :language: c :linenos: .. _create_dynamic_workqueue_43: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 384 -rw-rw-r-- 1 test test 151 Aug 2 11:47 Makefile -rw-rw-r-- 1 test test 84 Aug 2 12:51 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:51 Module.symvers -rw-rw-r-- 1 test test 2356 Aug 2 11:47 tc2.c -rw-rw-r-- 1 test test 181992 Aug 2 12:51 tc2.ko -rw-rw-r-- 1 test test 84 Aug 2 12:51 tc2.mod -rw-rw-r-- 1 test test 1103 Aug 2 12:51 tc2.mod.c -rw-rw-r-- 1 test test 149296 Aug 2 12:51 tc2.mod.o -rw-rw-r-- 1 test test 34160 Aug 2 12:51 tc2.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc2.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 1927.976881] Inside queue_init function [ 1927.977802] Inside workqueue_func_1 [ 1927.977886] Inside workqueue_func_2 [ 1928.986617] Inside workqueue_func_2 [ 1928.986634] Inside workqueue_func_1 [ 1930.010693] Inside workqueue_func_2 [ 1930.010731] Inside workqueue_func_1 [ 1931.034722] Inside workqueue_func_2 [ 1931.034739] Inside workqueue_func_1 [ 1932.058735] Inside workqueue_func_2 [ 1932.058751] Inside workqueue_func_1 [ 1933.082732] Inside workqueue_func_2 [ 1933.082760] Inside workqueue_func_1 [ 1934.106692] Inside workqueue_func_1 [ 1934.106709] Inside workqueue_func_2 [ 1935.130737] Inside workqueue_func_2 [ 1935.130753] Inside workqueue_func_1 [ 1936.154741] Inside workqueue_func_1 [ 1936.154758] Inside workqueue_func_2 [ 1937.178738] Inside workqueue_func_2 [ 1937.178755] Inside workqueue_func_1 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc2 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 1955.215382] Inside queue_exit function .. _create_dynamic_workqueue_44: .. tab-set:: .. tab-item:: Example 3 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_dynamic_workqueue_45: .. 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 .. _create_dynamic_workqueue_46: .. 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("Linux_usr"); MODULE_DESCRIPTION("Example of INIT_DELAYED_WORK"); .. _create_dynamic_workqueue_47: .. tab-set:: .. tab-item:: Initializing work * Initialize the work which we are going to use in this example .. code-block:: c INIT_DELAYED_WORK(&my_work_1,workqueue_func_1); INIT_DELAYED_WORK(&my_work_2,workqueue_func_2); .. _create_dynamic_workqueue_48: .. tab-set:: .. tab-item:: Workqueue Handler Function * This workqueue_func_1 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(1000); } } * This workqueue_func_2 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_2(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_2\n"); i++; msleep(1000); } } .. _create_dynamic_workqueue_49: .. tab-set:: .. tab-item:: Queue Start Function * This function creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { my_workqueue = create_workqueue(WQ_NAME); INIT_DELAYED_WORK(&my_work_1,workqueue_func_1); INIT_DELAYED_WORK(&my_work_2,workqueue_func_2); queue_delayed_work(my_workqueue,&my_work_1,msecs_to_jiffies(100)); queue_delayed_work(my_workqueue,&my_work_2,msecs_to_jiffies(300)); } .. _create_dynamic_workqueue_50: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _create_dynamic_workqueue_51: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { cancel_delayed_work_sync(&my_work_1); cancel_delayed_work_sync(&my_work_2); pr_info("Destroying workqueue\n"); destroy_workqueue(my_workqueue); } .. _create_dynamic_workqueue_52: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _create_dynamic_workqueue_53: .. 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(queue_init); module_exit(queue_exit); .. _create_dynamic_workqueue_54: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc3.c .. literalinclude:: create_dynamic_work/INIT_DELAYED_WORK/tc3.c :language: c :linenos: .. _create_dynamic_workqueue_55: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_dynamic_work/INIT_DELAYED_WORK/Makefile :language: c :linenos: .. _create_dynamic_workqueue_56: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 388 -rw-rw-r-- 1 test test 151 Aug 2 11:47 Makefile -rw-rw-r-- 1 test test 84 Aug 2 12:42 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:42 Module.symvers -rw-rw-r-- 1 test test 2390 Aug 2 11:47 tc3.c -rw-rw-r-- 1 test test 184616 Aug 2 12:42 tc3.ko -rw-rw-r-- 1 test test 84 Aug 2 12:42 tc3.mod -rw-rw-r-- 1 test test 1233 Aug 2 12:42 tc3.mod.c -rw-rw-r-- 1 test test 149488 Aug 2 12:42 tc3.mod.o -rw-rw-r-- 1 test test 36616 Aug 2 12:42 tc3.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc3.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 1400.538722] Inside workqueue_func_1 [ 1401.562742] Inside workqueue_func_1 [ 1402.586747] Inside workqueue_func_1 [ 1403.610761] Inside workqueue_func_1 [ 1404.634741] Inside workqueue_func_1 [ 1405.658741] Inside workqueue_func_1 [ 1406.682728] Inside workqueue_func_2 [ 1407.706664] Inside workqueue_func_2 [ 1408.730598] Inside workqueue_func_2 [ 1409.754723] Inside workqueue_func_2 [ 1410.778722] Inside workqueue_func_2 [ 1411.802725] Inside workqueue_func_2 [ 1412.826721] Inside workqueue_func_2 [ 1413.850751] Inside workqueue_func_2 [ 1414.874732] Inside workqueue_func_2 [ 1415.898674] Inside workqueue_func_2 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc3 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 1428.223989] Inside queue_exit function [ 1428.223998] Destroying workqueue .. _create_dynamic_workqueue_57: .. tab-set:: .. tab-item:: Example 4 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_dynamic_workqueue_58: .. 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 .. _create_dynamic_workqueue_59: .. 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("Linux_usr"); MODULE_DESCRIPTION("Example of INIT_DELAYED_WORK"); .. _create_dynamic_workqueue_60: .. tab-set:: .. tab-item:: Initializing work * Initialize the work which we are going to use in this example .. code-block:: c INIT_DELAYED_WORK(&my_work_1,workqueue_func_1); INIT_DELAYED_WORK(&my_work_2,workqueue_func_2); .. _create_dynamic_workqueue_61: .. tab-set:: .. tab-item:: Workqueue Handler Function * This workqueue_func_1 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(1000); } } * This workqueue_func_2 function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_2(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_2\n"); i++; msleep(1000); } } .. _create_dynamic_workqueue_62: .. tab-set:: .. tab-item:: Queue Start Function * This function creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { my_workqueue = create_workqueue(WQ_NAME); INIT_DELAYED_WORK_ONSTACK(&my_work,workqueue_func); queue_delayed_work(my_workqueue,&my_work,msecs_to_jiffies(100)); } .. _create_dynamic_workqueue_63: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _create_dynamic_workqueue_64: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); destroy_workqueue(my_workqueue); } .. _create_dynamic_workqueue_65: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _create_dynamic_workqueue_66: .. 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(queue_init); module_exit(queue_exit); .. _create_dynamic_workqueue_67: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc4.c .. literalinclude:: create_dynamic_work/INIT_DELAYED_WORK_ONSTACK/tc4.c :language: c :linenos: .. _create_dynamic_workqueue_68: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_dynamic_work/INIT_DELAYED_WORK_ONSTACK/Makefile :language: c :linenos: .. _create_dynamic_workqueue_69: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 384 -rw-rw-r-- 1 test test 151 Aug 2 11:47 Makefile -rw-rw-r-- 1 test test 92 Aug 2 12:44 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:44 Module.symvers -rw-rw-r-- 1 test test 1770 Aug 2 11:47 tc4.c -rw-rw-r-- 1 test test 181696 Aug 2 12:44 tc4.ko -rw-rw-r-- 1 test test 92 Aug 2 12:44 tc4.mod -rw-rw-r-- 1 test test 1188 Aug 2 12:44 tc4.mod.c -rw-rw-r-- 1 test test 149440 Aug 2 12:44 tc4.mod.o -rw-rw-r-- 1 test test 33672 Aug 2 12:44 tc4.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc4.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 1558.768976] Inside queue_init function [ 1558.870683] Inside workqueue_func [ 1559.902483] Inside workqueue_func [ 1560.922696] Inside workqueue_func [ 1561.946674] Inside workqueue_func [ 1562.970693] Inside workqueue_func [ 1563.994707] Inside workqueue_func [ 1565.018698] Inside workqueue_func [ 1566.042704] Inside workqueue_func [ 1567.066717] Inside workqueue_func [ 1568.090639] Inside workqueue_func * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc4 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 1578.489697] Inside queue_exit function [ 1578.489703] Destroying workqueue .. _create_dynamic_workqueue_70: .. tab-set:: .. tab-item:: Example 5 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_dynamic_workqueue_71: .. 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 .. _create_dynamic_workqueue_72: .. 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("Linux_usr"); MODULE_DESCRIPTION("Example of INIT_DEFERRABLE_WORK"); .. _create_dynamic_workqueue_73: .. tab-set:: .. tab-item:: Initializing work * Initialize the work which we are going to use in this example .. code-block:: c INIT_DEFERRABLE_WORK(&my_work,workqueue_func); .. _create_dynamic_workqueue_74: .. tab-set:: .. tab-item:: Workqueue Handler Function * This function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(1000); } } .. _create_dynamic_workqueue_75: .. tab-set:: .. tab-item:: Queue Start Function * This function creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { INIT_DEFERRABLE_WORK(&my_work,workqueue_func); schedule_delayed_work(&my_work,msecs_to_jiffies(100)); } .. _create_dynamic_workqueue_76: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _create_dynamic_workqueue_77: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); cancel_delayed_work(&my_work); } .. _create_dynamic_workqueue_78: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _create_dynamic_workqueue_79: .. 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(queue_init); module_exit(queue_exit); .. _create_dynamic_workqueue_80: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc5.c .. literalinclude:: create_dynamic_work/INIT_DEFERRABLE_WORK/tc5.c :language: c :linenos: .. _create_dynamic_workqueue_81: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_dynamic_work/INIT_DEFERRABLE_WORK/Makefile :language: c :linenos: .. _create_dynamic_workqueue_82: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 376 -rw-rw-r-- 1 test test 151 Aug 2 11:47 Makefile -rw-rw-r-- 1 test test 87 Aug 2 12:39 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:39 Module.symvers -rw-rw-r-- 1 test test 1607 Aug 2 11:47 tc5.c -rw-rw-r-- 1 test test 180088 Aug 2 12:39 tc5.ko -rw-rw-r-- 1 test test 87 Aug 2 12:39 tc5.mod -rw-rw-r-- 1 test test 1184 Aug 2 12:39 tc5.mod.c -rw-rw-r-- 1 test test 149424 Aug 2 12:39 tc5.mod.o -rw-rw-r-- 1 test test 32096 Aug 2 12:39 tc5.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc5.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 1244.134006] Inside queue_init function [ 1248.986733] Inside workqueue_func [ 1250.010739] Inside workqueue_func [ 1251.034686] Inside workqueue_func [ 1252.058733] Inside workqueue_func [ 1253.082743] Inside workqueue_func [ 1254.106735] Inside workqueue_func [ 1255.130726] Inside workqueue_func [ 1256.154716] Inside workqueue_func [ 1257.178737] Inside workqueue_func [ 1258.202672] Inside workqueue_func * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc5 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 1280.080401] Inside queue_exit function [ 1280.080405] Destroying workqueue .. _create_dynamic_workqueue_83: .. tab-set:: .. tab-item:: Example 6 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_dynamic_workqueue_84: .. 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 .. _create_dynamic_workqueue_85: .. 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("Linux_usr"); MODULE_DESCRIPTION("Example of INIT_DEFERRABLE_WORK"); .. _create_dynamic_workqueue_86: .. tab-set:: .. tab-item:: Initializing work * Initialize the work which we are going to use in this example .. code-block:: c INIT_DEFERRABLE_WORK(&my_work,workqueue_func); .. _create_dynamic_workqueue_87: .. tab-set:: .. tab-item:: Workqueue Handler Function * This function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(1000); } } .. _create_dynamic_workqueue_88: .. tab-set:: .. tab-item:: Queue Start Function * This function creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { INIT_DEFERRABLE_WORK(&my_work,workqueue_func); schedule_delayed_work(&my_work,msecs_to_jiffies(100)); } .. _create_dynamic_workqueue_89: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _create_dynamic_workqueue_90: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); cancel_delayed_work(&my_work); } .. _create_dynamic_workqueue_91: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _create_dynamic_workqueue_92: .. 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(queue_init); module_exit(queue_exit); .. _create_dynamic_workqueue_93: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc6.c .. literalinclude:: create_dynamic_work/INIT_RCU_WORK/tc6.c :language: c :linenos: .. _create_dynamic_workqueue_94: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_dynamic_work/INIT_RCU_WORK/Makefile :language: c :linenos: .. _create_dynamic_workqueue_95: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 380 -rw-rw-r-- 1 test test 151 Aug 2 11:47 Makefile -rw-rw-r-- 1 test test 80 Aug 2 12:46 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:46 Module.symvers -rw-rw-r-- 1 test test 1715 Aug 2 11:47 tc6.c -rw-rw-r-- 1 test test 180448 Aug 2 12:46 tc6.ko -rw-rw-r-- 1 test test 80 Aug 2 12:46 tc6.mod -rw-rw-r-- 1 test test 1104 Aug 2 12:46 tc6.mod.c -rw-rw-r-- 1 test test 149288 Aug 2 12:46 tc6.mod.o -rw-rw-r-- 1 test test 32624 Aug 2 12:46 tc6.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc6.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 1708.830257] Inside queue_init function [ 1708.870492] Inside workqueue_func [ 1709.882740] Inside workqueue_func [ 1710.906743] Inside workqueue_func [ 1711.930741] Inside workqueue_func [ 1712.954710] Inside workqueue_func [ 1713.978702] Inside workqueue_func [ 1715.002762] Inside workqueue_func [ 1716.026772] Inside workqueue_func [ 1717.050761] Inside workqueue_func [ 1718.074730] Inside workqueue_func * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc6 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 1730.664537] Inside queue_exit function [ 1730.664543] Destroying workqueue