背景
Linux内核模块中有些时候需要启动一个thread来处理事务。本文提供一个模板,方便未来快速取用。
机制用法
头文件:
#include <linux/kthread.h>
接口:
static int my_kthread_func(void *data) {
int count = 0;
int *arg = (int *)data;
while (!thread_should_stop) {
//sleep
}
}
注册:
thread = kthread_run(my_kthread_func, &data, "my_kthread");
一般linux内核提供一个thread_should_stop来控制thread的开关。
另外就是在while循环中一定要sleep或者schedule否则会造成一直占用CPU,其他无法调度,甚至影响系统功能,包括网络和命令行。
代码模块
kthread_module.c:
#include <linux/module.h> // 必须包含,支持模块操作
#include <linux/kernel.h> // 必须包含,支持内核操作
#include <linux/init.h> // 必须包含,支持模块初始化和清理操作
#include <linux/kthread.h> // 必须包含,支持内核线程操作
#include <linux/delay.h>
MODULE_LICENSE("GPL"); // 模块许可证
MODULE_AUTHOR("Your Name"); // 作者名字
MODULE_DESCRIPTION("A simple kernel thread module with parameter"); // 模块描述
MODULE_VERSION("0.01"); // 模块版本
// 全局变量,用于停止内核线程
static int thread_should_stop = 0;
// 内核线程函数
static int my_kthread_func(void *data) {
int count = 0;
int *arg = (int *)data; // 将void*转换为int*类型,以便访问传递的参数
while (!thread_should_stop) {
printk(KERN_INFO "内核线程运行中,参数值为: %d\n", *arg);
usleep_range(1000 * 1000, 1000 * 1000);
count++;
if (count == 5) {
thread_should_stop = 1;
}
}
printk(KERN_INFO "内核线程停止\n");
return 0;
}
int data = 42; // 传递给内核线程的参数
// 初始化函数
static int __init kthread_module_init(void) {
struct task_struct *thread;
printk(KERN_INFO "内核模块加载成功\n");
// 创建内核线程
thread = kthread_run(my_kthread_func, &data, "my_kthread");
if (IS_ERR(thread)) {
printk(KERN_INFO "无法创建内核线程\n");
return PTR_ERR(thread);
}
return 0;
}
// 清理函数
static void __exit kthread_module_exit(void) {
printk(KERN_INFO "内核模块卸载\n");
thread_should_stop = 1; // 发送停止信号
// 这里需要停止并销毁内核线程,但示例中未包含这部分代码
// 通常需要保存线程的句柄并在适当的时候调用kthread_stop(thread)
}
module_init(kthread_module_init);
module_exit(kthread_module_exit);
Makefile:
obj-m += kthread_module.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
实操
- 编译:make
- 加载:insmod kthread_module.ko
- 卸载:rmmod kthread_module.ko
综述
Linux内核模块中有些时候需要启动一个thread来处理事务。本文提供一个模板,方便未来快速取用。未来可以把这个接口封装一个pthread的方式来操作,这样同一份代码在内核态和用户态都能使用。