Creating completion variable
Topics in this section,
Explanation of Completion variable APIs
Explanation of miscellaneous APIs
Example 1: Create completion variable with DECLARE_COMPLETION
Example 2: Create completion variable using init_completion
Example 3: Create completion variable using COMPLETION_INITIALIZER
Example 4: Create completion variable using COMPLETION_INITIALIZER_ONSTACK
Example 5: Create completion variable using DECLARE_COMPLETION_ONSTACK
# |
Version |
---|---|
Ubuntu |
Ubuntu 22.10 |
Kernel |
6.7.9 |
In this program, you are going to learn
How to create completion variable ?
What are the different ways to create completion variable?
How to signal once the task is completed?
How to use Kthread APIs ?
How to use Completion APIs ?
How to use below APIs ?
Here is the function prototype of the API: kthread_should_stop
#include <linux/kthread.h>
bool kthread_should_stop(void);
where
kthread_should_stop: this is used to determine whether the thread should return now. Whenever the kthread_stop() is called it will be woken and returns true.
return type: returns true when the thread is stopped, false when the thread is still in execution
Here is an example of how to use the API,
while (!kthread_should_stop())
{
//add the instructions to be performed during thread execution.
}
Here is the function prototype of the API: kthread_run
#include <linux/kthread.h>
#define kthread_run(threadfn, data, namefmt, ...)
where
kthread_run : is used to create and wake a kthread
return type: struct task_struct* (i.e) address of the kthread
threadfn: function to executed by kthread
data: data pointer for threadfn which can be used to send any possible arguments required for threadfn.
namefmt: printf-style format for the thread name which will be displayed on ps output when the thread is in execution.
Here is an example of how to use the API,
kthread_run(mythread,NULL,"sample kthread");
Here is the function prototype of the API: kthread_stop
#include <linux/kthread.h>
int kthread_stop(struct task_struct *k);
where
kthread_stop: stops a kthread.
return type: returns the return value of threadfn() which is passed as an argument during kthread creation.
k: kthread created by one of the API used to created kthread.
Here is the example of how to use the API,
kthread_stop(mythread);
Here is the function prototype of the API: DECLARE_COMPLETION
#include <linux/completion.h>
#define DECLARE_COMPLETION(work) \
struct completion work = COMPLETION_INITIALIZER(work)
where
DECLARE_COMPLETION : declare and initialize a completion structure
work: identifier for completion structure
Here is the example of how to use the API
static DECLARE_COMPLETION(mycompletionvar);
Here is the prototype of the API: init_completion
#include <linux/completion.h>
static inline void init_completion(struct completion *x);
where
init_completion : initialize a dynamically allocated completion
x : pointer to completion structure that is to be initialized
Here is the example of how to use the API
init_completion(mycompletionvar);
Here is the prototype of the API: COMPLETION_INITIALIZER
#include <linux/completion.h>
#define COMPLETION_INITIALIZER(work) \
{ 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
where
COMPLETION_INITIALIZER : initializes a completion structure
work : identifier for completion structure
Here is the example of how to use the API
COMPLETION_INITIALIZER(mycompletionvar);
Here is the prototype of the API: COMPLETION_INITIALIZER_ONSTACK
#include <linux/completion.h>
#define COMPLETION_INITIALIZER_ONSTACK(work) \
(*({ init_completion(&work); &work; }))
where
COMPLETION_INITIALIZER_ONSTACK : nitializes a completion structure on the kernel stack.
work: identifier for the completion structure
Here is the example of how to use the API
COMPLETION_INITIALIZER_ONSTACK(mycompletionvar);
Here is the prototype of the API: DECLARE_COMPLETION_ONSTACK
#include <linux/completion.h>
# define DECLARE_COMPLETION_ONSTACK(work) \
struct completion work = COMPLETION_INITIALIZER_ONSTACK(work)
where
DECLARE_COMPLETION_ONSTACK : This macro declares and initializes a completion structure on the kernel stack.
work: identifier for the completion structure
Here is the example of how to use the API
DECLARE_COMPLETION_ONSTACK(mycompletionvar);
Here is the prototype of the API: wait_for_completion
#include <linux/completion.h>
void wait_for_completion(struct completion *x);
where
wait_for_completion : waits for completion of a task
x : holds the state of this particular completion
Here is an example of how to use the API,
wait_for_completion(mycompletionvar);
Here is the prototype of module paramter APIs
#include <linux/module.h>
#define MODULE_LICENSE(_license) MODULE_FILE MODULE_INFO(license, _license)
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
where
MODULE_LICENSE: tells the kernel what license is used by our module.
MODULE_AUTHOR: denotes the author of this kernel module.
MODULE_DESCRIPTION: gives a basic idea about what the kernel module does.
These information can be found when modinfo command is used which lists out all these above mentioned information.
Here is the example of how to use the Module parameter APIs,
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Usr");
MODULE_DESCRIPTION("Sample kernel module");
Here is the prototype of the API: IS_ERR
#include <linux/err.h>
static inline bool __must_check IS_ERR(__force const void *ptr);
where
IS_ERR: Detects an error pointer
return type: return true if it’s an error pointer else return false.
ptr: pointer which needs to detected.
Here is an example of how to use the API,
if(IS_ERR(sample_ptr)) {
//instructions to be executed when error ptr is detected
} else {
//instructions to be executed when error ptr is not detected
}
Here is the example of the API: wake_up_process
#include <linux/sched.h>
extern int wake_up_process(struct task_struct *tsk);
where
wake_up_process: wake up a specific process
return type: returns 1 if the process is woken up, 0 if the process is in running state.
tsk: process to be woken up.
Here is the example of how to use the API,
wake_up_process(mythread);
Here is the prototype of the Driver entry point API’s
#include <linux/module.h>
#define module_init(x) __initcall(x);
#define module_exit(x) __exitcall(x);
where
module_init: driver initialization entry point which will be called at module insertion time.
module_exit: driver exit entry point which will be called during the removal of module.
- x:
function to be run at module insertion for module_init function.
function to be run when driver is removed for module_exit function.
Here is an example of how to use the driver entry point API’s
module_init(myinitmodule);
module_exit(myexitmodule);
In this example let’s see how to create completion variable and use with kthread.
Include the follow header files(.h) to refer the API being used for the execution.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
#include <linux/delay.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 DECLARE_COMPLETION");
Declare the thread and completion variables which we are going to create and use in this example
static struct task_struct *my_thread1;
static struct task_struct *my_thread2;
static DECLARE_COMPLETION(thread_done);
Add the module init function which will be executed once we load the kernel module using insmod command.
static int __init declare_completion_init(void)
{
pr_info("Inside thread init function\n");
thread_start();
return 0;
}
Add the thread start function which is called from module init function, creates the thread and starts it’s execution.
void thread_start(void)
{
my_thread1 = kthread_run(my_thread_fn1,NULL,"DECLARE_COMPLETION thread1 example");
if (IS_ERR(my_thread1))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
my_thread2 = kthread_run(my_thread_fn2,NULL,"DECLARE_COMPLETION thread2 example");
if (IS_ERR(my_thread2))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
}
Add the module exit function which will be executed once we unload the kernel module using rmmod command.
static void __exit declare_completion_exit(void)
{
pr_info("Inside kthread exit function\n");
thread_stop();
}
Add the thread stop function which is called from module exit function, destroys the thread created and stops it’s execution.
void thread_stop(void)
{
kthread_stop(my_thread2);
kthread_stop(my_thread1);
pr_info("destroyed thread and completed task\n");
}
Add the thread function API which will be called as soon as the kthread is created and is in running state.
static int my_thread_fn1(void *data)
{
while (!kthread_should_stop()) {
pr_info("my_thread_fn1 execution\n");
wait_for_completion(&thread_done);
msleep(1000);
}
return 0;
}
static int my_thread_fn2(void *data)
{
while(!kthread_should_stop()) {
pr_info("my_thread_fn2 execution\n");
msleep(1000);
}
complete(&thread_done);
return 0;
}
Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
module_init(declare_completion_init);
module_exit(declare_completion_exit);
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/module.h>
4#include <linux/kthread.h>
5#include <linux/completion.h>
6#include <linux/delay.h>
7
8MODULE_LICENSE("GPL");
9MODULE_DESCRIPTION("Example of DECLARE_COMPLETION");
10MODULE_AUTHOR("linux usr");
11
12static struct task_struct *my_thread1;
13static struct task_struct *my_thread2;
14static DECLARE_COMPLETION(thread_done);
15
16/* my_thread_fn1 - executes when thread1 is created,
17 * waits for thread_done to complete,
18 * stops when kthread_stop is called */
19
20static int my_thread_fn1(void *data)
21{
22 while (!kthread_should_stop()) {
23 pr_info("my_thread_fn1 execution\n");
24 wait_for_completion(&thread_done);
25 msleep(1000);
26 }
27 return 0;
28}
29
30/* my_thread_fn2 - executes when thread2 is created,
31 * prints a message and sleeps for 1000 ms,
32 * sends complete signal,
33 * stops when kthread_stop is called */
34
35static int my_thread_fn2(void *data)
36{
37 while(!kthread_should_stop()) {
38 pr_info("my_thread_fn2 execution\n");
39 msleep(1000);
40 }
41 complete(&thread_done);
42 return 0;
43}
44
45/* thread_start - creates thread and starts execution */
46
47void thread_start(void)
48{
49 my_thread1 = kthread_run(my_thread_fn1,NULL,"DECLARE_COMPLETION thread1 example");
50 if (IS_ERR(my_thread1))
51 pr_info("error creating in kthread\n");
52 else
53 pr_info("successfully created kthread\n");
54 my_thread2 = kthread_run(my_thread_fn2,NULL,"DECLARE_COMPLETION thread2 example");
55 if (IS_ERR(my_thread2))
56 pr_info("error creating in kthread\n");
57 else
58 pr_info("successfully created kthread\n");
59}
60
61/* declare_completion_init - calls thread_start function,
62 * executes when module is loaded */
63
64static int __init declare_completion_init(void)
65{
66 pr_info("inside thread init function\n");
67 thread_start();
68 return 0;
69}
70
71/* thread_stop - destroys thread and stops execution */
72
73void thread_stop(void)
74{
75 kthread_stop(my_thread2);
76 kthread_stop(my_thread1);
77 pr_info("destroyed thread and completed task\n");
78}
79
80/* declare_completion_exit - calls thread_stop function,
81 * executes when the module is loaded */
82
83static void __exit declare_completion_exit(void)
84{
85 pr_info("inside thread exit function\n");
86 thread_stop();
87}
88
89module_init(declare_completion_init);
90module_exit(declare_completion_exit);
1obj-m += kthread.o
2
3all:
4 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Run make to compile the kernel source and generate the .ko image.
make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
You are using: gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
CC [M] $HOME/kthread_examples/kthread.o
MODPOST $HOME/kthread_examples/Module.symvers
CC [M] $HOME/kthread_examples/kthread.mod.o
LD [M] $HOME/kthread_examples/kthread.ko
BTF [M] $HOME/kthread_examples/kthread.ko
Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
Check if the .ko is generated or not using ls command.
test@test-V520-15IKL:~$ ls -l
total 360
-rw-rw-r-- 1 test test 713 Mar 18 16:06 kthread.c
-rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
-rw-rw-r-- 1 test test 58 Mar 18 16:08 kthread.mod
-rw-rw-r-- 1 test test 1047 Mar 18 16:08 kthread.mod.c
-rw-rw-r-- 1 test test 96512 Mar 18 16:08 kthread.mod.o
-rw-rw-r-- 1 test test 74696 Mar 18 16:08 kthread.o
-rw-rw-r-- 1 test test 161 Mar 18 16:00 Makefile
-rw-rw-r-- 1 test test 58 Mar 18 16:08 modules.order
-rw-rw-r-- 1 test test 0 Mar 18 16:08 Module.symvers
Run modinfo command to get the information about the kernel module.
test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
filename: $HOME/kthread_examples/kthread.ko
description: Example of DECLARE_COMPLETION
author: Linux Usr
license: GPL
srcversion: 8D2147F67AB01CF0E482DAC
depends:
retpoline: Y
name: kthread
vermagic: 6.7.9 SMP preempt mod_unload modversions
insert the module using insmod command.
test@test-V520-15IKL:~$ sudo insmod ./kthread.ko
check if the module is loaded or not using lsmod command.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
kthread 16384 0
check if the thread is created or not using ps command.
test@test-V520-15IKL:~$ ps -N | grep DECLARE_COMPLETION
11293 ? 00:00:00 DECLARE_COMPLETION thread1 example
11294 ? 00:00:00 DECLARE_COMPLETION thread2 example
check for the kernel messages from init function and thread function once the module is loaded and thread is created.
test@test-V520-15IKL:~$ sudo dmesg
[ 6013.312821] inside thread init function
[ 6013.312847] successfully created kthread
[ 6013.312849] my_thread_fn1 execution
[ 6013.312875] successfully created kthread
[ 6013.312876] my_thread_fn2 execution
[ 6014.337095] my_thread_fn2 execution
[ 6015.361109] my_thread_fn2 execution
remove the module from kernel using rmmod command.
test@test-V520-15IKL:~$ sudo rmmod kthread
check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
test@test-V520-15IKL:~$
check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
test@test-V520-15IKL:~$ ps -N | grep DECLARE_COMPLETION
test@test-V520-15IKL:~$
Check for kernel messages from exit function using dmesg command.
test@test-V520-15IKL:~$ sudo dmesg
[ 6022.497201] destroyed thread and completed task
In this example let’s see how to create completion variable with init_completion and use kthread with it.
Include the follow header files(.h) to refer the API being used for the execution.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
#include <linux/delay.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_completion");
Declare the thread variables which we are going to create and use in this example
static struct task_struct *my_thread1;
static struct task_struct *my_thread2;
static struct completion thread_done;
Add the module init function which will be executed once we load the kernel module using insmod command.
static int __init init_completion_init(void)
{
pr_info("Inside kthread init function\n");
thread_start();
return 0;
}
Add the thread start function called from the module init function which is used to create the thread and execute it.
void thread_start(void)
{
init_completion(&thread_done);
pr_info("completion variable initialized\n");
my_thread1 = kthread_run(my_thread_fn1,NULL,"init_completion thread 1 example");
if (IS_ERR(my_thread1))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
my_thread2 = kthread_run(my_thread_fn2,NULL,"init_completion thread2 example");
if (IS_ERR(my_thread2))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
}
Add the module exit function which will be executed once we unload the kernel module using rmmod command.
static void __exit init_completion_exit(void)
{
pr_info("Inside kthread exit function\n");
thread_stop();
}
Add the thread stop function called from the module exit function which is used to destroy the thread and stop its execution.
void thread_stop(void)
{
kthread_stop(my_thread1);
kthread_stop(my_thread2);
pr_info("destroyed thread and completed task\n");
}
Add the thread function API which will be called as soon as the kthread is created and is in running state.
static int my_thread_fn1(void *data)
{
while (!kthread_should_stop()) {
pr_info("my_thread_fn1 execution\n");
msleep(1000);
}
complete(&thread_done);
return 0;
}
static int my_thread_fn2(void *data)
{
while(!kthread_should_stop()) {
pr_info("my_thread_fn2 execution\n");
wait_for_completion(&thread_done);
msleep(1000);
}
return 0;
}
Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
module_init(init_completion_init);
module_exit(init_completion_exit);
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/module.h>
4#include <linux/kthread.h>
5#include <linux/completion.h>
6#include <linux/delay.h>
7
8MODULE_LICENSE("GPL");
9MODULE_DESCRIPTION("Example of init_completion");
10MODULE_AUTHOR("linux usr");
11
12static struct task_struct *my_thread1;
13static struct task_struct *my_thread2;
14static struct completion thread_done;
15
16/* my_thread_fn1 - executes when thread1 is created,
17 * prints a message and sleeps for 1000ms,
18 * send completes signal,
19 * stops when kthread_stop is called */
20
21static int my_thread_fn1(void *data)
22{
23 while (!kthread_should_stop()) {
24 pr_info("my_thread_fn1 execution\n");
25 msleep(1000);
26 }
27 complete(&thread_done);
28 return 0;
29}
30
31/* my_thread_fn2 - executes when thread2 is created,
32 * waits for the completion signal,
33 * prints a message and sleeps for 1000ms,
34 * stops when kthread_stop is called*/
35
36static int my_thread_fn2(void *data)
37{
38 while(!kthread_should_stop()) {
39 pr_info("my_thread_fn2 execution\n");
40 wait_for_completion(&thread_done);
41 msleep(1000);
42 }
43 return 0;
44}
45
46/* thread_start - creates thread and executes it*/
47
48void thread_start(void)
49{
50 init_completion(&thread_done);
51 pr_info("completion variable initialized\n");
52 my_thread1 = kthread_run(my_thread_fn1,NULL,"init_completion thread 1 example");
53 if (IS_ERR(my_thread1))
54 pr_info("error creating in kthread\n");
55 else
56 pr_info("successfully created kthread\n");
57 my_thread2 = kthread_run(my_thread_fn2,NULL,"init_completion thread2 example");
58 if (IS_ERR(my_thread2))
59 pr_info("error creating in kthread\n");
60 else
61 pr_info("successfully created kthread\n");
62}
63
64/* init_completion_init - calls thread_start function,
65 * executes when module is loaded */
66
67static int __init init_completion_init(void)
68{
69 pr_info("inside thread init function\n");
70 thread_start();
71 return 0;
72}
73
74/* thread_stop - destroys thread and stops execution */
75
76void thread_stop(void)
77{
78 kthread_stop(my_thread1);
79 kthread_stop(my_thread2);
80 pr_info("destroyed thread and completed task\n");
81}
82
83/* init_completion_exit - calls thread_stop,
84 * executes when module is unloaded */
85
86static void __exit init_completion_exit(void)
87{
88 pr_info("inside thread exit function\n");
89 thread_stop();
90}
91
92module_init(init_completion_init);
93module_exit(init_completion_exit);
1obj-m += kthread.o
2
3all:
4 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Run make to compile the kernel source and generate the .ko image.
make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
You are using: gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
CC [M] $HOME/kthread_examples/kthread.o
MODPOST $HOME/kthread_examples/Module.symvers
CC [M] $HOME/kthread_examples/kthread.mod.o
LD [M] $HOME/kthread_examples/kthread.ko
BTF [M] $HOME/kthread_examples/kthread.ko
Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
Check if the .ko is generated or not using ls command.
test@test-V520-15IKL:~$ ls -l
total 360
-rw-rw-r-- 1 test test 713 Mar 18 16:06 kthread.c
-rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
-rw-rw-r-- 1 test test 58 Mar 18 16:08 kthread.mod
-rw-rw-r-- 1 test test 1047 Mar 18 16:08 kthread.mod.c
-rw-rw-r-- 1 test test 96512 Mar 18 16:08 kthread.mod.o
-rw-rw-r-- 1 test test 74696 Mar 18 16:08 kthread.o
-rw-rw-r-- 1 test test 161 Mar 18 16:00 Makefile
-rw-rw-r-- 1 test test 58 Mar 18 16:08 modules.order
-rw-rw-r-- 1 test test 0 Mar 18 16:08 Module.symvers
Run modinfo command to get the information about the kernel module.
test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
filename: $HOME/kthread_examples/kthread.ko
description: Example of init_completion
author: Linux Usr
license: GPL
srcversion: 8D2147F67AB01CF0E482DAC
depends:
retpoline: Y
name: kthread
vermagic: 6.7.9 SMP preempt mod_unload modversions
insert the module using insmod command.
test@test-V520-15IKL:~$ sudo insmod ./kthread.ko
check if the module is loaded or not using lsmod command.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
kthread 16384 0
check if the thread is created or not using ps command.
test@test-V520-15IKL:~$ ps -N | grep init_completion
19813 ? 00:00:00 init_completion thread 1 example
19814 ? 00:00:00 init_completion thread2 example
check for the kernel messages from init function and thread function once the module is loaded and thread is created.
test@test-V520-15IKL:~$ sudo dmesg
[15868.565622] inside thread init function
[15868.565627] completion variable initialized
[15868.565754] successfully created kthread
[15868.565760] my_thread_fn1 execution
[15868.565868] successfully created kthread
[15868.565878] my_thread_fn2 execution
[15869.588653] my_thread_fn1 execution
[15870.612639] my_thread_fn1 execution
remove the module from kernel using rmmod command.
test@test-V520-15IKL:~$ sudo rmmod kthread
check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
test@test-V520-15IKL:~$
check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
test@test-V520-15IKL:~$ ps -N | grep init_completion
test@test-V520-15IKL:~$
Check for kernel messages from exit function using dmesg command.
test@test-V520-15IKL:~$ sudo dmesg
[15873.684426] destroyed thread and completed task
In this example let’s see how to create completion variable using completion_initializer and use kthread with it.
Include the follow header files(.h) to refer the API being used for the execution.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
#include <linux/delay.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 completion initializer");
Declare the thread and completion variables which we are going to create and use in this example
static struct task_struct *my_thread1;
static struct task_struct *my_thread2;
static struct completion thread_done = COMPLETION_INITIALIZER(thread_done);
Add the module init function which will be executed once we load the kernel module using insmod command.
static int __init completion_initializer_init(void)
{
pr_info("Inside kthread init function\n");
thread_start();
return 0;
}
Add the thread start function called from module init function, which creates the thread, wakes it up and starts its execution.
void thread_start(void)
{
my_thread1 = kthread_run(my_thread_fn1,NULL,"completion_initializer thread1 example");
if (IS_ERR(my_thread1))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
my_thread2 = kthread_run(my_thread_fn2,NULL,"completion_initializer thread2 example");
if (IS_ERR(my_thread2))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
}
Add the module exit function which will be executed once we unload the kernel module using rmmod command.
static void __exit completion_initializer_exit(void)
{
pr_info("Inside kthread exit function\n");
thread_stop();
}
Add the thread stop function which is called from module exit function, which destroys the thread and stops the execution.
void thread_stop(void)
{
kthread_stop(my_thread1);
kthread_stop(my_thread2);
pr_info("destroyed thread and completed task\n");
}
Add the thread function API which will be called as soon as the kthread is created and is in running state.
static int my_thread_fn1(void *data)
{
while (!kthread_should_stop()) {
pr_info("my_thread_fn1 execution\n");
msleep(1000);
}
complete(&thread_done);
return 0;
}
static int my_thread_fn2(void *data)
{
while(!kthread_should_stop()) {
wait_for_completion(&thread_done);
pr_info("my_thread_fn2 execution\n");
msleep(1000);
}
return 0;
}
Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
module_init(kthread_completion_initializer_init);
module_exit(kthread_completion_initializer_exit);
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/module.h>
4#include <linux/kthread.h>
5#include <linux/completion.h>
6#include <linux/delay.h>
7
8MODULE_LICENSE("GPL");
9MODULE_DESCRIPTION("Example of completion_initializer");
10MODULE_AUTHOR("linux usr");
11
12static struct task_struct *my_thread1;
13static struct task_struct *my_thread2;
14static struct completion thread_done = COMPLETION_INITIALIZER(thread_done);
15
16/* my_thread_fn1 - executes when thread1 is called,
17 * prints a message and sleeps for 1000ms,
18 * sends complete signal,
19 * stops when kthread_stop is called */
20
21static int my_thread_fn1(void *data)
22{
23 while (!kthread_should_stop()) {
24 pr_info("my_thread_fn1 execution\n");
25 msleep(1000);
26 }
27 complete(&thread_done);
28 return 0;
29}
30
31/* my_thread_fn2 - executes when thread2 is called,
32 * waits for completion signal,
33 * prints a message and sleeps for 1000ms,
34 * stops when kthread_stop is called*/
35
36static int my_thread_fn2(void *data)
37{
38 while(!kthread_should_stop()) {
39 wait_for_completion(&thread_done);
40 pr_info("my_thread_fn2 execution\n");
41 msleep(1000);
42 }
43 return 0;
44}
45
46/* thread_start - creates thread and starts execution */
47
48void thread_start(void)
49{
50 my_thread1 = kthread_run(my_thread_fn1,NULL,"completion_initializer thread1 example");
51 if (IS_ERR(my_thread1))
52 pr_info("error creating in kthread\n");
53 else
54 pr_info("successfully created kthread\n");
55 my_thread2 = kthread_run(my_thread_fn2,NULL,"completion_initializer thread2 example");
56 if (IS_ERR(my_thread2))
57 pr_info("error creating in kthread\n");
58 else
59 pr_info("successfully created kthread\n");
60}
61
62/* completion_initializer_init - calls thread_start,
63 * executes when the module is loaded */
64
65static int __init completion_initializer_init(void)
66{
67 pr_info("inside thread init function\n");
68 thread_start();
69 return 0;
70}
71
72/* thread_stop - destroys thread and stops execution */
73
74void thread_stop(void)
75{
76 kthread_stop(my_thread1);
77 kthread_stop(my_thread2);
78 pr_info("destroyed thread and completed task\n");
79}
80
81/* completion_initializer_exit - calls thread_stop,
82 * executes when module is unloaded */
83
84static void __exit completion_initializer_exit(void)
85{
86 pr_info("inside kthread exit function\n");
87 thread_stop();
88}
89
90module_init(completion_initializer_init);
91module_exit(completion_initializer_exit);
1obj-m += kthread.o
2
3all:
4 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Run make to compile the kernel source and generate the .ko image.
make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
You are using: gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
CC [M] $HOME/kthread_examples/kthread.o
MODPOST $HOME/kthread_examples/Module.symvers
CC [M] $HOME/kthread_examples/kthread.mod.o
LD [M] $HOME/kthread_examples/kthread.ko
BTF [M] $HOME/kthread_examples/kthread.ko
Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
Check if the .ko is generated or not using ls command.
test@test-V520-15IKL:~$ ls -l
total 360
-rw-rw-r-- 1 test test 713 Mar 18 16:06 kthread.c
-rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
-rw-rw-r-- 1 test test 58 Mar 18 16:08 kthread.mod
-rw-rw-r-- 1 test test 1047 Mar 18 16:08 kthread.mod.c
-rw-rw-r-- 1 test test 96512 Mar 18 16:08 kthread.mod.o
-rw-rw-r-- 1 test test 74696 Mar 18 16:08 kthread.o
-rw-rw-r-- 1 test test 161 Mar 18 16:00 Makefile
-rw-rw-r-- 1 test test 58 Mar 18 16:08 modules.order
-rw-rw-r-- 1 test test 0 Mar 18 16:08 Module.symvers
Run modinfo command to get the information about the kernel module.
test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
filename: $HOME/kthread_examples/kthread.ko
description: Example of completion_initializer
author: Linux Usr
license: GPL
srcversion: 8D2147F67AB01CF0E482DAC
depends:
retpoline: Y
name: kthread
vermagic: 6.7.9 SMP preempt mod_unload modversions
insert the module using insmod command.
test@test-V520-15IKL:~$ sudo insmod ./kthread.ko
check if the module is loaded or not using lsmod command.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
kthread 16384 0
check if the thread is created or not using ps command.
test@test-V520-15IKL:~$ ps -N | grep completion_initializer
22765 ? 00:00:00 completion_initializer thread1 example
22766 ? 00:00:00 completion_initializer thread2 example
check for the kernel messages from init function and thread function once the module is loaded and thread is created.
test@test-V520-15IKL:~$ sudo dmesg
[23035.070258] inside thread init function
[23035.070335] successfully created kthread
[23035.070341] my_thread_fn1 execution
[23035.070382] successfully created kthread
[23036.084091] my_thread_fn1 execution
[23037.108194] my_thread_fn1 execution
[23038.132183] my_thread_fn1 execution
[23039.156253] my_thread_fn1 execution
remove the module from kernel using rmmod command.
test@test-V520-15IKL:~$ sudo rmmod kthread
check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
test@test-V520-15IKL:~$
check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
test@test-V520-15IKL:~$ ps -N | grep completion_initializer
test@test-V520-15IKL:~$
Check for kernel messages from exit function using dmesg command.
test@test-V520-15IKL:~$ sudo dmesg
[23047.946466] inside kthread exit function
[23048.372744] my_thread_fn2 execution
[23049.396770] destroyed thread and completed task
In this example let’s see how to create completion variable using COMPLETION_INITIALIZER_ONSTACK and use kthreads with it.
Include the follow header files(.h) to refer the API being used for the execution.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
#include <linux/delay.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 completion_initializer_onstack");
Declare the thread variables which we are going to create and use in this example
struct my_completion {
struct completion thread_done;
};
static struct task_struct *my_thread1;
static struct task_struct *my_thread2;
struct my_completion completion_var;
Add the module init function which will be executed once we load the kernel module using insmod command.
static int __init completion_initializer_onstack_init(void)
{
pr_info("Inside kthread init function\n");
thread_start();
return 0;
}
Add the thread start function called from module init function, which creates the thread, wakes it up and starts its execution.
void thread_start(void)
{
completion_var.thread_done = COMPLETION_INITIALIZER_ONSTACK(completion_var.thread_done);
my_thread1 = kthread_run(my_thread_fn1,NULL,"completion_initializer_onstack thread1 example");
if (IS_ERR(my_thread1))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
my_thread2 = kthread_run(my_thread_fn2,NULL,"completion_initializer_onstack thread2 example");
if (IS_ERR(my_thread2))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
}
Add the module exit function which will be executed once we unload the kernel module using rmmod command.
static void __exit completion_initializer_onstack_exit(void)
{
pr_info("inside kthread exit function\n");
thread_stop();
}
Add the thread stop function which is called from module exit function, which destroys the thread and stops the execution.
void thread_stop(void)
{
kthread_stop(my_thread1);
kthread_stop(my_thread2);
pr_info("destroyed thread and completed task\n");
}
Add the thread function API which will be called as soon as the kthread is created and is in running state.
static int my_thread_fn1(void *data)
{
while (!kthread_should_stop()) {
pr_info("my_thread_fn1 execution\n");
msleep(1000);
}
complete(&completion_var.thread_done);
return 0;
}
static int my_thread_fn2(void *data)
{
while(!kthread_should_stop()) {
wait_for_completion(&completion_var.thread_done);
pr_info("my_thread_fn2 execution\n");
msleep(1000);
}
return 0;
}
Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
module_init(completion_initializer_onstack_init);
module_exit(completion_initializer_onstack_exit);
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/module.h>
4#include <linux/kthread.h>
5#include <linux/completion.h>
6#include <linux/delay.h>
7
8MODULE_LICENSE("GPL");
9MODULE_DESCRIPTION("example of complete_initializer_onstack");
10MODULE_AUTHOR("linux usr");
11
12struct my_completion {
13 struct completion thread_done;
14};
15static struct task_struct *my_thread1;
16static struct task_struct *my_thread2;
17struct my_completion completion_var;
18
19/* my_thread_fn1 - executes when thread1 is created,
20 * prints messages and sleeps for 1000ms,
21 * send completes signal,
22 * stops when kthread_stop is called */
23
24static int my_thread_fn1(void *data)
25{
26 while (!kthread_should_stop()) {
27 pr_info("my_thread_fn1 execution\n");
28 msleep(1000);
29 }
30 complete(&completion_var.thread_done);
31 return 0;
32}
33
34/* my_thread_fn2 - executes when thread2 is created,
35 * waits for completion,
36 * prints a message and sleeps for 1000ms,
37 * stops when kthread_stop is called */
38
39static int my_thread_fn2(void *data)
40{
41 while(!kthread_should_stop()) {
42 wait_for_completion(&completion_var.thread_done);
43 pr_info("my_thread_fn2 execution\n");
44 msleep(1000);
45 }
46 return 0;
47}
48
49/* thread_start - creates thread and starts execution */
50
51void thread_start(void)
52{
53 completion_var.thread_done = COMPLETION_INITIALIZER_ONSTACK(completion_var.thread_done);
54 my_thread1 = kthread_run(my_thread_fn1,NULL,"completion_initializer_onstack thread1 example");
55 if (IS_ERR(my_thread1))
56 pr_info("error creating in kthread\n");
57 else
58 pr_info("successfully created kthread\n");
59 my_thread2 = kthread_run(my_thread_fn2,NULL,"completion_initializer_onstack thread2 example");
60 if (IS_ERR(my_thread2))
61 pr_info("error creating in kthread\n");
62 else
63 pr_info("successfully created kthread\n");
64}
65
66/* completion_initializer_onstack - calls thread_start,
67 * executes when completion_initializer_onstack */
68
69static int __init completion_initializer_onstack_init(void)
70{
71 pr_info("inside thread init function\n");
72 thread_start();
73 return 0;
74}
75
76/* thread_stop - destroys thread and stops execution */
77
78void thread_stop(void)
79{
80 kthread_stop(my_thread1);
81 kthread_stop(my_thread2);
82 pr_info("destroyed thread and completed task\n");
83}
84
85/* completion_initializer_onstack_exit - calls thread_stop,
86 * executes when completion_intializer_onstack */
87
88static void __exit completion_initializer_onstack_exit(void)
89{
90 pr_info("inside kthread exit function\n");
91 thread_stop();
92}
93
94module_init(completion_initializer_onstack_init);
95module_exit(completion_initializer_onstack_exit);
1obj-m += kthread.o
2
3all:
4 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Run make to compile the kernel source and generate the .ko image.
make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
You are using: gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
CC [M] $HOME/kthread_examples/kthread.o
MODPOST $HOME/kthread_examples/Module.symvers
CC [M] $HOME/kthread_examples/kthread.mod.o
LD [M] $HOME/kthread_examples/kthread.ko
BTF [M] $HOME/kthread_examples/kthread.ko
Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
Check if the .ko is generated or not using ls command.
test@test-V520-15IKL:~$ ls -l
total 360
-rw-rw-r-- 1 test test 713 Mar 18 16:06 kthread.c
-rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
-rw-rw-r-- 1 test test 58 Mar 18 16:08 kthread.mod
-rw-rw-r-- 1 test test 1047 Mar 18 16:08 kthread.mod.c
-rw-rw-r-- 1 test test 96512 Mar 18 16:08 kthread.mod.o
-rw-rw-r-- 1 test test 74696 Mar 18 16:08 kthread.o
-rw-rw-r-- 1 test test 161 Mar 18 16:00 Makefile
-rw-rw-r-- 1 test test 58 Mar 18 16:08 modules.order
-rw-rw-r-- 1 test test 0 Mar 18 16:08 Module.symvers
Run modinfo command to get the information about the kernel module.
test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
filename: $HOME/kthread_examples/kthread.ko
description: Example of completion_initializer_onstack
author: Linux Usr
license: GPL
srcversion: 8D2147F67AB01CF0E482DAC
depends:
retpoline: Y
name: kthread
vermagic: 6.7.9 SMP preempt mod_unload modversions
insert the module using insmod command.
test@test-V520-15IKL:~$ sudo insmod ./kthread.ko
check if the module is loaded or not using lsmod command.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
kthread 16384 0
check if the thread is created or not using ps command.
test@test-V520-15IKL:~$ ps -N | grep completion_initializer_onstack
4967 ? 00:00:00 completion_initializer_onstack thread1 example
4968 ? 00:00:00 completion_initializer_onstack thread2 example
check for the kernel messages from init function and thread function once the module is loaded and thread is created.
test@test-V520-15IKL:~$ sudo dmesg
[ 2083.334632] inside thread init function
[ 2083.334752] successfully created kthread
[ 2083.334756] my_thread_fn1 execution
[ 2083.334916] successfully created kthread
[ 2084.345928] my_thread_fn1 execution
[ 2085.369973] my_thread_fn1 execution
[ 2086.398003] my_thread_fn1 execution
remove the module from kernel using rmmod command.
test@test-V520-15IKL:~$ sudo rmmod kthread
check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
test@test-V520-15IKL:~$
check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
test@test-V520-15IKL:~$ ps -N | grep completion_initializer_onstack
test@test-V520-15IKL:~$
Check for kernel messages from exit function using dmesg command.
test@test-V520-15IKL:~$ sudo dmesg
[ 2094.780840] inside kthread exit function
[ 2095.610379] my_thread_fn2 execution
[ 2096.634403] destroyed thread and completed task
In this example let’s see how to create completion variable using DECLARE_COMPLETION_ONSTACK and use it with kthread.
Include the follow header files(.h) to refer the API being used for the execution.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
#include <linux/delay.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 declare_completion_onstack");
Declare the thread variables which we are going to create and use in this example
static struct task_struct *my_thread1;
static struct task_struct *my_thread2;
DECLARE_COMPLETION_ONSTACK(thread_done);
Add the module init function which will be executed once we load the kernel module using insmod command.
static int __init declare_completion_onstack_init(void)
{
pr_info("Inside kthread init function\n");
thread_start();
return 0;
}
Add the thread start function called from module init function, which creates the thread, wakes it up and starts its execution.
void thread_start(void)
{
my_thread1 = kthread_run(my_thread_fn1,NULL,"declare_completion_onstack thread1 example");
if (IS_ERR(my_thread1))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
my_thread2 = kthread_run(my_thread_fn2,NULL,"declare_completion_onstack thread2 example");
if (IS_ERR(my_thread2))
pr_info("error creating in kthread\n");
else
pr_info("successfully created kthread\n");
}
Add the module exit function which will be executed once we unload the kernel module using rmmod command.
static void __exit declare_completion_onstack_exit(void)
{
pr_info("Inside kthread exit function\n");
thread_stop();
}
Add the thread stop function which is called from module exit function, which destroys the thread and stops the execution.
void thread_stop(void)
{
kthread_stop(my_thread2);
kthread_stop(my_thread1);
pr_info("destroyed thread and completed task\n");
}
Add the thread function API which will be called as soon as the kthread is created and is in running state.
static int my_thread_fn1(void *data)
{
while (!kthread_should_stop()) {
wait_for_completion(&thread_done);
pr_info("my_thread_fn1 execution\n");
msleep(1000);
}
return 0;
}
static int my_thread_fn2(void *data)
{
while(!kthread_should_stop()) {
pr_info("my_thread_fn2 execution\n");
msleep(1000);
}
complete(&thread_done);
return 0;
}
Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
module_init(declare_completion_onstack_init);
module_exit(declare_completion_onstack_exit);
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/module.h>
4#include <linux/kthread.h>
5#include <linux/completion.h>
6#include <linux/delay.h>
7
8MODULE_LICENSE("GPL");
9MODULE_DESCRIPTION("Example of declare_completion_onstack");
10MODULE_AUTHOR("linux usr");
11
12static struct task_struct *my_thread1;
13static struct task_struct *my_thread2;
14DECLARE_COMPLETION_ONSTACK(thread_done);
15
16/* my_thread_fn1 - executes when thread1 is created,
17 * waits for completion signal,
18 * prints a message and sleeps for 1000ms,
19 * stops when kthread_stop is called */
20
21static int my_thread_fn1(void *data)
22{
23 while (!kthread_should_stop()) {
24 wait_for_completion(&thread_done);
25 pr_info("my_thread_fn1 execution\n");
26 msleep(1000);
27 }
28 return 0;
29}
30
31/* my_thread_fn2 - executes when thread2 is created,
32 * prints a message and sleeps for 1000ms,
33 * sends completion signal,
34 * stops when kthread_stop is called */
35
36static int my_thread_fn2(void *data)
37{
38 while(!kthread_should_stop()) {
39 pr_info("my_thread_fn2 execution\n");
40 msleep(1000);
41 }
42 complete(&thread_done);
43 return 0;
44}
45
46/*thread_start - creates thread and starts execution */
47
48void thread_start(void)
49{
50 my_thread1 = kthread_run(my_thread_fn1,NULL,"declare_completion_onstack thread1 example");
51 if (IS_ERR(my_thread1))
52 pr_info("error creating in kthread\n");
53 else
54 pr_info("successfully created kthread\n");
55 my_thread2 = kthread_run(my_thread_fn2,NULL,"declare_completion_onstack thread2 example");
56 if (IS_ERR(my_thread2))
57 pr_info("error creating in kthread\n");
58 else
59 pr_info("successfully created kthread\n");
60}
61
62/* declare_completion_onstack_init - calls thread_start,
63 * executes when module is loaded */
64
65static int __init declare_completion_onstack_init(void)
66{
67 pr_info("inside thread init function\n");
68 thread_start();
69 return 0;
70}
71
72/* thread_stop - destroys thread and stops execution */
73
74void thread_stop(void)
75{
76 kthread_stop(my_thread2);
77 kthread_stop(my_thread1);
78 pr_info("destroyed thread and completed task\n");
79}
80
81/* declare_completion_onstack_exit - calls thread_stop,
82 * executes when module is unloaded */
83
84static void __exit declare_completion_onstack_exit(void)
85{
86 pr_info("inside kthread exit function\n");
87 thread_stop();
88}
89
90module_init(declare_completion_onstack_init);
91module_exit(declare_completion_onstack_exit);
1obj-m += kthread.o
2
3all:
4 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Run make to compile the kernel source and generate the .ko image.
make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
You are using: gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
CC [M] $HOME/kthread_examples/kthread.o
MODPOST $HOME/kthread_examples/Module.symvers
CC [M] $HOME/kthread_examples/kthread.mod.o
LD [M] $HOME/kthread_examples/kthread.ko
BTF [M] $HOME/kthread_examples/kthread.ko
Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
Check if the .ko is generated or not using ls command.
test@test-V520-15IKL:~$ ls -l
total 360
-rw-rw-r-- 1 test test 713 Mar 18 16:06 kthread.c
-rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
-rw-rw-r-- 1 test test 58 Mar 18 16:08 kthread.mod
-rw-rw-r-- 1 test test 1047 Mar 18 16:08 kthread.mod.c
-rw-rw-r-- 1 test test 96512 Mar 18 16:08 kthread.mod.o
-rw-rw-r-- 1 test test 74696 Mar 18 16:08 kthread.o
-rw-rw-r-- 1 test test 161 Mar 18 16:00 Makefile
-rw-rw-r-- 1 test test 58 Mar 18 16:08 modules.order
-rw-rw-r-- 1 test test 0 Mar 18 16:08 Module.symvers
Run modinfo command to get the information about the kernel module.
test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
filename: $HOME/kthread_examples/kthread.ko
description: Example of declare_completion_onstack
author: Linux Usr
license: GPL
srcversion: 8D2147F67AB01CF0E482DAC
depends:
retpoline: Y
name: kthread
vermagic: 6.7.9 SMP preempt mod_unload modversions
insert the module using insmod command.
test@test-V520-15IKL:~$ sudo insmod ./kthread.ko
check if the module is loaded or not using lsmod command.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
kthread 16384 0
check if the thread is created or not using ps command.
test@test-V520-15IKL:~$ ps -N | grep declare_completion_onstack
5863 ? 00:00:00 declare_completion_onstack thread1 example
5864 ? 00:00:00 declare_completion_onstack thread2 example
check for the kernel messages from init function and thread function once the module is loaded and thread is created.
test@test-V520-15IKL:~$ sudo dmesg
[ 4329.862271] inside thread init function
[ 4329.862331] successfully created kthread
[ 4329.862344] successfully created kthread
[ 4329.862345] my_thread_fn2 execution
[ 4330.886693] my_thread_fn2 execution
[ 4331.910730] my_thread_fn2 execution
remove the module from kernel using rmmod command.
test@test-V520-15IKL:~$ sudo rmmod kthread
check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
test@test-V520-15IKL:~$ sudo lsmod | grep kthread
test@test-V520-15IKL:~$
check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
test@test-V520-15IKL:~$ ps -N | grep declare_completion_onstack
test@test-V520-15IKL:~$
Check for kernel messages from exit function using dmesg command.
test@test-V520-15IKL:~$ sudo dmesg
[ 4340.770038] inside kthread exit function
[ 4341.127057] my_thread_fn1 execution
[ 4342.151095] destroyed thread and completed task
kthread API |
Learning |
---|---|
kthread_run |
Create and wake a thread |
kthread_should_stop |
To determine when thread should exit |
kthread_stop |
Stop a thread created by kthread_create |
Completion API |
Learning |
---|---|
DECLARE_COMPLETION |
Declare completion variable |
init_completion |
Initialize completion variable |
COMPLETION_INITIALIZER |
Initializes a completion structure |
COMPLETION_INITIALIZER_ONSTACK |
Initializes a completion structure on the kernel stack. |
DECLARE_COMPLETION_ONSTACK |
This macro declares and initializes a completion structure on the kernel stack. |
complete |
signals a signal thread waiting on this completion |
wait_for_completion |
waits for completion of task |
API |
Learning |
---|---|
MODULE_LICENSE |
Used to denote the license used in the kernel module |
MODULE_AUTHOR |
Used to mention the author of the kernel module |
MODULE_DESCRIPTION |
Used to describe what the module does |
IS_ERR |
Detects an error pointer |
wake_up_process |
wake up a specific process |
msleep |
will put in sleep for a certain amount of msecs time. |
module_init |
Driver initialization entry point |
module_exit |
Driver exit entry point |
pr_info |
Print an info-level message |