Heng30的博客
搜索 分类 关于 订阅

如何在Linux驱动中创建线程?

2025-03-03

在Linux内核驱动中创建线程是一个很常见的功能。下面的例子使用两种方法来创建线程。其中kthread_run函数不需要创建线程,直接就让线程运行起来,比较方便。

实例代码

// simple_cdev.c

#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/sched.h>

static int t1 = 1, t2 = 2;
static struct task_struct *kthread_1 = NULL;
static struct task_struct *kthread_2 = NULL;
static struct completion thread_exit;

static int _thread_cb(void *data) {
    unsigned int cnt = 0;
    int tid = *(int *)data;

    while (!kthread_should_stop()) {
        pr_info("Thread %d is running. Count = %u", tid, cnt++);
        msleep(tid * 1000);
    }

    pr_info("Thread %d stopped", tid);
    complete(&thread_exit);
    return 0;
}

static int __init simple_cdev_init(void) {
    pr_info("simple_cdev_init\n");

    init_completion(&thread_exit);

    kthread_1 = kthread_create(_thread_cb, &t1, "kthread_1");
    if (!kthread_1) {
        pr_err("kthread_create thread_1 error");
        return -EIO;
    }
    wake_up_process(kthread_1);

    kthread_2 = kthread_run(_thread_cb, &t2, "kthread_2");
    if (!kthread_2) {
        pr_err("kthread_create thread_2 error");
        kthread_stop(kthread_1);
        return -EIO;
    }

    return 0;
}

static void __exit simple_cdev_exit(void) {
    pr_info("simple_cdev_exit\n");

    kthread_stop(kthread_1);
    kthread_stop(kthread_2);

    wait_for_completion(&thread_exit);
    wait_for_completion(&thread_exit);
}

module_init(simple_cdev_init);
module_exit(simple_cdev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple_cdev kernel module");

Makefile编译脚本

#!/bin/sh

top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build

obj-m += simple_cdev.o

all:
        make -C $(kernel-dir) modules M=$(top-dir)

clean:
        rm -f *.o *.ko *.mod *.mod.c *.order *.symvers
        make -C $(kernel-dir) clean m=$(top-dir)

测试

  • 安装驱动:insmod simple_cdev.ko

  • 移除驱动:rmmod simple_cdev.ko

  • dmesg查看输出信息:

[51160.021722] simple_cdev_init
[51160.021807] Thread 1 is running. Count = 0
[51160.021854] Thread 2 is running. Count = 0
[51161.082695] Thread 1 is running. Count = 1
[51162.043351] Thread 2 is running. Count = 1
[51162.121245] Thread 1 is running. Count = 2
[51163.132780] Thread 1 is running. Count = 3
[51164.099720] Thread 2 is running. Count = 2
[51164.155951] Thread 1 is running. Count = 4
[51165.183403] Thread 1 is running. Count = 5
[51165.792184] simple_cdev_exit
[51166.153078] Thread 2 is running. Count = 3
[51166.193663] Thread 1 stopped
[51168.223015] Thread 2 stopped