温馨提示×

Linux驱动怎样实现多线程

小樊
43
2025-10-30 18:49:20
栏目: 智能运维

在Linux中,驱动程序通常运行在内核空间,而内核本身并不是多线程的。然而,Linux内核提供了内核线程(kthread)和内核同步原语(如自旋锁、信号量等)来实现并发操作。以下是在Linux驱动中实现多线程的一些方法:

1. 使用内核线程(kthread)

内核线程是由内核创建和管理的轻量级线程。你可以通过kthread_create函数创建一个内核线程,并通过kthread_run函数启动它。

#include <linux/kthread.h>
#include <linux/module.h>

static int my_thread_func(void *data)
{
    while (!kthread_should_stop()) {
        // 执行任务
        printk(KERN_INFO "My kernel thread is running\n");
        msleep(1000); // 休眠1秒
    }
    return 0;
}

static struct task_struct *my_thread;

static int __init my_driver_init(void)
{
    my_thread = kthread_create(my_thread_func, NULL, "my_kthread");
    if (IS_ERR(my_thread)) {
        printk(KERN_ALERT "Failed to create kernel thread\n");
        return PTR_ERR(my_thread);
    }
    wake_up_process(my_thread);
    return 0;
}

static void __exit my_driver_exit(void)
{
    if (my_thread) {
        kthread_stop(my_thread);
    }
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");

2. 使用工作队列(workqueue)

工作队列允许你在内核线程上下文中调度工作。你可以将任务添加到工作队列中,由内核线程异步执行。

#include <linux/workqueue.h>
#include <linux/module.h>

static struct work_struct my_work;

static void my_work_handler(struct work_struct *work)
{
    // 执行任务
    printk(KERN_INFO "Work queue task is running\n");
}

static int __init my_driver_init(void)
{
    INIT_WORK(&my_work, my_work_handler);
    schedule_work(&my_work);
    return 0;
}

static void __exit my_driver_exit(void)
{
    cancel_work_sync(&my_work);
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");

3. 使用自旋锁和信号量

为了保护共享数据,你需要使用自旋锁或信号量来同步对共享资源的访问。

自旋锁

#include <linux/spinlock.h>
#include <linux/module.h>

static DEFINE_SPINLOCK(my_lock);
int shared_data = 0;

static int my_thread_func(void *data)
{
    while (!kthread_should_stop()) {
        spin_lock(&my_lock);
        shared_data++;
        spin_unlock(&my_lock);
        printk(KERN_INFO "Shared data: %d\n", shared_data);
        msleep(1000);
    }
    return 0;
}

static struct task_struct *my_thread;

static int __init my_driver_init(void)
{
    my_thread = kthread_create(my_thread_func, NULL, "my_kthread");
    if (IS_ERR(my_thread)) {
        printk(KERN_ALERT "Failed to create kernel thread\n");
        return PTR_ERR(my_thread);
    }
    wake_up_process(my_thread);
    return 0;
}

static void __exit my_driver_exit(void)
{
    if (my_thread) {
        kthread_stop(my_thread);
    }
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");

信号量

#include <linux/semaphore.h>
#include <linux/module.h>

static DECLARE_SEMAPHORE(my_sem);
int shared_data = 0;

static int my_thread_func(void *data)
{
    while (!kthread_should_stop()) {
        down(&my_sem);
        shared_data++;
        up(&my_sem);
        printk(KERN_INFO "Shared data: %d\n", shared_data);
        msleep(1000);
    }
    return 0;
}

static struct task_struct *my_thread;

static int __init my_driver_init(void)
{
    my_thread = kthread_create(my_thread_func, NULL, "my_kthread");
    if (IS_ERR(my_thread)) {
        printk(KERN_ALERT "Failed to create kernel thread\n");
        return PTR_ERR(my_thread);
    }
    wake_up_process(my_thread);
    return 0;
}

static void __exit my_driver_exit(void)
{
    if (my_thread) {
        kthread_stop(my_thread);
    }
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");

总结

在Linux驱动中实现多线程主要通过内核线程、工作队列以及同步原语(如自旋锁和信号量)来实现。选择合适的方法取决于你的具体需求和应用场景。

0