Linux内核工作队列

来源:互联网 发布:网络管理考试题 编辑:程序博客网 时间:2024/04/30 12:59

工作队列意义

        在Linux2.6中引入了工作队列,它允许内核函数(工作)被激活,在稍后的时间里由一种叫做工作者线程的特殊线程来执行。这样的意义在于,某些内核函数可以在线程的上下文中执行,它可以被内核调度,同时也可被阻塞与睡眠。

        在中断的下半部,可以将任务提交到工作队列里,稍后由特殊的内核线程来调度其中的工作,这样下半部的任务就可以放到进程的上下文中来进行。如果中断下半部需要处理诸如访问磁盘数据块(可阻塞)这样的任务,那么唯一的方式就是在进程的上下文中运行。而这里的工作队列就提供一个很好的解决方法。

工作队列原理 

        工作队列由工作队里子系统来实现,工作队列子系统提供创建内核线程的接口,创建的线程(工作者线程)负责维护工作队列。可以再驱动中专门创建工作者线程来完成需要推后完成的工作,不过工作者子系统提供了一个缺省的工作者线程来处理这些工作。

        因此,工作者队列就变成了这样一种接口,把要推后的工作提交到工作队列,由工作者线程来负责解决工作队列里的工作。

        其中缺省的工作者线程叫做events/n,这里n是处理器号;每个处理器对应一个线程。一般情况下都采用缺省的工作者线程,内核开发者反对创建新的内核线程。

工作队列结构

        工作者线程组  workqueue_struct
        struct workqueue_struct {
            struct cpu_workqueue_struct cpu_wq[NR_CPUS];
        }      
        工作者线程      cpu_workqueue_struct
        struct cpu_workqueue_struct {
            struct list_head worklist;                    //工作队列
            struct workqueue_struct *wq;           //关联工作者线程组
            task_t *thread;                                     //关联线程
        }
        工作                  work_struct
        struct work_struct {
            atomic_long_t data;
            struct list_head  entry;
            work_func_t func; 
        }
        所有的工作者线程都是用普通内核线程实现的,都要执行worker_thread()线程函数。在工作者线程初始化完成后,会进入休眠。当有工作插入到队列时,工作者线程会被唤醒,以便去完成工作中的任务。

工作队列实现


        默认情况下,每个cpu都对应一个工作者线程,每个工作者线程多维护者一个工作队列。将需要的任务关联到work,提交work到工作队列即可唤醒工作者线程,在稍后工作者线程就会处理自己的工作队列中的任务。

工作队列使用

       创建工作

       DECLARE(name, void (*func), void *data);                                                         //编译时静态创建

       INIT_WORK(struct work_struct *work, void (*func) (void *), void *data);  //运行时根据指针动态创建

       其中工作处理函数原型为 void work_handler(void *data);

       调度工作

        schedule_work(&work);

        schedule_delayed_work(&work, delay);

        这里调度处理将work提交给缺省的events工作者线程,一旦工作者线程被唤醒,工作队列中的work就会被处理。

工作队列问题

        1.工作与可延时函数的区别


        2.为什么要用工作队列

           有些任务在下半部需要被调度,因此需要再进程上下文中执行,工作队列提供了这样一个功能允许内核函数被激活,稍后在工作者线程中被调度。 

0 0