Create Workqueue

#

Version

Ubuntu

Ubuntu 22.10

Kernel

6.8.0

  • In this program, you are going to learn

  • How to create workqueue ?

  • How to allocate the work to the queue ?

#include <linux/workqueue.h>

#define create_workqueue(name)
  • Here is an example of how to use the API,

my_workqueue = create_workqueue(WQ_NAME);
  • Here is the function prototype of the API: INIT_WORK

#include <linux/workqueue.h>

#define INIT_WORK(_work, _func)
  • Here is an example of how to use the API,

INIT_WORK(&my_work_1,workqueue_func_1);
  • Here is the function prototype of the API: queue_work

#include <linux/workqueue.h>

static inline bool queue_work(struct workqueue_struct *wq, struct work_struct *work);
  • Here is an example of how to use the API,

queue_work(my_workqueue,&my_work_1);
  • Here is the function prototype of the API: queue_work

#include <linux/workqueue.h>

extern void destroy_workqueue(struct workqueue_struct *wq);
  • Here is an example of how to use the API,

destroy_workqueue(my_workqueue);
#include <linux/workqueue.h>

#define create_singlethread_workqueue(name)
  • Here is an example of how to use the API,

my_workqueue = create_singlethread_workqueue(WQ_NAME);
#include <linux/workqueue.h>

#define create_freezable_workqueue(name)
  • Here is an example of how to use the API,

my_workqueue = create_freezable_workqueue(WQ_NAME);
  • In this example let’s see how to create workqueue and execute it.

  • Include the follow header files(.h) to refer the API being used for the execution.

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
  • Add the following module macros to display information about the license, author and description about the module.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux_usr");
MODULE_DESCRIPTION("Example of create_workqueue");
  • Initialize the work which we are going to use in this example

INIT_WORK(&my_work_1,workqueue_func_1);
  • This function executes when work is queued to workqueue.

void workqueue_func_1(struct work_struct *work)
{
        int i = 0;
        while (i < 10) {
                pr_info("Inside workqueue_func_1\n");
                i++;
                msleep(500);
        }
}
  • This function creates workqueue, intiializes work and queues to the workqueue.

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);
}
  • This function executes when module is loaded.

static int __init queue_init(void)
{
        pr_info("Inside queue_init function\n");
        queue_start();
        return 0;
}
  • This function executes during execution of queue_exit, waits until the completion and destroys workqueue.

void queue_stop(void)
{
        pr_info("Destroying workqueue\n");
        destroy_workqueue(my_workqueue);
}
  • This function executes when module is unloaded.

static void __exit queue_exit(void)
{
        pr_info("Inside queue_exit function\n");
        queue_stop();
        return;
}
  • Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

module_init(queue_init);
module_exit(queue_exit);
 1#include <linux/init.h>
 2#include <linux/kernel.h>
 3#include <linux/module.h>
 4#include <linux/workqueue.h>
 5#include <linux/delay.h>
 6#include <linux/jiffies.h>
 7
 8#define WQ_NAME "tc_workqueue"
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of create_workqueue");
13
14static struct workqueue_struct *my_workqueue;
15struct work_struct my_work_1;
16void workqueue_func_1(struct work_struct *work);
17void queue_start(void);
18void queue_stop(void);
19
20/* workqueue_func_1 - executes when work is queued to workqueue,
21 * prints a statement and sleeps for 1000ms,
22 * stops when i value is greater than 10 */
23
24void workqueue_func_1(struct work_struct *work)
25{
26    int i = 0;
27    while (i < 10) {
28        pr_info("Inside workqueue_func_1\n");
29        i++;
30        msleep(500);
31    }
32}
33
34/* queue_start - executes during execution of queue_start,
35 * creates workqueue,
36 * intiializes work and queues to the workqueue */
37
38void queue_start(void)
39{
40    my_workqueue = create_workqueue(WQ_NAME);
41    INIT_WORK(&my_work_1,workqueue_func_1);
42    queue_work(my_workqueue,&my_work_1);
43}
44
45/* queue_init - executes when module is loaded,
46 * calls queue_start */
47
48static int __init queue_init(void)
49{
50    pr_info("Inside queue_init function\n");
51    queue_start();
52    return 0;
53}
54
55/* queue_stop - executes during execution of queue_exit,
56 * waits until the completion and destroys workqueue */
57
58void queue_stop(void)
59{
60    pr_info("Destroying workqueue\n");
61    destroy_workqueue(my_workqueue);
62}
63
64/* queue_exit - executes when module is unloaded,
65 * calls queue_stop */
66
67static void __exit queue_exit(void)
68{
69    pr_info("Inside queue_exit function\n");
70    queue_stop();
71    return;
72}
73
74module_init(queue_init);
75module_exit(queue_exit);
1obj-m += tc1.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 load the kernel module.

$ make
  • Check if work_queue.ko is generated or not using ls command.

$ 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.

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

$ 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.

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

$ dmesg
[  251.832722] Inside queue_exit function
[  251.832729] Destroying workqueue
  • In this example let’s see how to create single thread workqueue and execute it.

  • Include the follow header files(.h) to refer the API being used for the execution.

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
  • Add the following module macros to display information about the license, author and description about the module.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux_usr");
MODULE_DESCRIPTION("Example of create_singlethread_workqueue");
  • Initialize the work which we are going to use in this example

INIT_WORK(&my_work_1,workqueue_func_1);
  • This function executes when work is queued to workqueue.

void workqueue_func_1(struct work_struct *work)
{
        int i = 0;
        while (i < 10) {
                pr_info("Inside workqueue_func_1\n");
                i++;
                msleep(500);
        }
}
  • This function creates workqueue, intiializes work and queues to the workqueue.

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);
}
  • This function executes when module is loaded.

static int __init queue_init(void)
{
        pr_info("Inside queue_init function\n");
        queue_start();
        return 0;
}
  • This function executes during execution of queue_exit, waits until the completion and destroys workqueue.

void queue_stop(void)
{
        pr_info("Destroying workqueue\n");
        destroy_workqueue(my_workqueue);
}
  • This function executes when module is unloaded.

static void __exit queue_exit(void)
{
        pr_info("Inside queue_exit function\n");
        queue_stop();
        return;
}
  • Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

module_init(queue_init);
module_exit(queue_exit);
 1#include <linux/init.h>
 2#include <linux/kernel.h>
 3#include <linux/module.h>
 4#include <linux/workqueue.h>
 5#include <linux/delay.h>
 6#include <linux/jiffies.h>
 7
 8#define WQ_NAME "tc_workqueue"
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of create_singlethread_workqueue");
13
14static struct workqueue_struct *my_workqueue;
15struct work_struct my_work_1;
16void workqueue_func_1(struct work_struct *work);
17void queue_start(void);
18void queue_stop(void);
19
20/* workqueue_func_1 - executes when work is queued to workqueue,
21 * prints a statement and sleeps for 1000ms,
22 * stops when i value is greater than 10 */
23
24void workqueue_func_1(struct work_struct *work)
25{
26    int i = 0;
27    while (i < 10) {
28        pr_info("Inside workqueue_func_1\n");
29        i++;
30        msleep(500);
31    }
32}
33
34/* queue_start - executes during execution of queue_start,
35 * creates workqueue,
36 * intiializes work and queues to the workqueue */
37
38void queue_start(void)
39{
40    my_workqueue = create_singlethread_workqueue(WQ_NAME);
41    INIT_WORK(&my_work_1,workqueue_func_1);
42    queue_work(my_workqueue,&my_work_1);
43}
44
45/* queue_init - executes when module is loaded,
46 * calls queue_start */
47
48static int __init queue_init(void)
49{
50    pr_info("Inside queue_init function\n");
51    queue_start();
52    return 0;
53}
54
55/* queue_stop - executes during execution of queue_exit,
56 * waits until the completion and destroys workqueue */
57
58void queue_stop(void)
59{
60    pr_info("Destroying workqueue\n");
61    destroy_workqueue(my_workqueue);
62}
63
64/* queue_exit - executes when module is unloaded,
65 * calls queue_stop */
66
67static void __exit queue_exit(void)
68{
69    pr_info("Inside queue_exit function\n");
70    queue_stop();
71    return;
72}
73
74module_init(queue_init);
75module_exit(queue_exit);
1obj-m += tc2.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 load the kernel module.

$ make
  • Check if work_queue.ko is generated or not using ls command.

$ 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.

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

$ 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.

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

$ dmesg
[  653.077727] Inside queue_exit function
[  653.077730] Destroying workqueue
  • In this example let’s see how to create freezable workqueue and execute it.

  • Include the follow header files(.h) to refer the API being used for the execution.

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
  • Add the following module macros to display information about the license, author and description about the module.

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux_usr");
MODULE_DESCRIPTION("Example of create_freezable_workqueue");
  • Initialize the work which we are going to use in this example

INIT_WORK(&my_work_1,workqueue_func_1);
  • This function executes when work is queued to workqueue.

void workqueue_func_1(struct work_struct *work)
{
        int i = 0;
        while (i < 10) {
                pr_info("Inside workqueue_func_1\n");
                i++;
                msleep(500);
        }
}
  • This function creates workqueue, intiializes work and queues to the workqueue.

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);
}
  • This function executes when module is loaded.

static int __init queue_init(void)
{
        pr_info("Inside queue_init function\n");
        queue_start();
        return 0;
}
  • This function executes during execution of queue_exit, waits until the completion and destroys workqueue.

void queue_stop(void)
{
        pr_info("Destroying workqueue\n");
        destroy_workqueue(my_workqueue);
}
  • This function executes when module is unloaded.

static void __exit queue_exit(void)
{
        pr_info("Inside queue_exit function\n");
        queue_stop();
        return;
}
  • Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

module_init(queue_init);
module_exit(queue_exit);
 1#include <linux/init.h>
 2#include <linux/kernel.h>
 3#include <linux/module.h>
 4#include <linux/workqueue.h>
 5#include <linux/delay.h>
 6#include <linux/jiffies.h>
 7
 8#define WQ_NAME "tc_workqueue"
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of create_freezable_workqueue");
13
14static struct workqueue_struct *my_workqueue;
15struct work_struct my_work_1;
16void workqueue_func_1(struct work_struct *work);
17void queue_start(void);
18void queue_stop(void);
19
20/* workqueue_func_1 - executes when work is queued to workqueue,
21 * prints a statement and sleeps for 1000ms,
22 * stops when i value is greater than 10 */
23
24void workqueue_func_1(struct work_struct *work)
25{
26    int i = 0;
27    while (i < 10) {
28        pr_info("Inside workqueue_func_1\n");
29        i++;
30        msleep(500);
31    }
32}
33
34/* queue_start - executes during execution of queue_start,
35 * creates workqueue,
36 * intiializes work and queues to the workqueue */
37
38void queue_start(void)
39{
40    my_workqueue = create_freezable_workqueue(WQ_NAME);
41    INIT_WORK(&my_work_1,workqueue_func_1);
42    queue_work(my_workqueue,&my_work_1);
43}
44
45/* queue_init - executes when module is loaded,
46 * calls queue_start */
47
48static int __init queue_init(void)
49{
50    pr_info("Inside queue_init function\n");
51    queue_start();
52    return 0;
53}
54
55/* queue_stop - executes during execution of queue_exit,
56 * waits until the completion and destroys workqueue */
57
58void queue_stop(void)
59{
60    pr_info("Destroying workqueue\n");
61    destroy_workqueue(my_workqueue);
62}
63
64/* queue_exit - executes when module is unloaded,
65 * calls queue_stop */
66
67static void __exit queue_exit(void)
68{
69    pr_info("Inside queue_exit function\n");
70    queue_stop();
71    return;
72}
73
74module_init(queue_init);
75module_exit(queue_exit);
1obj-m += tc3.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 load the kernel module.

$ make
  • Check if work_queue.ko is generated or not using ls command.

$ 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.

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

$ 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.

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

$ dmesg
[  885.279641] Inside queue_exit function
[  885.279650] Destroying workqueue