Create Workqueue ================ .. 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:`create_singlethread_workqueue ` * :ref:`create_freezable_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 single thread 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 freezable 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_workqueue_0: .. tab-set:: .. tab-item:: Version Info =============================== ======================================= # Version =============================== ======================================= Ubuntu Ubuntu 22.10 Kernel 6.8.0 =============================== ======================================= .. _create_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 `_ * `create_singlethread_workqueue `_ * `create_freezable_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_workqueue_2: .. tab-set:: .. tab-item:: Explanation of workqueue APIs .. _create_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_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_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_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_workqueue_46: .. tab-set:: .. tab-item:: create_singlethread_workqueue * Here is the function prototype of the API: `create_singlethread_workqueue `_ .. code-block:: c #include #define create_singlethread_workqueue(name) * Here is an example of how to use the API, .. code-block:: c my_workqueue = create_singlethread_workqueue(WQ_NAME); .. _create_workqueue_47: .. tab-set:: .. tab-item:: create_freezable_workqueue * Here is the function prototype of the API: `create_freezable_workqueue `_ .. code-block:: c #include #define create_freezable_workqueue(name) * Here is an example of how to use the API, .. code-block:: c my_workqueue = create_freezable_workqueue(WQ_NAME); .. _create_workqueue_7: .. tab-set:: .. tab-item:: Example 1 : Creating a workqueue * In this example let's see how to create workqueue and execute it. .. _create_workqueue_8: .. 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_workqueue_9: .. 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 create_workqueue"); .. _create_workqueue_10: .. 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); .. _create_workqueue_11: .. 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(500); } } .. _create_workqueue_12: .. 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_WORK(&my_work_1,workqueue_func_1); queue_work(my_workqueue,&my_work_1); } .. _create_workqueue_13: .. 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_workqueue_14: .. 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_workqueue_15: .. 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_workqueue_16: .. 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_workqueue_17: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc1.c .. literalinclude:: create_workqueue/create_workqueue/tc1.c :language: c :linenos: .. _create_workqueue_18: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_workqueue/create_workqueue/Makefile :language: c :linenos: .. _create_workqueue_19: .. 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:42 Makefile -rw-rw-r-- 1 test test 80 Aug 2 12:21 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:21 Module.symvers -rw-rw-r-- 1 test test 1736 Aug 2 11:42 tc1.c -rw-rw-r-- 1 test test 180760 Aug 2 12:21 tc1.ko -rw-rw-r-- 1 test test 80 Aug 2 12:21 tc1.mod -rw-rw-r-- 1 test test 1103 Aug 2 12:21 tc1.mod.c -rw-rw-r-- 1 test test 149288 Aug 2 12:21 tc1.mod.o -rw-rw-r-- 1 test test 32936 Aug 2 12:21 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 [ 237.521464] Inside queue_init function [ 237.522188] Inside workqueue_func_1 [ 238.042620] Inside workqueue_func_1 [ 238.554641] Inside workqueue_func_1 [ 239.066622] Inside workqueue_func_1 [ 239.578636] Inside workqueue_func_1 [ 240.090615] Inside workqueue_func_1 [ 240.602564] Inside workqueue_func_1 [ 241.114599] Inside workqueue_func_1 [ 241.626673] Inside workqueue_func_1 [ 242.138618] 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 [ 251.832722] Inside queue_exit function [ 251.832729] Destroying workqueue .. _create_workqueue_20: .. tab-set:: .. tab-item:: Example 2 : Creating a single thread workqueue * In this example let's see how to create single thread workqueue and execute it. .. _create_workqueue_21: .. 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_workqueue_22: .. 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 create_singlethread_workqueue"); .. _create_workqueue_23: .. 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); .. _create_workqueue_24: .. 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(500); } } .. _create_workqueue_25: .. 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_singlethread_workqueue(WQ_NAME); INIT_WORK(&my_work_1,workqueue_func_1); queue_work(my_workqueue,&my_work_1); } .. _create_workqueue_26: .. 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_workqueue_27: .. 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_workqueue_28: .. 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_workqueue_29: .. 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_workqueue_30: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc2.c .. literalinclude:: create_workqueue/create_singlethread_workqueue/tc2.c :language: c :linenos: .. _create_workqueue_31: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_workqueue/create_singlethread_workqueue/Makefile :language: c :linenos: .. _create_workqueue_32: .. 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 12:28 Makefile -rw-rw-r-- 1 test test 93 Aug 2 12:28 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:28 Module.symvers -rw-rw-r-- 1 test test 1762 Aug 2 11:42 tc2.c -rw-rw-r-- 1 test test 180816 Aug 2 12:28 tc2.ko -rw-rw-r-- 1 test test 93 Aug 2 12:28 tc2.mod -rw-rw-r-- 1 test test 1103 Aug 2 12:28 tc2.mod.c -rw-rw-r-- 1 test test 149312 Aug 2 12:28 tc2.mod.o -rw-rw-r-- 1 test test 32968 Aug 2 12:28 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 [ 636.552146] Inside queue_init function [ 636.552516] Inside workqueue_func_1 [ 637.082615] Inside workqueue_func_1 [ 637.594573] Inside workqueue_func_1 [ 638.106515] Inside workqueue_func_1 [ 638.618599] Inside workqueue_func_1 [ 639.134537] Inside workqueue_func_1 [ 639.642665] Inside workqueue_func_1 [ 640.154697] Inside workqueue_func_1 [ 640.666640] Inside workqueue_func_1 [ 641.178613] 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 [ 653.077727] Inside queue_exit function [ 653.077730] Destroying workqueue .. _create_workqueue_33: .. tab-set:: .. tab-item:: Example 3 : Creating a freezable workqueue * In this example let's see how to create freezable workqueue and execute it. .. _create_workqueue_34: .. 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_workqueue_35: .. 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 create_freezable_workqueue"); .. _create_workqueue_36: .. 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); .. _create_workqueue_37: .. 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(500); } } .. _create_workqueue_38: .. 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_freezable_workqueue(WQ_NAME); INIT_WORK(&my_work_1,workqueue_func_1); queue_work(my_workqueue,&my_work_1); } .. _create_workqueue_39: .. 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_workqueue_40: .. 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_workqueue_41: .. 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_workqueue_42: .. 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_workqueue_43: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc3.c .. literalinclude:: create_workqueue/create_freezable_workqueue/tc3.c :language: c :linenos: .. _create_workqueue_44: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: create_workqueue/create_freezable_workqueue/Makefile :language: c :linenos: .. _create_workqueue_45: .. 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:42 Makefile -rw-rw-r-- 1 test test 90 Aug 2 12:32 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:32 Module.symvers -rw-rw-r-- 1 test test 1756 Aug 2 11:42 tc3.c -rw-rw-r-- 1 test test 180800 Aug 2 12:32 tc3.ko -rw-rw-r-- 1 test test 90 Aug 2 12:32 tc3.mod -rw-rw-r-- 1 test test 1103 Aug 2 12:32 tc3.mod.c -rw-rw-r-- 1 test test 149304 Aug 2 12:32 tc3.mod.o -rw-rw-r-- 1 test test 32960 Aug 2 12:32 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 [ 866.843964] Inside queue_init function [ 866.844248] Inside workqueue_func_1 [ 867.354660] Inside workqueue_func_1 [ 867.866729] Inside workqueue_func_1 [ 868.378724] Inside workqueue_func_1 [ 868.890716] Inside workqueue_func_1 [ 869.402722] Inside workqueue_func_1 [ 869.914731] Inside workqueue_func_1 [ 870.426712] Inside workqueue_func_1 [ 870.938724] Inside workqueue_func_1 [ 871.450719] Inside workqueue_func_1 * 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 [ 885.279641] Inside queue_exit function [ 885.279650] Destroying workqueue