Create Workqueue
Topics in this section,
# |
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 ?
How to use Workqueue APIs ?
How to use below APIs ?
Here is the function prototype of the API: create_workqueue
#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);
Here is the function prototype of the API: create_singlethread_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);
Here is the function prototype of the API: create_freezable_workqueue
#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