Linux内核线程kthread用法示例
--发布于 2025-09-16 21:34:10
在Ubuntu 22.04 LTS(内核版本 5.15.0-153-generic)上测试通过。
kthread_demo.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h> // 包含kthread_run、kthread_stop等函数
#include <linux/delay.h> // 包含msleep_interruptible等延时函数
#include <linux/completion.h>// 用于同步(可选,视需求)
#include <linux/signal.h> // 用于allow_signal函数
// 定义线程私有数据结构(可选,用于传递参数)
struct my_thread_data {
int count; // 计数器
struct completion exit; // 用于通知线程退出完成(可选)
};
// 内核线程的主函数(必须返回int,参数为void*)
static int my_kthread_func(void *data)
{
struct my_thread_data *thread_data = (struct my_thread_data *)data;
allow_signal(SIGKILL); // 允许接收SIGKILL信号(可选,用于强制终止)
while (!kthread_should_stop()) { // 核心循环条件:检查是否需要停止
printk(KERN_INFO "Kernel thread: count = %d\n", thread_data->count++);
// 休眠1秒(可被信号中断)
// 若使用msleep(1000)会忙等待,msleep_interruptible()更高效
if (msleep_interruptible(1000)) {
printk(KERN_INFO "Thread interrupted by signal, exiting...\n");
break; // 被信号中断时退出循环
}
}
printk(KERN_INFO "Kernel thread exiting, final count = %d\n", thread_data->count);
complete(&thread_data->exit); // 通知等待者线程已退出(可选)
return 0;
}
static struct task_struct *my_thread = NULL; // 保存线程描述符
static struct my_thread_data thread_data; // 线程私有数据
// 模块初始化函数(加载模块时调用)
static int __init my_module_init(void)
{
printk(KERN_INFO "Loading my module...\n");
// 初始化完成量(可选,若需要同步退出)
init_completion(&thread_data.exit);
// 创建并启动内核线程:
// 参数1:线程名称(用于ps查看)
// 参数2:传递给线程函数的参数(这里是thread_data的指针)
my_thread = kthread_run(my_kthread_func, &thread_data, "my_kthread");
if (IS_ERR(my_thread)) {
printk(KERN_ERR "Failed to create kernel thread: %ld\n", PTR_ERR(my_thread));
return PTR_ERR(my_thread);
}
printk(KERN_INFO "Kernel thread created successfully, PID = %d\n", task_pid_nr(my_thread));
return 0;
}
// 模块退出函数(卸载模块时调用)
static void __exit my_module_exit(void)
{
printk(KERN_INFO "Unloading my module...\n");
if (my_thread) {
// 停止线程(会触发kthread_should_stop()返回true)
kthread_stop(my_thread);
// 等待线程实际退出(可选,但推荐,避免模块卸载时线程仍在运行)
wait_for_completion(&thread_data.exit);
printk(KERN_INFO "Kernel thread stopped\n");
}
printk(KERN_INFO "Module unloaded\n");
}
// 注册模块初始化和退出函数
module_init(my_module_init);
module_exit(my_module_exit);
// 模块元信息
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple example of kthread_run()");
Makefile文件
CONFIG_MODULE_SIG=n
obj-m := kthread_demo.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
查看日志
tail -f /var/log/kern.log
加载模块
sudo insmod kthread_demo.ko
输出日志
Sep 16 21:12:31 zwm3222735 kernel: [86299.599938] Loading my module...
Sep 16 21:12:31 zwm3222735 kernel: [86299.600048] Kernel thread created successfully, PID = 9957
Sep 16 21:12:31 zwm3222735 kernel: [86299.600224] Kernel thread: count = 0
Sep 16 21:12:32 zwm3222735 kernel: [86300.621069] Kernel thread: count = 1
Sep 16 21:12:33 zwm3222735 kernel: [86301.645100] Kernel thread: count = 2
Sep 16 21:12:34 zwm3222735 kernel: [86302.669096] Kernel thread: count = 3
Sep 16 21:12:35 zwm3222735 kernel: [86303.693124] Kernel thread: count = 4
Sep 16 21:12:36 zwm3222735 kernel: [86304.717041] Kernel thread: count = 5
Sep 16 21:12:37 zwm3222735 kernel: [86305.741109] Kernel thread: count = 6
Sep 16 21:12:39 zwm3222735 kernel: [86306.765253] Kernel thread: count = 7
卸载模块
sudo rmmod kthread_demo
输出日志
Sep 16 21:16:17 zwm3222735 kernel: [86524.877048] Kernel thread: count = 220
Sep 16 21:16:18 zwm3222735 kernel: [86525.901067] Kernel thread: count = 221
Sep 16 21:16:19 zwm3222735 kernel: [86526.925052] Kernel thread: count = 222
Sep 16 21:16:20 zwm3222735 kernel: [86527.949034] Kernel thread: count = 223
Sep 16 21:16:21 zwm3222735 kernel: [86528.973025] Kernel thread: count = 224
Sep 16 21:16:21 zwm3222735 kernel: [86529.680844] Unloading my module...
Sep 16 21:16:22 zwm3222735 kernel: [86529.997195] Kernel thread exiting, final count = 225
Sep 16 21:16:22 zwm3222735 kernel: [86529.997337] Kernel thread stopped
Sep 16 21:16:22 zwm3222735 kernel: [86529.997338] Module unloaded
--更新于 2025-09-16 21:36:34