Create Dynamic Work

Topics in this section,

#

Version

Ubuntu

Ubuntu 22.10

Kernel

6.8.0

#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 INIT_WORK_ONSTACK(_work, _func)
  • Here is an example of how to use the API,

INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1);
INIT_WORK_ONSTACK(&my_work_2,workqueue_func_2);
#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);
#include <linux/workqueue.h>

static inline bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay);
  • Here is an example of how to use the API,

queue_delayed_work(my_workqueue,&my_work_1,msecs_to_jiffies(100));
queue_delayed_work(my_workqueue,&my_work_2,msecs_to_jiffies(300));
#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);
#include <linux/workqueue.h>

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

INIT_DELAYED_WORK_ONSTACK(&my_work,workqueue_func);
#include <linux/workqueue.h>

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

INIT_DEFERRABLE_WORK(&my_work,workqueue_func);
#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));
#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);
#include <linux/workqueue.h>

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

INIT_RCU_WORK(&my_work,workqueue_func);
#include <linux/workqueue.h>

extern bool queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork);
  • Here is an example of how to use the API,

queue_rcu_work(my_workqueue,&my_work);
#include <linux/workqueue.h>

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

flush_workqueue(my_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 INIT_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)
{
        pr_info("Inside workqueue_func_2\n");
}
  • This function creates workqueue, intiializes work and queues to the workqueue.

void queue_start(void)
{
        my_work_queue = create_workqueue(WQ_NAME);
        INIT_WORK(&my_work_1,workqueue_func_1);
        INIT_WORK(&my_work_2,workqueue_func_2);
        queue_work(my_work_queue,&my_work_2);
        queue_work(my_work_queue,&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)
{
        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
 7#define WQ_NAME "tc1_workqueue"
 8
 9MODULE_LICENSE("GPL");
10MODULE_AUTHOR("Linux_usr");
11MODULE_DESCRIPTION("Example of INIT_WORK");
12
13struct work_struct my_work_1;
14struct work_struct my_work_2;
15struct workqueue_struct *my_work_queue;
16void workqueue_func_1(struct work_struct *work);
17void workqueue_func_2(struct work_struct *work);
18void queue_start(void);
19void queue_stop(void);
20
21/* workqueue_func_1 - executes when work_1 is queued to workqueue,
22 * prints a statements and sleeps for 1000 secs,
23 * stops when i values goes greater than 10 */
24
25void workqueue_func_1(struct work_struct *work)
26{
27    int i = 0;
28    while(i < 10){
29        pr_info("Inside workqueue_func_1\n");
30        i++;
31        msleep(1000);
32    }
33}
34
35/* workqueue_func_2 - executes when work_2 is queued to workqueue,
36 * prints a statements and exits from the function */
37
38void workqueue_func_2(struct work_struct *work)
39{
40    pr_info("Inside workqueue_func_2\n");
41}
42
43/* queue_start - executes when the module is initialized,
44 * creates workqueue,
45 * initializes work and queues to workqueue */
46
47void queue_start(void)
48{
49    my_work_queue = create_workqueue(WQ_NAME);
50    INIT_WORK(&my_work_1,workqueue_func_1);
51    INIT_WORK(&my_work_2,workqueue_func_2);
52    queue_work(my_work_queue,&my_work_2);
53    queue_work(my_work_queue,&my_work_1);
54}
55
56/* queue_init - calls when module is inserted,
57 * calls queue_start function */
58
59static int __init queue_init(void)
60{
61    pr_info("Inside queue_init function\n");
62    queue_start();
63    return 0;
64}
65
66/* queue_stop - calls during the execution of queue_exit,
67 * destroys the workqueue */
68
69void queue_stop(void)
70{
71    destroy_workqueue(my_work_queue);
72}
73
74/* queue_exit - executes when the module is removed,
75 * calls queue_stop function */
76
77static void __exit queue_exit(void)
78{
79    pr_info("Inside queue_exit function\n");
80    queue_stop();
81    return;
82}
83
84module_init(queue_init);
85module_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 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 INIT_WORK_ONSTACK");
  • Initialize the work which we are going to use in this example

INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1);
INIT_WORK_ONSTACK(&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_1 = create_workqueue(WQ_NAME_1);
        my_workqueue_2 = create_workqueue(WQ_NAME_2);
        INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1);
        INIT_WORK_ONSTACK(&my_work_2,workqueue_func_2);
        queue_work(my_work_queue,&my_work_2);
        queue_work(my_work_queue,&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)
{
        destroy_workqueue(my_workqueue);
        destroy_workqueue(my_workqueue_2);
}
  • 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
 7#define WQ_NAME_1 "tc2_workqueue_1"
 8#define WQ_NAME_2 "tc2_workqueue_2" 
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of INIT_WORK_ONSTACK");
13
14struct workqueue_struct *my_workqueue_1;
15struct workqueue_struct *my_workqueue_2;
16struct work_struct my_work_1;
17struct work_struct my_work_2;
18void workqueue_func_1(struct work_struct *work);
19void workqueue_func_2(struct work_struct *work);
20void queue_start(void);
21void queue_stop(void);
22
23/* workqueue_func_1 - executes when work_1 is queued to workqueue,
24 * prints a statement and sleeps for 1000ms,
25 * stops when i value goes greater than 10 */
26
27void workqueue_func_1(struct work_struct *work)
28{
29    int i = 0;
30    while (i < 10) {
31        pr_info("Inside workqueue_func_1\n");
32        i++;
33        msleep(1000);
34    }
35}
36
37/* workqueue_func_2 - executes when work_2 is queued to workqueue,
38 * prints a statement and sleeps for 1000ms,
39 * stops when i value goes greater than 10 */
40
41void workqueue_func_2(struct work_struct *work)
42{
43    int i = 0;
44    while (i < 10) {
45        pr_info("Inside workqueue_func_2\n");
46        i++;
47        msleep(1000);
48    }
49}
50
51/* queue_start - executes during the execution of queue_init,
52 * creates workqueues,
53 * intializes work and queues to the workqueue */
54
55void queue_start(void)
56{
57    my_workqueue_1 = create_workqueue(WQ_NAME_1);
58    my_workqueue_2 = create_workqueue(WQ_NAME_2);
59    INIT_WORK_ONSTACK(&my_work_1,workqueue_func_1);
60    INIT_WORK_ONSTACK(&my_work_2,workqueue_func_2);
61    queue_work(my_workqueue_1,&my_work_1);
62    queue_work(my_workqueue_2,&my_work_2);
63}
64
65/* queue_init - executes during the module insertion,
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 workqueues */
77
78void queue_stop(void)
79{
80    destroy_workqueue(my_workqueue_1);
81    destroy_workqueue(my_workqueue_2);
82}
83
84/* queue_exit - executes during the removal of module,
85 * calls queue_stop */
86
87static void __exit queue_exit(void)
88{
89    pr_info("Inside queue_exit function\n");
90    queue_stop();
91    return;
92}
93
94module_init(queue_init);
95module_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     84 Aug  2 12:51 modules.order
-rw-rw-r-- 1 test test      0 Aug  2 12:51 Module.symvers
-rw-rw-r-- 1 test test   2356 Aug  2 11:47 tc2.c
-rw-rw-r-- 1 test test 181992 Aug  2 12:51 tc2.ko
-rw-rw-r-- 1 test test     84 Aug  2 12:51 tc2.mod
-rw-rw-r-- 1 test test   1103 Aug  2 12:51 tc2.mod.c
-rw-rw-r-- 1 test test 149296 Aug  2 12:51 tc2.mod.o
-rw-rw-r-- 1 test test  34160 Aug  2 12:51 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
[ 1927.976881] Inside queue_init function
[ 1927.977802] Inside workqueue_func_1
[ 1927.977886] Inside workqueue_func_2
[ 1928.986617] Inside workqueue_func_2
[ 1928.986634] Inside workqueue_func_1
[ 1930.010693] Inside workqueue_func_2
[ 1930.010731] Inside workqueue_func_1
[ 1931.034722] Inside workqueue_func_2
[ 1931.034739] Inside workqueue_func_1
[ 1932.058735] Inside workqueue_func_2
[ 1932.058751] Inside workqueue_func_1
[ 1933.082732] Inside workqueue_func_2
[ 1933.082760] Inside workqueue_func_1
[ 1934.106692] Inside workqueue_func_1
[ 1934.106709] Inside workqueue_func_2
[ 1935.130737] Inside workqueue_func_2
[ 1935.130753] Inside workqueue_func_1
[ 1936.154741] Inside workqueue_func_1
[ 1936.154758] Inside workqueue_func_2
[ 1937.178738] Inside workqueue_func_2
[ 1937.178755] 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
[ 1955.215382] Inside queue_exit function
  • 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 INIT_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)
{
        cancel_delayed_work_sync(&my_work_1);
        cancel_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#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 "tc3_workqueue"
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of INIT_DELAYED_WORK");
13
14struct workqueue_struct *my_workqueue;
15struct delayed_work my_work_1;
16struct delayed_work 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 - exectues when work_1 is queued to workqueue,
23 * prints a statement and sleeps for 1000ms,
24 * stops when i value goes 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(1000);
33    }
34}
35
36/* workqueue_func_2 - executes when work_2 is queued to workqueue,
37 * prints a statement and sleeps for 1000ms,
38 * stops when i value goes greater than 10ms */
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(1000);
47    }
48}
49
50/* queue_start - executes during execution of queue_init,
51 * creates workqueue,
52 * initializes work and queues to the workqueue */
53
54void queue_start(void)
55{
56    my_workqueue = create_workqueue(WQ_NAME);
57    INIT_DELAYED_WORK(&my_work_1,workqueue_func_1);
58    INIT_DELAYED_WORK(&my_work_2,workqueue_func_2);
59    queue_delayed_work(my_workqueue,&my_work_1,msecs_to_jiffies(100));
60    queue_delayed_work(my_workqueue,&my_work_2,msecs_to_jiffies(300));
61}
62
63/* queue_init - executes when the module is inserted,
64 * calls queue_start */
65
66static int __init queue_init(void)
67{
68    pr_info("Inside queue_init function\n");
69    queue_start();
70    return 0;
71}
72
73/* queue_stop - executes during the execution of queue_exit,
74 * destroys work and workqueues */
75
76void queue_stop(void)
77{
78    cancel_delayed_work_sync(&my_work_1);
79    cancel_delayed_work_sync(&my_work_2);
80    pr_info("Destroying workqueue\n");
81    destroy_workqueue(my_workqueue);
82}
83
84/* queue_exit - executes when the module is removed,
85 * calls queue_stop */
86
87static void __exit queue_exit(void)
88{
89    pr_info("Inside queue_exit function\n");
90    queue_stop();
91    return;
92}
93
94module_init(queue_init);
95module_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
[ 1400.538722] Inside workqueue_func_1
[ 1401.562742] Inside workqueue_func_1
[ 1402.586747] Inside workqueue_func_1
[ 1403.610761] Inside workqueue_func_1
[ 1404.634741] Inside workqueue_func_1
[ 1405.658741] Inside workqueue_func_1
[ 1406.682728] Inside workqueue_func_2
[ 1407.706664] Inside workqueue_func_2
[ 1408.730598] Inside workqueue_func_2
[ 1409.754723] Inside workqueue_func_2
[ 1410.778722] Inside workqueue_func_2
[ 1411.802725] Inside workqueue_func_2
[ 1412.826721] Inside workqueue_func_2
[ 1413.850751] Inside workqueue_func_2
[ 1414.874732] Inside workqueue_func_2
[ 1415.898674] 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
[ 1428.223989] Inside queue_exit function
[ 1428.223998] 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 INIT_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_ONSTACK(&my_work,workqueue_func);
        queue_delayed_work(my_workqueue,&my_work,msecs_to_jiffies(100));
}
  • 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 "tc4_workqueue"
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of INIT_DELAYED_WORK_ONSTACK");
13
14struct workqueue_struct *my_workqueue;
15struct delayed_work my_work;
16void workqueue_func(struct work_struct *work);
17void queue_start(void);
18void queue_stop(void);
19
20/* workqueue_func - executes when work is queued to workqueue,
21 * prints a statement and sleeps for 1000ms,
22 * stops when i value goes greater than 10 */
23
24void workqueue_func(struct work_struct *work)
25{
26    int i = 0;
27    while (i < 10) {
28        pr_info("Inside workqueue_func\n");
29        i++;
30        msleep(1000);
31    }
32}
33
34/* queue_start - executes during the execution of queue_init,
35 * creates workqueue,
36 * initializes work and queues it to workqueue */
37
38void queue_start(void)
39{
40    my_workqueue = create_workqueue(WQ_NAME);
41    INIT_DELAYED_WORK_ONSTACK(&my_work,workqueue_func);
42    queue_delayed_work(my_workqueue,&my_work,msecs_to_jiffies(100));
43}
44
45/* queue_init - executes during the module initialization,
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 * destroys the workqueue */
57
58void queue_stop(void)
59{
60    pr_info("Destroying workqueue\n");
61    destroy_workqueue(my_workqueue);
62}
63
64/* queue_exit - executes during the execution of queue_exit,
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 += 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 384
-rw-rw-r-- 1 test test    151 Aug  2 11:47 Makefile
-rw-rw-r-- 1 test test     92 Aug  2 12:44 modules.order
-rw-rw-r-- 1 test test      0 Aug  2 12:44 Module.symvers
-rw-rw-r-- 1 test test   1770 Aug  2 11:47 tc4.c
-rw-rw-r-- 1 test test 181696 Aug  2 12:44 tc4.ko
-rw-rw-r-- 1 test test     92 Aug  2 12:44 tc4.mod
-rw-rw-r-- 1 test test   1188 Aug  2 12:44 tc4.mod.c
-rw-rw-r-- 1 test test 149440 Aug  2 12:44 tc4.mod.o
-rw-rw-r-- 1 test test  33672 Aug  2 12:44 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
[ 1558.768976] Inside queue_init function
[ 1558.870683] Inside workqueue_func
[ 1559.902483] Inside workqueue_func
[ 1560.922696] Inside workqueue_func
[ 1561.946674] Inside workqueue_func
[ 1562.970693] Inside workqueue_func
[ 1563.994707] Inside workqueue_func
[ 1565.018698] Inside workqueue_func
[ 1566.042704] Inside workqueue_func
[ 1567.066717] Inside workqueue_func
[ 1568.090639] 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
[ 1578.489697] Inside queue_exit function
[ 1578.489703] 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 INIT_DEFERRABLE_WORK");
  • Initialize the work which we are going to use in this example

INIT_DEFERRABLE_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)
{
        INIT_DEFERRABLE_WORK(&my_work,workqueue_func);
        schedule_delayed_work(&my_work,msecs_to_jiffies(100));
}
  • 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_delayed_work(&my_work);
}
  • 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
 8MODULE_LICENSE("GPL");
 9MODULE_AUTHOR("Linux_usr");
10MODULE_DESCRIPTION("Example of INIT_DEFERRABLE_WORK");
11
12struct delayed_work my_work;
13void workqueue_func(struct work_struct *work);
14void queue_start(void);
15void queue_stop(void);
16
17/* workqueue_func - executes when work is queued to workqueue,
18 * prints a statement and sleeps for 1000ms,
19 * stops when i value is greater than 10 */
20
21void workqueue_func(struct work_struct *work)
22{
23    int i = 0;
24    while (i < 10) {
25        pr_info("Inside workqueue_func\n");
26        i++;
27        msleep(1000);
28    }
29}
30
31/* queue_start - executes during the execution of queue_init,
32 * initializes work and schedule the work */
33
34void queue_start(void)
35{
36    INIT_DEFERRABLE_WORK(&my_work,workqueue_func);
37    schedule_delayed_work(&my_work,msecs_to_jiffies(100));
38}
39
40/* queue_init - executes during module initialization,
41 * calls queue_start */
42
43static int __init queue_init(void)
44{
45    pr_info("Inside queue_init function\n");
46    queue_start();
47    return 0;
48}
49
50/* queue_stop - executes during the execution of queue_exit,
51 * destroys the work after its completion */
52
53void queue_stop(void)
54{
55    pr_info("Destroying workqueue\n");
56    cancel_delayed_work(&my_work);
57}
58
59/* queue_exit - executes during removal of module,
60 * calls queue_exit */
61
62static void __exit queue_exit(void)
63{
64    pr_info("Inside queue_exit function\n");
65    queue_stop();
66    return;
67}
68
69module_init(queue_init);
70module_exit(queue_exit);
1obj-m += tc5.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 376
-rw-rw-r-- 1 test test    151 Aug  2 11:47 Makefile
-rw-rw-r-- 1 test test     87 Aug  2 12:39 modules.order
-rw-rw-r-- 1 test test      0 Aug  2 12:39 Module.symvers
-rw-rw-r-- 1 test test   1607 Aug  2 11:47 tc5.c
-rw-rw-r-- 1 test test 180088 Aug  2 12:39 tc5.ko
-rw-rw-r-- 1 test test     87 Aug  2 12:39 tc5.mod
-rw-rw-r-- 1 test test   1184 Aug  2 12:39 tc5.mod.c
-rw-rw-r-- 1 test test 149424 Aug  2 12:39 tc5.mod.o
-rw-rw-r-- 1 test test  32096 Aug  2 12:39 tc5.o
  • Load the module to kernel using insmod command.

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

$ dmesg
[ 1244.134006] Inside queue_init function
[ 1248.986733] Inside workqueue_func
[ 1250.010739] Inside workqueue_func
[ 1251.034686] Inside workqueue_func
[ 1252.058733] Inside workqueue_func
[ 1253.082743] Inside workqueue_func
[ 1254.106735] Inside workqueue_func
[ 1255.130726] Inside workqueue_func
[ 1256.154716] Inside workqueue_func
[ 1257.178737] Inside workqueue_func
[ 1258.202672] Inside workqueue_func
  • Unload the module using rmmod command.

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

$ dmesg
[ 1280.080401] Inside queue_exit function
[ 1280.080405] 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 INIT_DEFERRABLE_WORK");
  • Initialize the work which we are going to use in this example

INIT_DEFERRABLE_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)
{
        INIT_DEFERRABLE_WORK(&my_work,workqueue_func);
        schedule_delayed_work(&my_work,msecs_to_jiffies(100));
}
  • 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_delayed_work(&my_work);
}
  • 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 "tc6_workqueue"
 9
10MODULE_LICENSE("GPL");
11MODULE_AUTHOR("Linux_usr");
12MODULE_DESCRIPTION("Example of INIT_RCU_WORK");
13
14struct workqueue_struct *my_workqueue;
15struct rcu_work my_work;
16void workqueue_func(struct work_struct *work);
17void queue_start(void);
18void queue_stop(void);
19
20/* workqueue_func - 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(struct work_struct *work)
25{
26    int i = 0;
27    while (i < 10) {
28        pr_info("Inside workqueue_func\n");
29        i++;
30        msleep(1000);
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_RCU_WORK(&my_work,workqueue_func);
42    queue_rcu_work(my_workqueue,&my_work);
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    flush_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 += tc6.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 tc6.c
-rw-rw-r-- 1 test test 180448 Aug  2 12:46 tc6.ko
-rw-rw-r-- 1 test test     80 Aug  2 12:46 tc6.mod
-rw-rw-r-- 1 test test   1104 Aug  2 12:46 tc6.mod.c
-rw-rw-r-- 1 test test 149288 Aug  2 12:46 tc6.mod.o
-rw-rw-r-- 1 test test  32624 Aug  2 12:46 tc6.o
  • Load the module to kernel using insmod command.

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

$ dmesg
[ 1708.830257] Inside queue_init function
[ 1708.870492] Inside workqueue_func
[ 1709.882740] Inside workqueue_func
[ 1710.906743] Inside workqueue_func
[ 1711.930741] Inside workqueue_func
[ 1712.954710] Inside workqueue_func
[ 1713.978702] Inside workqueue_func
[ 1715.002762] Inside workqueue_func
[ 1716.026772] Inside workqueue_func
[ 1717.050761] Inside workqueue_func
[ 1718.074730] Inside workqueue_func
  • Unload the module using rmmod command.

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

$ dmesg
[ 1730.664537] Inside queue_exit function
[ 1730.664543] Destroying workqueue