一、kthread_create & kthread_run

内核线程是工作在内核空间的,不属于任何一个进程,可以发生睡眠。可以用内核线程来进行一些循环的动作,比如通过循环拉高拉低gpio设置成方波输出的信号来模拟pwm信号,比如循环控制led的闪灯效果等等都可以使用到内核线程kthread_create接口函数。

内核线程的相关代码目录:

1
2
include/linux/kthread.h 
kernel/kthread.c

创建并启动一个内核线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
const char namefmt[], ...);

_/**_
_* kthread_run - create and wake a thread._
_* @threadfn: the function to run until signal_pending(current)._
_* @data: data ptr for @threadfn._
_* @namefmt: printf-style name for the thread._
_*_
_* Description: Convenient wrapper for kthread_create() followed by_
_* wake_up_process(). Returns the kthread or ERR_PTR(-ENOMEM)._
_*/_

#define kthread_run(threadfn, data, namefmt, ...) \
({ \
struct task_struct *__k \
= kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
if (!IS_ERR(__k)) \
wake_up_process(__k); \
__k; \
})

其中kthread_create()只是创建一个内核线程,但并没有启动,需要调用wake_up_process()来启动线程,所以内核又帮我们定义了一个宏kthread_run来帮我们搞定。内核线程创建成功后,会返回一个struct task_struct对象指针,方便我们的后续操作。

二、关闭一个内核线程

1
int kthread_stop(struct task_struct *k);

这个调用是会阻塞等待,直到内核线程k退出为止。原因为此函数内部会调用wait_for_completion()的方法(通过等待队列来实现),阻塞等待内核线程自身的退出。

三、内核线程函数,如何判断自身需要退出

1
int kthread_should_stop(void);

如果该内核线程已经被设置stop标志了,则会返回1,否则返回0。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>

#define ENTER() printk(KERN_DEBUG "%s() Enter", __func__)
#define EXIT() printk(KERN_DEBUG "%s() Exit", __func__)
#define ERR(fmt, args...) printk(KERN_ERR "%s()-%d: " fmt "\n", __func__, __LINE__, ##args)
#define DBG(fmt, args...) printk(KERN_DEBUG "%s()-%d: " fmt "\n", __func__, __LINE__, ##args)

static struct task_struct *test_kthread = NULL; //_定义一个_task_struct_结构体指针,赋值为_NULL

static int kthread_test_func(void) //定义一个内核线程要执行的函数
{
ENTER();
while (!kthread_should_stop()) {
DBG("kthread is running");
msleep(5000);
}

EXIT();
return 0;

}

static __init int kthread_test_init(void)
{
ENTER();
test_kthread = kthread_run(kthread_test_func, NULL, "kthread-test"); _//_创建线程_kthread-test_,并且运行
if (!test_kthread) {
ERR("kthread_run fail");
return -ECHILD;
}
EXIT();
return 0;
}

static __exit void kthread_test_exit(void)
{
ENTER();
if (test_kthread) {
DBG("kthread_stop");
kthread_stop(test_kthread); _//_停止内核线程
test_kthread = NULL;
}
EXIT();
}

module_init(kthread_test_init);
module_exit(kthread_test_exit);
MODULE_AUTHOR("czd,214241976@qq.com");
MODULE_DESCRIPTION("Device_create Driver");
MODULE_LICENSE("GPL");

描述文字
© 2024 mengchao666 开心地使用 Stellar 主题,星际地球第
收集了 62 颗星星 ✧ 共 83.3k 粒星尘,好像写完一本 鲁迅 的《呐喊》了啊