linux延时工作任务create_singlethread_workqueue函数的使用

Linux中Workqueue机制分析

软硬件协同设计是未来发展的主流,软硬件的界限越来越模糊,软硬件的设计思想是相通的,实现方法是各异的,实现的结果上当然也存在较大差别,因此,很有必要做好软硬件的协同设计。

什么是workqueue?Linux中的Workqueue机制就是为了简化内核线程的创建。通过调用workqueue的接口就能创建内核线程。并且可以根据当前系统CPU的个数创建线程的数量,使得线程处理的事务能够并行化。workqueue是内核中实现简单而有效的机制,他显然简化了内核daemon的创建,方便了用户的编程, Workqueue机制的实现Workqueue机制中定义了两个重要的数据结构,分析如下:

1、cpu_workqueue_struct结构。

该结构将CPU和内核线程进行了绑定。在创建workqueue的过程中,Linux根据当前系统CPU的个数创建cpu_workqueue_struct。在该结构主要维护了一个任务队列,以及内核线程需要睡眠的等待队列,另外还维护了一个任务上下文,即task_struct

2、work_struct结构是对任务的抽象。

在该结构中需要维护具体的任务方法,需要处理的数据,以及任务处理的时间。该结构定义如下:

struct work_struct {

         unsigned long pending;

         struct list_head entry;

         void (*func)(void *);

         void *data; 

         void *wq_data;  

         strut timer_list timer; 

             };  

     当用户调用workqueue的初始化接口create_workqueue或者create_singlethread_workqueue对workqueue队列进行初始化时,内核就开始为用户分配一个workqueue对象,并且将其链到一个全局的workqueue队列中。然后Linux根据当前CPU的情况,为workqueue对象分配与CPU个数相同的cpu_workqueue_struct对象,每个cpu_workqueue_struct对象都会存在一条任务队列。紧接着,Linux为每个cpu_workqueue_struct对象分配一个内核thread,即内核daemon去处理每个队列中的任务。至此,用户调用初始化接口将workqueue初始化完毕,返回workqueue的指针。

    在初始化workqueue过程中,内核需要初始化内核线程,注册的内核线程工作比较简单,就是不断的扫描对应cpu_workqueue_struct中的任务队列,从中获取一个有效任务,然后执行该任务。所以如果任务队列为空,那么内核daemon就在cpu_workqueue_struct中的等待队列上睡眠,直到有人唤醒daemon去处理任务队列。

    Workqueue初始化完毕之后,将任务运行的上下文环境构建起来了,但是具体还没有可执行的任务,所以,需要定义具体的work_struct对象。然后将work_struct加入到任务队列中,Linux会唤醒daemon去处理任务。

    上述描述的workqueue内核实现原理可以描述如下:

   在Workqueue机制中,提供了一个系统默认的workqueue队列——keventd_wq,这个队列是Linux系统在初始化的时候就创建的。用户可以直接初始化一个work_struct对象,然后在该队列中进行调度,使用更加方便。

Workqueue编程接口序号接口函数说明:

1、 create_workqueue 用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。

输入参数:@name:workqueue的名称

2、 create_singlethread_workqueue 用于创建workqueue,只创建一个内核线程。输入参数:@name:workqueue名称

3、 destroy_workqueue 释放workqueue队列。输入参数:@ workqueue_struct:需要释放的workqueue队列指针

4、 schedule_work 调度执行一个具体的任务,执行的任务将会被挂入Linux系统提供的workqueue——keventd_wq输入参数:@ work_struct:具体任务对象指针

5、 schedule_delayed_work 延迟一定时间去执行一个具体的任务,功能与schedule_work类似,多了一个延迟时间,输入参数:@work_struct:具体任务对象指针@delay:延迟时间

6、 queue_work 调度执行一个指定workqueue中的任务。输入参数:@ workqueue_struct:指定的workqueue指针@work_struct:具体任务对象指针

7、 queue_delayed_work 延迟调度执行一个指定workqueue中的任务,功能与queue_work类似,输入参数多了一个delay。

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 中,可以使用 `create_singlethread_workqueue()` 函数来创建一个单线程工作队列。 该函数的原型如下: ```c struct workqueue_struct *create_singlethread_workqueue(const char *name); ``` 其中,`name` 参数是工作队列的名称。该函数返回一个指向 `workqueue_struct` 结构体的指针,该结构体表示创建的工作队列。 下面是一个简单的示例,展示了如何使用 `create_singlethread_workqueue()` 函数创建一个单线程工作队列: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/workqueue.h> static struct workqueue_struct *workqueue; static void work_handler(struct work_struct *work) { printk(KERN_INFO "Hello, world!\n"); } static DECLARE_WORK(work, work_handler); static int __init my_module_init(void) { workqueue = create_singlethread_workqueue("my_workqueue"); if (!workqueue) { printk(KERN_ERR "Failed to create workqueue\n"); return -ENOMEM; } schedule_work(&work); return 0; } static void __exit my_module_exit(void) { flush_work(&work); destroy_workqueue(workqueue); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); ``` 在这个示例中,我们首先定义了一个工作处理函数 `work_handler`,它将打印一条消息。然后,我们使用 `DECLARE_WORK` 宏定义了一个工作项 `work`,并将其与 `work_handler` 函数关联起来。 在 `my_module_init` 函数中,我们调用 `create_singlethread_workqueue` 函数来创建一个名为 `my_workqueue` 的工作队列。然后,我们调用 `schedule_work` 函数将 `work` 工作项添加到工作队列中。 在 `my_module_exit` 函数中,我们使用 `flush_work` 函数等待工作项完成,并使用 `destroy_workqueue` 函数销毁工作队列。 需要注意的是,工作队列中的工作项是在内核线程中执行的,而不是在进程上下文中执行的。因此,在工作队列中执行的函数应该是内核级别的函数,而不是用户空间的函数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值