Workqueue : schedule_work ============================ .. tab-set:: .. tab-item:: Workqueue : scheduled_work * 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 schedule the workqueue ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use Workqueue APIs ? * `INIT_WORK `_ * `schedule_work `_ * `cancel_work_sync `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`Key learnings in this program ` * :ref:`Explanation of program part by part ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initialize variables and functions ` * :ref:`Module init function ` * :ref:`Module exit function ` * :ref:`Workqueue APIs ` * :ref:`Mention init and exit functions ` * :ref:`See full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Summary of workqueue APIs ` .. _p2_Workqueue_schedule_work_0: .. tab-set:: .. tab-item:: Key learnings in this program * ``INIT_WORK`` is a macro used for initializing a workqueue structure. For example, .. code-block:: c INIT_WORK(&my_work, workqueue_func); * ``schedule_work`` is a function used to schedule a workqueue for execution. For example, .. code-block:: c schedule_work(&my_work); * ``cancel_work_sync`` is a function used to cancel a scheduled workqueue and wait for it to complete before returning. For example, .. code-block:: c cancel_work_sync(&my_work); .. _p2_Workqueue_schedule_work_4: .. tab-set:: .. tab-item:: Explanation of program part by part * Here is the explanation of the source code. .. _p2_Workqueue_schedule_work_5: .. tab-set:: .. tab-item:: List of headers .. code-block:: #include #include #include #include #include #include * Include the headers file to refer the APIs used in this program. .. _p2_Workqueue_schedule_work_6: .. tab-set:: .. tab-item:: Modules macro .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_usr"); MODULE_DESCRIPTION("Workqueue"); * Add the modules macro which contains the information of module such as license, author and description. .. _p2_Workqueue_schedule_work_7: .. tab-set:: .. tab-item:: Initialize variables and functions .. code-block:: c void workqueue_func(struct work_struct *work); static struct work_struct my_work; * Initialize the variables and APIs which is used in this program. .. _p2_Workqueue_schedule_work_8: .. tab-set:: .. tab-item:: Module init function .. code-block:: c static int __init queue_init(void) { INIT_WORK(&my_work, workqueue_func); schedule_work(&workqueue); pr_info("Driver Loaded\n"); return 0; } * Create the module init function which will be called once the module is loaded into linux kernel. * ``schedule_work`` is used to schedule the workqueue. .. _p2_Workqueue_schedule_work_9: .. tab-set:: .. tab-item:: Module exit function .. code-block:: c static void __exit queue_exit(void) { cancel_work_sync(&my_work); pr_info("Driver Unloaded...\n"); } * Create the module exit function which will be called once the module is unloaded into linux kernel. .. _p2_Workqueue_schedule_work_10: .. tab-set:: .. tab-item:: Workqueue APIs .. code-block:: c void workqueue_func(struct work_struct *work) { pr_info("Inside Workqueue function\n"); } * Workqueue APIs is called once the work is scheduled. * This API will be passed as a parameter during the time of declaring the workqueue. .. _p2_Workqueue_schedule_work_11: .. tab-set:: .. tab-item:: Mention init and exit functions .. code-block:: c module_init(queue_init); module_exit(queue_exit); * Mention the module init and exit functions which needs to be executed when the module is loaded and unloaded. .. _p2_Workqueue_schedule_work_12: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: work_queue.c .. literalinclude:: p2_Workqueue_schedule_work/work_queue.c :language: c :linenos: :emphasize-lines: 17,26,27,36 .. _p2_Workqueue_schedule_work_1: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: p2_Workqueue_schedule_work/Makefile :language: c :linenos: .. _p2_Workqueue_schedule_work_2: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make make -C /lib/modules/5.4.0-150-generic/build M=$HOME/kernel_work_queue modules make[1]: Entering directory '/usr/src/linux-headers-5.4.0-150-generic' CC [M] $HOME/kernel_work_queue/work_queue.o Building modules, stage 2. MODPOST 1 modules CC [M] $HOME/kernel_work_queue/work_queue.mod.o LD [M] $HOME/kernel_work_queue/work_queue.ko make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-150-generic' * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ 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 work_queue.c -rw-rw-r-- 1 test test 5880 Feb 26 13:18 work_queue.ko -rw-rw-r-- 1 test test 47 Feb 26 13:18 work_queue.mod -rw-rw-r-- 1 test test 919 Feb 26 13:18 work_queue.mod.c -rw-rw-r-- 1 test test 3448 Feb 26 13:18 work_queue.mod.o -rw-rw-r-- 1 test test 3320 Feb 26 13:18 work_queue.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./work_queue.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [77441.125186] Driver Loaded [77441.125190] Inside Workqueue function * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod work_queue * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [77441.125186] Driver Loaded [77441.125190] Inside Workqueue function [77453.580892] Driver Unloaded... .. _p2_Workqueue_schedule_work_3: .. tab-set:: .. tab-item:: Summary of workqueue APIs =============================== ================================= API Learning =============================== ================================= INIT_WORK To initialize the workqueue schedule_work To allocate the work to the queue cancel_work_sync Cancel the scheduled work =============================== =================================