INIT_WORK和INIT_DELAYED_WORK

来源:互联网 发布:php编辑器代码 编辑:程序博客网 时间:2024/05/29 08:48

http://blog.csdn.net/bingqingsuimeng/article/details/7891157?readlog

这两个宏都定义于include/linux/workqueue.h:

     79 #define INIT_WORK(_work, _func)                                         /

     80         do {                                                            /

     81                 (_work)->data = (atomic_long_t) WORK_DATA_INIT();       /

     82                 INIT_LIST_HEAD(&(_work)->entry);                        /

     83                 PREPARE_WORK((_work), (_func));                         /

     84         } while (0)

     85

     86 #define INIT_DELAYED_WORK(_work, _func)                         /

     87         do {                                                    /

     88                 INIT_WORK(&(_work)->work, (_func));             /

     89                 init_timer(&(_work)->timer);                    /

     90         } while (0)


localhost:/usr/src/linux-2.6.22.1/drivers/usb/core # ps -el

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

4 S     0     1     0  0  76   0 -   195 -      ?        00:00:02 init

1 S     0     2     1  0 -40   - -     0 migrat ?        00:00:00 migration/0

1 S     0     3     1  0  94  19 -     0 ksofti ?        00:00:00 ksoftirqd/0

1 S     0     4     1  0 -40   - -     0 migrat ?        00:00:00 migration/1

1 S     0     5     1  0  94  19 -     0 ksofti ?        00:00:00 ksoftirqd/1

1 S     0     6     1  0 -40   - -     0 migrat ?        00:00:00 migration/2

5 S     0    18     1  0  70  -5 -     0 worker ?        00:00:00 events/0

1 S     0    19     1  0  70  -5 -     0 worker ?        00:00:00 events/1

5 S     0    20     1  0  70  -5 -     0 worker ?        00:00:00 events/2

5 S     0    21     1  0  70  -5 -     0 worker ?        00:00:00 events/3

5 S     0    22     1  0  70  -5 -     0 worker ?        00:00:00 events/4

1 S     0    23     1  0  70  -5 -     0 worker ?        00:00:00 events/5

5 S     0    24     1  0  70  -5 -     0 worker ?        00:00:00 events/6

5 S     0    25     1  0  70  -5 -     0 worker ?        00:00:00 events/7


events/0events/7,07啊这些都是处理器的编号,每个处理器对应其中的一个线程.要是您的计算机只有一个处理器,那么您只能看到一个这样的线程,events/0,您要是双处理器那您就会看到多出一个events/1的线程

这些events被叫做工作者线程,或者说worker threads,更确切的说,这些应该是缺省的工作者线程.而与工作者线程相关的一个概念就是工作队列,或者叫work queue.工作队列的作用就是把工作推后,交由一个内核线程去执行,更直接的说就是如果您写了一个函数,而您现在不想马上执行它,您想在将来某个时刻去执行它,那您用工作队列准没错.您大概会想到中断也是这样,提供一个中断服务函数,在发生中断的时候去执行,没错,和中断相比,工作队列最大的好处就是可以调度可以睡眠,灵活性更好.


关于工作队列机制,咱们还会用到另外两个函数,它们是cancel_delayed_work(struct delayed_work *work)flush_scheduled_work().其中cancel_delayed_work()的意思不言自明,对一个延迟执行的工作来说,这个函数的作用是在这个工作还未执行的时候就把它给取消掉.


flush_scheduled_work()的作用,是为了防止有竞争条件的出现,您要是对竞争条件不是很明白,那也不要紧,反正基本上每次cancel_delayed_work之后您都得调用flush_scheduled_work()这个函数,特别是对于内核模块,如果一个模块使用了工作队列机制,并且利用了events这个缺省队列,那么在卸载这个模块之前,您必须得调用这个函数,这叫做刷新一个工作队列,也就是说,函数会一直等待,直到队列中所有对象都被执行以后才返回.当然,在等待的过程中,这个函数可以进入睡眠.反正刷新完了之后,这个函数会被唤醒,然后它就返回了.关于这里这个竞争,可以这样理解,events对应的这个队列,人家本来是按部就班的执行,一个一个来,您要是突然把您的模块给卸载了,或者说你把你的那个工作从工作队列里取出来了,events作为队列管理者,它可能根本就不知道,比如说它先想好了,下午3点执行队列里的第N个成员,可是您突然把第N-1个成员给取走了,那您说这是不是得出错?所以,为了防止您这种唯恐天下不乱的人做出冒天下之大不韪的事情来,提供了一个函数,flush_scheduled_work(),给您调用,以消除所谓的竞争条件,其实说竞争太专业了点,说白了就是防止混乱吧.




原创粉丝点击