Destroy Work
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 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: work_pending
#include <linux/workqueue.h>
#define work_pending(work)
Here is an example of how to use the API,
work_pending(&my_work_1);
Here is the function prototype of the API: INIT_DELAYED_WORK
#include <linux/workqueue.h>
#define INIT_DELAYED_WORK(_work, _func)
Here is an example of how to use the API,
INIT_DELAYED_WORK(&my_work_1,workqueue_func_1);
INIT_DELAYED_WORK(&my_work_2,workqueue_func_2);
Here is the function prototype of the API: delayed_work_pending
#include <linux/workqueue.h>
#define delayed_work_pending(w)
Here is an example of how to use the API,
delayed_work_pending(&my_work_1);
Here is the function prototype of the API: cancel_delayed_work_sync
#include <linux/workqueue.h>
extern bool cancel_delayed_work_sync(struct delayed_work *dwork);
Here is an example of how to use the API,
cancel_delayed_work_sync(&my_work_1);
cancel_delayed_work_sync(&my_work_2);
Here is the function prototype of the API: schedule_work
#include <linux/workqueue.h>
static inline bool schedule_work(struct work_struct *work);
Here is an example of how to use the API,
schedule_work(&my_work_1);
schedule_work(&my_work_2);
Here is the function prototype of the API: cancel_work
#include <linux/workqueue.h>
extern bool cancel_work(struct work_struct *work);
Here is an example of how to use the API,
cancel_work(&my_work_1);
cancel_work(&my_work_2);
Here is the function prototype of the API: schedule_delayed_work
#include <linux/workqueue.h>
static inline bool schedule_delayed_work(struct delayed_work *dwork, unsigned long delay);
Here is an example of how to use the API,
schedule_delayed_work(&my_work,msecs_to_jiffies(100));
Here is the function prototype of the API: cancel_delayed_work
#include <linux/workqueue.h>
extern bool cancel_delayed_work(struct delayed_work *dwork);
Here is an example of how to use the API,
cancel_delayed_work(&my_work);
In this example let’s see how to destroy the 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 cancel_workqueue");
Initialize the work which we are going to use in this example
INIT_WORK(&my_work_1,workqueue_func_1);
INIT_WORK(&my_work_2,workqueue_func_2);
This workqueue_func_1 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(1000);
}
}
This workqueue_func_2 function executes when work is queued to workqueue.
void workqueue_func_2(struct work_struct *work)
{
int i = 0;
while (i < 10) {
pr_info("Inside workqueue_func_1\n");
i++;
msleep(1000);
}
}
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);
INIT_WORK(&my_work_2,workqueue_func_2);
if (!work_pending(&my_work_1)) {
queue_work(my_workqueue,&my_work_1);
}
if (!work_pending(&my_work_2)) {
queue_work(my_workqueue,&my_work_2);
}
}
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");
cancel_work(&my_work_1);
cancel_work(&my_work_2);
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/* schedule_work/delayed_work_pending */
2
3#include <linux/init.h>
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/workqueue.h>
7#include <linux/delay.h>
8#include <linux/jiffies.h>
9
10#define WQ_NAME "tc8_workqueue"
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Linux_usr");
14MODULE_DESCRIPTION("Example of work_pending");
15
16struct workqueue_struct *my_workqueue;
17struct work_struct my_work_1;
18struct work_struct my_work_2;
19void workqueue_func_1(struct work_struct *work);
20void workqueue_func_2(struct work_struct *work);
21void queue_start(void);
22void queue_stop(void);
23
24/* workqueue_func_1 - executes when work is queued to workqueue,
25 * prints a statement and sleeps for 1000ms,
26 * stops when i value is greater than 10 */
27
28void workqueue_func_1(struct work_struct *work)
29{
30 int i = 0;
31 while (i < 10) {
32 pr_info("Inside workqueue_func_1\n");
33 i++;
34 msleep(500);
35 }
36}
37
38/* workqueue_func_2 - executes when work is queued to workqueue,
39 * prints a statement and sleeps for 1000ms,
40 * stops when i value is greater than 10 */
41
42void workqueue_func_2(struct work_struct *work)
43{
44 int i = 0;
45 while (i < 10) {
46 pr_info("Inside workqueue_func_2\n");
47 i++;
48 msleep(500);
49 }
50}
51
52/* queue_start - executes during execution of queue_start,
53 * creates workqueue,
54 * intiializes work and queues to the workqueue */
55
56void queue_start(void)
57{
58 my_workqueue = create_workqueue(WQ_NAME);
59 INIT_WORK(&my_work_1,workqueue_func_1);
60 INIT_WORK(&my_work_2,workqueue_func_2);
61 if (!work_pending(&my_work_1)) {
62 queue_work(my_workqueue,&my_work_1);
63 }
64 if (!work_pending(&my_work_2)) {
65 queue_work(my_workqueue,&my_work_2);
66 }
67}
68
69/* queue_init - executes when module is loaded,
70 * calls queue_start */
71
72static int __init queue_init(void)
73{
74 pr_info("Inside queue_init function\n");
75 queue_start();
76 return 0;
77}
78
79/* queue_stop - executes during execution of queue_exit,
80 * waits until the completion and destroys workqueue */
81
82void queue_stop(void)
83{
84 pr_info("Destroying workqueue\n");
85 cancel_work(&my_work_1);
86 cancel_work(&my_work_2);
87 destroy_workqueue(my_workqueue);
88}
89
90/* queue_exit - executes when module is unloaded,
91 * calls queue_stop */
92
93static void __exit queue_exit(void)
94{
95 pr_info("Inside queue_exit function\n");
96 queue_stop();
97 return;
98}
99
100module_init(queue_init);
101module_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: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.
$ sudo insmod ./tc1.ko
Check kernel messages to verify if the module is loaded or not.
$ 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.
$ sudo rmmod tc1
Check kernel messages to see if the module is unloaded or not.
$ dmesg
[ 1835.094347] Inside queue_exit function
In this example let’s see how to destroy the 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 flush_work");
Initialize the work which we are going to use in this example
INIT_WORK(&my_work_1,workqueue_func_1);
INIT_WORK(&my_work_2,workqueue_func_2);
This workqueue_func_1 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(1000);
}
}
This workqueue_func_2 function executes when work is queued to workqueue.
void workqueue_func_2(struct work_struct *work)
{
int i = 0;
while (i < 10) {
pr_info("Inside workqueue_func_1\n");
i++;
msleep(1000);
}
}
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);
INIT_WORK(&my_work_2,workqueue_func_2);
if (!work_pending(&my_work_1)) {
queue_work(my_workqueue,&my_work_1);
}
if (!work_pending(&my_work_2)) {
queue_work(my_workqueue,&my_work_2);
}
}
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");
flush_work(&my_work_1);
flush_work(&my_work_2);
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 "tc8_workqueue"
9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of work_pending");
13
14struct workqueue_struct *my_workqueue;
15struct work_struct my_work_1;
16struct work_struct my_work_2;
17void workqueue_func_1(struct work_struct *work);
18void workqueue_func_2(struct work_struct *work);
19void queue_start(void);
20void queue_stop(void);
21
22/* workqueue_func_1 - executes when work is queued to workqueue,
23 * prints a statement and sleeps for 1000ms,
24 * stops when i value is greater than 10 */
25
26void workqueue_func_1(struct work_struct *work)
27{
28 int i = 0;
29 while (i < 10) {
30 pr_info("Inside workqueue_func_1\n");
31 i++;
32 msleep(500);
33 }
34}
35
36/* workqueue_func_2 - executes when work is queued to workqueue,
37 * prints a statement and sleeps for 1000ms,
38 * stops when i value is greater than 10 */
39
40void workqueue_func_2(struct work_struct *work)
41{
42 int i = 0;
43 while (i < 10) {
44 pr_info("Inside workqueue_func_2\n");
45 i++;
46 msleep(500);
47 }
48}
49
50/* queue_start - executes during execution of queue_start,
51 * creates workqueue,
52 * intiializes work and queues to the workqueue */
53
54void queue_start(void)
55{
56 my_workqueue = create_workqueue(WQ_NAME);
57 INIT_WORK(&my_work_1,workqueue_func_1);
58 INIT_WORK(&my_work_2,workqueue_func_2);
59 if (!work_pending(&my_work_1)) {
60 queue_work(my_workqueue,&my_work_1);
61 }
62 if (!work_pending(&my_work_2)) {
63 queue_work(my_workqueue,&my_work_2);
64 }
65}
66
67/* queue_init - executes when module is loaded,
68 * calls queue_start */
69
70static int __init queue_init(void)
71{
72 pr_info("Inside queue_init function\n");
73 queue_start();
74 return 0;
75}
76
77/* queue_stop - executes during execution of queue_exit,
78 * waits until the completion and destroys workqueue */
79
80void queue_stop(void)
81{
82 pr_info("Destroying workqueue\n");
83 flush_work(&my_work_1);
84 flush_work(&my_work_2);
85 destroy_workqueue(my_workqueue);
86}
87
88/* queue_exit - executes when module is unloaded,
89 * calls queue_stop */
90
91static void __exit queue_exit(void)
92{
93 pr_info("Inside queue_exit function\n");
94 queue_stop();
95 return;
96}
97
98module_init(queue_init);
99module_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 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 tc2.c
-rw-rw-r-- 1 test test 180944 Aug 2 12:48 tc2.ko
-rw-rw-r-- 1 test test 76 Aug 2 12:48 tc2.mod
-rw-rw-r-- 1 test test 1103 Aug 2 12:48 tc2.mod.c
-rw-rw-r-- 1 test test 149280 Aug 2 12:48 tc2.mod.o
-rw-rw-r-- 1 test test 33112 Aug 2 12:48 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
[ 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.
$ sudo rmmod tc2
Check kernel messages to see if the module is unloaded or not.
$ dmesg
[ 1835.094347] Inside queue_exit function
In this example let’s see how to destroy 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 flush_delayed_work");
Initialize the work which we are going to use in this example
INIT_DELAYED_WORK(&my_work_1,workqueue_func_1);
INIT_DELAYED_WORK(&my_work_2,workqueue_func_2);
This workqueue_func_1 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(1000);
}
}
This workqueue_func_2 function executes when work is queued to workqueue.
void workqueue_func_2(struct work_struct *work)
{
int i = 0;
while (i < 10) {
pr_info("Inside workqueue_func_2\n");
i++;
msleep(1000);
}
}
This function creates workqueue, intiializes work and queues to the workqueue.
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));
}
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)
{
flush_delayed_work_sync(&my_work_1);
flush_delayed_work_sync(&my_work_2);
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/* create_dynamic_work/INIT_DELAYED_WORK */
2
3#include <linux/init.h>
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/workqueue.h>
7#include <linux/delay.h>
8#include <linux/jiffies.h>
9
10#define WQ_NAME "tc3_workqueue"
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Linux_usr");
14MODULE_DESCRIPTION("Example of INIT_DELAYED_WORK");
15
16struct workqueue_struct *my_workqueue;
17struct delayed_work my_work_1;
18struct delayed_work my_work_2;
19void workqueue_func_1(struct work_struct *work);
20void workqueue_func_2(struct work_struct *work);
21void queue_start(void);
22void queue_stop(void);
23
24/* workqueue_func_1 - exectues when work_1 is queued to workqueue,
25 * prints a statement and sleeps for 1000ms,
26 * stops when i value goes greater than 10 */
27
28void workqueue_func_1(struct work_struct *work)
29{
30 int i = 0;
31 while (i < 10) {
32 pr_info("Inside workqueue_func_1\n");
33 i++;
34 msleep(1000);
35 }
36}
37
38/* workqueue_func_2 - executes when work_2 is queued to workqueue,
39 * prints a statement and sleeps for 1000ms,
40 * stops when i value goes greater than 10ms */
41
42void workqueue_func_2(struct work_struct *work)
43{
44 int i = 0;
45 while (i < 10) {
46 pr_info("Inside workqueue_func_2\n");
47 i++;
48 msleep(1000);
49 }
50}
51
52/* queue_start - executes during execution of queue_init,
53 * creates workqueue,
54 * initializes work and queues to the workqueue */
55
56void queue_start(void)
57{
58 my_workqueue = create_workqueue(WQ_NAME);
59 INIT_DELAYED_WORK(&my_work_1,workqueue_func_1);
60 INIT_DELAYED_WORK(&my_work_2,workqueue_func_2);
61 queue_delayed_work(my_workqueue,&my_work_1,msecs_to_jiffies(100));
62 queue_delayed_work(my_workqueue,&my_work_2,msecs_to_jiffies(300));
63}
64
65/* queue_init - executes when the module is inserted,
66 * calls queue_start */
67
68static int __init queue_init(void)
69{
70 pr_info("Inside queue_init function\n");
71 queue_start();
72 return 0;
73}
74
75/* queue_stop - executes during the execution of queue_exit,
76 * destroys work and workqueues */
77
78void queue_stop(void)
79{
80 flush_delayed_work(&my_work_1);
81 flush_delayed_work(&my_work_2);
82 pr_info("Destroying workqueue\n");
83 destroy_workqueue(my_workqueue);
84}
85
86/* queue_exit - executes when the module is removed,
87 * calls queue_stop */
88
89static void __exit queue_exit(void)
90{
91 pr_info("Inside queue_exit function\n");
92 queue_stop();
93 return;
94}
95
96module_init(queue_init);
97module_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 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.
$ sudo insmod ./tc3.ko
Check kernel messages to verify if the module is loaded or not.
$ dmesg
[282169.096177] Inside queue_init function
[282169.198261] Inside workqueue_func_1
[282170.218283] Inside workqueue_func_1
[282171.242140] Inside workqueue_func_1
[282172.266278] Inside workqueue_func_1
[282173.290254] Inside workqueue_func_1
[282174.314224] Inside workqueue_func_1
[282175.338284] Inside workqueue_func_1
[282176.362292] Inside workqueue_func_1
[282177.386297] Inside workqueue_func_1
[282178.410281] Inside workqueue_func_1
[282179.434217] Inside workqueue_func_2
[282180.458275] Inside workqueue_func_2
[282181.482260] Inside workqueue_func_2
[282182.506300] Inside workqueue_func_2
[282183.530275] Inside workqueue_func_2
[282184.554217] Inside workqueue_func_2
[282185.578258] Inside workqueue_func_2
[282186.602256] Inside workqueue_func_2
[282187.626266] Inside workqueue_func_2
[282188.650265] Inside workqueue_func_2
Unload the module using rmmod command.
$ sudo rmmod tc3
Check kernel messages to see if the module is unloaded or not.
$ dmesg
[282192.532346] Inside queue_exit function
[282192.532350] Destroying workqueue
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 flush_rcu_work");
Initialize the work which we are going to use in this example
INIT_RCU_WORK(&my_work,workqueue_func);
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(1000);
}
}
This function creates workqueue, intiializes work and queues to the workqueue.
void queue_start(void)
{
my_workqueue = create_workqueue(WQ_NAME);
INIT_RCU_WORK(&my_work,workqueue_func);
queue_rcu_work(my_workqueue,&my_work);
}
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");
flush_rcu_work(&my_work);
flush_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/* create_dynamic_work/INIT_RCU_WORK */
2
3#include <linux/init.h>
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/workqueue.h>
7#include <linux/delay.h>
8#include <linux/jiffies.h>
9
10#define WQ_NAME "tc6_workqueue"
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Linux_usr");
14MODULE_DESCRIPTION("Example of INIT_RCU_WORK");
15
16struct workqueue_struct *my_workqueue;
17struct rcu_work my_work;
18void workqueue_func(struct work_struct *work);
19void queue_start(void);
20void queue_stop(void);
21
22/* workqueue_func - executes when work is queued to workqueue,
23 * prints a statement and sleeps for 1000ms,
24 * stops when i value is greater than 10 */
25
26void workqueue_func(struct work_struct *work)
27{
28 int i = 0;
29 while (i < 10) {
30 pr_info("Inside workqueue_func\n");
31 i++;
32 msleep(1000);
33 }
34}
35
36/* queue_start - executes during execution of queue_start,
37 * creates workqueue,
38 * intiializes work and queues to the workqueue */
39
40void queue_start(void)
41{
42 my_workqueue = create_workqueue(WQ_NAME);
43 INIT_RCU_WORK(&my_work,workqueue_func);
44 queue_rcu_work(my_workqueue,&my_work);
45}
46
47/* queue_init - executes when module is loaded,
48 * calls queue_start */
49
50static int __init queue_init(void)
51{
52 pr_info("Inside queue_init function\n");
53 queue_start();
54 return 0;
55}
56
57/* queue_stop - executes during execution of queue_exit,
58 * waits until the completion and destroys workqueue */
59
60void queue_stop(void)
61{
62 pr_info("Destroying workqueue\n");
63 flush_rcu_work(&my_work);
64 flush_workqueue(my_workqueue);
65}
66
67/* queue_exit - executes when module is unloaded,
68 * calls queue_stop */
69
70static void __exit queue_exit(void)
71{
72 pr_info("Inside queue_exit function\n");
73 queue_stop();
74 return;
75}
76
77module_init(queue_init);
78module_exit(queue_exit);
1obj-m += tc4.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 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 tc4.c
-rw-rw-r-- 1 test test 180448 Aug 2 12:46 tc4.ko
-rw-rw-r-- 1 test test 80 Aug 2 12:46 tc4.mod
-rw-rw-r-- 1 test test 1104 Aug 2 12:46 tc4.mod.c
-rw-rw-r-- 1 test test 149288 Aug 2 12:46 tc4.mod.o
-rw-rw-r-- 1 test test 32624 Aug 2 12:46 tc4.o
Load the module to kernel using insmod command.
$ sudo insmod ./tc4.ko
Check kernel messages to verify if the module is loaded or not.
$ dmesg
[282424.157821] Inside queue_init function
[282424.202296] Inside workqueue_func
[282425.226337] Inside workqueue_func
[282426.250143] Inside workqueue_func
[282427.274333] Inside workqueue_func
[282428.298179] Inside workqueue_func
[282429.322313] Inside workqueue_func
[282430.346329] Inside workqueue_func
[282431.370333] Inside workqueue_func
[282432.394338] Inside workqueue_func
[282433.418338] Inside workqueue_func
Unload the module using rmmod command.
$ sudo rmmod tc4
Check kernel messages to see if the module is unloaded or not.
$ dmesg
[282439.203573] Inside queue_exit function
[282439.203578] Destroying workqueue