伟明部落格

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