精华内容
下载资源
问答
  • cancel_delayed_work和flush_scheduled_work

    千次阅读 2012-12-25 20:33:47
    那好,我们来看点具体的,比如935行,INIT_DELAYED_WORK().这是一张新面孔.同志们大概注意到了,在hub这个故事里,我们的讲解风格略有变化,对于那些旧的东西,对于那些在usb-storage里面讲过很多次的东西,我们不会再多提,...

    是不是觉得很玄?像思念一样玄?那好,我们来看点具体的,比如935,INIT_DELAYED_WORK().这是一张新面孔.同志们大概注意到了,hub这个故事里,我们的讲解风格略有变化,对于那些旧的东西,对于那些在usb-storage里面讲过很多次的东西,我们不会再多提,但是对于新鲜的东西,我们会花大把的笔墨去描摹.这样做的原因很简单,男人嘛,有几个不是喜新厌旧呢,要不然也不会结婚前觉得适合自己的女人很少,结婚后觉得适合自己的女人很多.

    所以本节我们就用大把的笔墨来讲述老百姓自己的故事.就讲这一行,935.INIT_DELAYED_WORK()是一个宏,我们给它传递了两个参数.&hub->ledsled_work.对设备驱动熟悉的人不会觉得INIT_DELAYED_WORK()很陌生,其实鸦片战争那会儿就有这个宏了,只不过从2.6.20的内核开始这个宏做了改变,原来这个宏是三个参数,后来改成了两个参数,所以经常在网上看见一些同志抱怨说最近某个模块编译失败了,说什么make的时候遇见这么一个错误:

    error: macro "INIT_DELAYED_WORK" passed 3 arguments, but takes just 2

    当然更为普遍的看到下面这个错误:

    error: macro "INIT_WORK" passed 3 arguments, but takes just 2

    于是就让我们来仔细看看INIT_WORKINIT_DELAYED_WORK.其实前者是后者的一个特例,它们涉及到的就是传说中的工作队列.这两个宏都定义于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)

    有时候特怀念谭浩强那本书里的那些例子程序,因为那些程序都特简单,不像现在看到的这些,动不动就是些复杂的函数复杂的数据结构复杂的宏,严重挫伤了我这样的有志青年的自信心.就比如眼下这几个宏吧,宏里边还是宏,一个套一个,不是说看不懂,因为要看懂也不难,一层一层展开,只不过确实没必要非得都看懂,现在这样一种朦胧美也许更美,有那功夫把这些都展开我还不如去认认真真学习三个代表呢.总之,关于工作队列,就这么说吧,Linux内核实现了一个内核线程,直观一点,ps命令看一下您的进程,

    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

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

    1 S     0     8     1  0 -40   - -     0 migrat ?        00:00:00 migration/3

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

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

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

    1 S     0    12     1  0 -40   - -     0 migrat ?        00:00:00 migration/5

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

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

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

    1 S     0    16     1  0 -40   - -     0 migrat ?        00:00:00 migration/7

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

    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的线程.哥们儿这里Dell PowerEdge 2950的机器,8个处理器,所以就是events/0events/7.

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

    就比如这里,如果我们将来某个时刻希望能够调用led_work()这么一个我们自己写的函数,那么我们所要做的就是利用工作队列.如何利用呢?第一步就是使用INIT_WORK()或者INIT_DELAYED_WORK()来初始化这么一个工作,或者叫任务,初始化了之后,将来如果咱们希望调用这个led_work()函数,那么咱们只要用一句schedule_work()或者schedule_delayed_work()就可以了,特别的,咱们这里使用的是INIT_DELAYED_WORK(),那么之后我们就会调用schedule_delayed_work(),这俩是一对.它表示,您希望经过一段延时然后再执行某个函数,所以,咱们今后会见到schedule_delayed_work()这个函数的,而它所需要的参数,一个就是咱们这里的&hub->leds,另一个就是具体自己需要的延时.&hub->leds是什么呢?struct usb_hub中的成员,struct delayed_work leds,专门用于延时工作的,再看struct delayed_work,这个结构体定义于include/linux/workqueue.h:

         35 struct delayed_work {

         36         struct work_struct work;

         37         struct timer_list timer;

         38 };

    其实就是一个struct work_struct和一个timer_list,前者是为了往工作队列里加入自己的工作,后者是为了能够实现延时执行,咱们把话说得更明白一点,您看那些events线程,它们对应一个结构体,struct workqueue_struct,也就是说它们维护着一个队列,完了您要是想利用工作队列这么一个机制呢,您可以自己创建一个队列,也可以直接使用events对应的这个队列,对于大多数情况来说,都是选择了events对应的这个队列,也就是说大家都共用这么一个队列,怎么用呢?先初始化,比如调用INIT_DELAYED_WORK(),这么一初始化吧,实际上就是为一个struct work_struct结构体绑定一个函数,就比如咱们这里的两个参数,&hub->ledsled_work()的关系,就最终让hub_leds这个struct work_struct结构体和函数led_work()相绑定了起来,您问怎么绑定的?您瞧,struct work_struct也是定义于include/linux/workqueue.h:

         24 struct work_struct {

         25         atomic_long_t data;

         26 #define WORK_STRUCT_PENDING 0           /* T if work item pending execution */

         27 #define WORK_STRUCT_FLAG_MASK (3UL)

         28 #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)

         29         struct list_head entry;

         30         work_func_t func;

         31 };

    瞅见最后这个成员func了吗,初始化的目的就是让func指向led_work(),这就是绑定,所以以后咱们调用schedule_delayed_work()的时候,咱们只要传递struct work_struct的结构体参数即可,不用再每次都把led_work()这个函数名也给传递一次,一旦绑定,人家就知道了,对于led_work(),那她就嫁鸡随鸡,嫁狗随狗,嫁混蛋随混蛋了.您大概还有一个疑问,为什么只要这里初始化好了,到时候调用schedule_delayed_work()就可以了呢?事实上,events这么一个线程吧,它其实和hub的内核线程一样,有事情就处理,没事情就睡眠,也是一个死循环,schedule_delayed_work()的作用就是唤醒这个线程,确切的说,是先把自己的这个struct work_struct插入workqueue_struct这个队列里,然后唤醒昏睡中的events.然后events就会去处理,您要是有延时,那么它就给您安排延时以后执行,您要是没有延时,或者您设了延时为0,那好,那就赶紧给您执行.咱这里不是讲了两个宏吗,一个INIT_WORK(),一个INIT_DELAYED_WORK(),后者就是专门用于可以有延时的,而前者就是没有延时的,这里咱们调用的是INIT_DELAYED_WORK(),不过您别美,过一会您会看见INIT_WORK()也被使用了,因为咱们hub驱动中还有另一个地方也想利用工作队列这么一个机制,而它不需要延时,所以就使用INIT_WORK()进行初始化,然后在需要调用相关函数的时候调用schedule_work()即可.此乃后话,暂且不表.

    基本上这一节咱们就是介绍了Linux内核中工作队列机制提供的接口,两对函数INIT_DELAYED_WORK()schedule_delayed_work(),INIT_WORK()schedule_work().

    关于工作队列机制,咱们还会用到另外两个函数,它们是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(),给您调用,以消除所谓的竞争条件,其实说竞争太专业了点,说白了就是防止混乱吧.

    Ok,关于这些接口就讲到这里,日后咱们自然会在hub驱动里见到这些接口函数是如何被使用的.到那时候再来看.这就是蝴蝶效应.当我们看到INIT_WORK/INIT_DELAYED_WORK()的时候,我们是没法预测未来会发生什么的.所以我们只能拭目以待.又想起了那句老话,大学生活就像被强奸,如果不能反抗,那就只能静静的去享受它.

     

    展开全文
  • 是不是觉得很玄?...那好,我们来看点具体的,比如935行,INIT_DELAYED_WORK().这是一张新面孔.同志们大概注意到了,在hub这个故事里,我们的讲解风格略有变化,对于那些旧的东西,对于那些在usb-storage里面...

    转自:http://blog.chinaunix.net/uid-9688646-id-4052595.html

    是不是觉得很玄?像思念一样玄?那好,我们来看点具体的,比如935行,INIT_DELAYED_WORK().这是一张新面孔.同志们大概注意到了,在hub这个故事里,我们的讲解风格略有变化,对于那些旧的东西,对于那些在usb-storage里面讲过很多次的东西,我们不会再多提,但是对于新鲜的东西,我们会花大把的笔墨去描摹.这样做的原因很简单,男人嘛,有几个不是喜新厌旧呢,要不然也不会结婚前觉得适合自己的女人很少,结婚后觉得适合自己的女人很多.

    所以本节我们就用大把的笔墨来讲述老百姓自己的故事.就讲这一行,935行.INIT_DELAYED_WORK()是一个宏,我们给它传递了两个参数.&hub->leds和led_work.对设备驱动熟悉的人不会觉得INIT_DELAYED_WORK()很陌生,其实鸦片战争那会儿就有这个宏了,只不过从2.6.20的内核开始这个宏做了改变,原来这个宏是三个参数,后来改成了两个参数,所以经常在网上看见一些同志抱怨说最近某个模块编译失败了,说什么make的时候遇见这么一个错误:

    error: macro "INIT_DELAYED_WORK" passed 3 arguments, but takes just 2

    当然更为普遍的看到下面这个错误:

    error: macro "INIT_WORK" passed 3 arguments, but takes just 2

    于是就让我们来仔细看看INIT_WORK和INIT_DELAYED_WORK.其实前者是后者的一个特例,它们涉及到的就是传说中的工作队列.这两个宏都定义于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)

    有时候特怀念谭浩强那本书里的那些例子程序,因为那些程序都特简单,不像现在看到的这些,动不动就是些复杂的函数复杂的数据结构复杂的宏,严重挫伤了我这样的有志青年的自信心.就比如眼下这几个宏吧,宏里边还是宏,一个套一个,不是说看不懂,因为要看懂也不难,一层一层展开,只不过确实没必要非得都看懂,现在这样一种朦胧美也许更美,有那功夫把这些都展开我还不如去认认真真学习三个代表呢.总之,关于工作队列,就这么说吧,Linux内核实现了一个内核线程,直观一点,ps命令看一下您的进程,

    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

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

    1 S     0     8     1  0 -40   - -     0 migrat ?        00:00:00 migration/3

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

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

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

    1 S     0    12     1  0 -40   - -     0 migrat ?        00:00:00 migration/5

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

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

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

    1 S     0    16     1  0 -40   - -     0 migrat ?        00:00:00 migration/7

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

    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/0到events/7,0啊7啊这些都是处理器的编号,每个处理器对应其中的一个线程.要是您的计算机只有一个处理器,那么您只能看到一个这样的线程,events/0,您要是双处理器那您就会看到多出一个events/1的线程.哥们儿这里Dell PowerEdge 2950的机器,8个处理器,所以就是events/0到events/7了.

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

    就比如这里,如果我们将来某个时刻希望能够调用led_work()这么一个我们自己写的函数,那么我们所要做的就是利用工作队列.如何利用呢?第一步就是使用INIT_WORK()或者INIT_DELAYED_WORK()来初始化这么一个工作,或者叫任务,初始化了之后,将来如果咱们希望调用这个led_work()函数,那么咱们只要用一句schedule_work()或者schedule_delayed_work()就可以了,特别的,咱们这里使用的是INIT_DELAYED_WORK(),那么之后我们就会调用schedule_delayed_work(),这俩是一对.它表示,您希望经过一段延时然后再执行某个函数,所以,咱们今后会见到schedule_delayed_work()这个函数的,而它所需要的参数,一个就是咱们这里的&hub->leds,另一个就是具体自己需要的延时.&hub->leds是什么呢?struct usb_hub中的成员,struct delayed_work leds,专门用于延时工作的,再看struct delayed_work,这个结构体定义于include/linux/workqueue.h:

         35 struct delayed_work {

         36         struct work_struct work;

         37         struct timer_list timer;

         38 };

    其实就是一个struct work_struct和一个timer_list,前者是为了往工作队列里加入自己的工作,后者是为了能够实现延时执行,咱们把话说得更明白一点,您看那些events线程,它们对应一个结构体,struct workqueue_struct,也就是说它们维护着一个队列,完了您要是想利用工作队列这么一个机制呢,您可以自己创建一个队列,也可以直接使用events对应的这个队列,对于大多数情况来说,都是选择了events对应的这个队列,也就是说大家都共用这么一个队列,怎么用呢?先初始化,比如调用INIT_DELAYED_WORK(),这么一初始化吧,实际上就是为一个struct work_struct结构体绑定一个函数,就比如咱们这里的两个参数,&hub->leds和led_work()的关系,就最终让hub_leds这个struct work_struct结构体和函数led_work()相绑定了起来,您问怎么绑定的?您瞧,struct work_struct也是定义于include/linux/workqueue.h:

         24 struct work_struct {

         25         atomic_long_t data;

         26 #define WORK_STRUCT_PENDING 0           /* T if work item pending execution */

         27 #define WORK_STRUCT_FLAG_MASK (3UL)

         28 #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)

         29         struct list_head entry;

         30         work_func_t func;

         31 };

    瞅见最后这个成员func了吗,初始化的目的就是让func指向led_work(),这就是绑定,所以以后咱们调用schedule_delayed_work()的时候,咱们只要传递struct work_struct的结构体参数即可,不用再每次都把led_work()这个函数名也给传递一次,一旦绑定,人家就知道了,对于led_work(),那她就嫁鸡随鸡,嫁狗随狗,嫁混蛋随混蛋了.您大概还有一个疑问,为什么只要这里初始化好了,到时候调用schedule_delayed_work()就可以了呢?事实上,events这么一个线程吧,它其实和hub的内核线程一样,有事情就处理,没事情就睡眠,也是一个死循环,而schedule_delayed_work()的作用就是唤醒这个线程,确切的说,是先把自己的这个struct work_struct插入workqueue_struct这个队列里,然后唤醒昏睡中的events.然后events就会去处理,您要是有延时,那么它就给您安排延时以后执行,您要是没有延时,或者您设了延时为0,那好,那就赶紧给您执行.咱这里不是讲了两个宏吗,一个INIT_WORK(),一个INIT_DELAYED_WORK(),后者就是专门用于可以有延时的,而前者就是没有延时的,这里咱们调用的是INIT_DELAYED_WORK(),不过您别美,过一会您会看见INIT_WORK()也被使用了,因为咱们hub驱动中还有另一个地方也想利用工作队列这么一个机制,而它不需要延时,所以就使用INIT_WORK()进行初始化,然后在需要调用相关函数的时候调用schedule_work()即可.此乃后话,暂且不表.

    基本上这一节咱们就是介绍了Linux内核中工作队列机制提供的接口,两对函数INIT_DELAYED_WORK()对schedule_delayed_work(),INIT_WORK()对schedule_work().

    关于工作队列机制,咱们还会用到另外两个函数,它们是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(),给您调用,以消除所谓的竞争条件,其实说竞争太专业了点,说白了就是防止混乱吧.

    Ok,关于这些接口就讲到这里,日后咱们自然会在hub驱动里见到这些接口函数是如何被使用的.到那时候再来看.这就是蝴蝶效应.当我们看到INIT_WORK/INIT_DELAYED_WORK()的时候,我们是没法预测未来会发生什么的.所以我们只能拭目以待.又想起了那句老话,大学生活就像被强奸,如果不能反抗,那就只能静静的去享受它.










    本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/5037172.html,如需转载请自行联系原作者


    展开全文
  • Cloning scheduled downtime does not work. <h2>Expected Behavior <p>Click on clone link and as in case of other director objects a cloning window should be displayed. <h2>Current Behavior <p>Clicking ...
  • <div><p>Hello, I created a task to run each 15 minutes via Django admin form, but it runs each minute. the setting is like this: <pre><code> py Q_CLUSTER = { 'name': '...
  • <div><p>A scheduled 'update status' activity on twitter channel does not post something to the actual twitter channel.</p><p>该提问来源于开源项目:CampaignChain/campaignchain</p></div>
  • 报表订阅在一段日期以后突然不工作了。 原因是用户的账号是跟AD账号捆绑的,而公司每两个月都强制需要更新一...而cognos schedule依赖的凭证并不会一起更新。 解决方法是,到用户首选项当中renew the credentials. ...

    报表订阅在一段日期以后突然不工作了。

    原因是用户的账号是跟AD账号捆绑的,而公司每两个月都强制需要更新一次AD账户的密码。而cognos schedule依赖的凭证并不会一起更新。

    解决方法是,到用户首选项当中renew the credentials.



    一劳永逸的解决方法是,新建一个公共sender账号,专门用于订阅报表。并把它的密码设置为永不过期。


    展开全文
  • <p>Question: how is it supposed to work? I think the documentation on this is missing. <h2>Description <ul><li>I'm running on <code>spring-boot:1.4.6</code>.</li><li>I have only <code>tracer-...
  • The scheduled date/time is not effected. <p>Scenario: I daily receive a news paper at 8:00. In my daily schedule I will read this after 18:00. I would like to enter this as: task add Read news paper...
  • My WiFi router is configured to scheduled reboot every night while I sleep, but it seems that this application cannot work in such scenarios, because every morning I take my phone and find out that ...
  • <p>Fix bug with scheduled note working in the trash. <p>How to repeat bug: 1. Make scheduled note with cron; 2. Move it to trash; 3. Restart zeppelin. <h3>What type of PR is it? <p>Bug Fix <h3>What is...
  • <div><p>When attempting to export messages from admin app, if any of the reports to be exported has scheduled tasks whose messages have not yet been generated, API throws an error and the resulting ...
  • <div><p>after refreshing method is not working in 1.4.2 release</p><p>该提问来源于开源项目:spring-cloud/spring-cloud-commons</p></div>
  • - make FUNC(scriptedExplosive) work in scheduled env - add option to directly add one explosive as object for convenience <p>the alternative syntax can do stuff like: <code>_bomb call ace_explosives_...
  • <div><ul>[X] Steps to reproduce provided</li><li>[x] Example that reproduces the problem uploaded to Github</li><li>[X] Full description of the issue provided (see below)</li></ul> ...
  • This causes integration and acceptance tests to fail when a component schedules work on a queue (e.g., <code>afterRender). <p>I've create a simple use case to demonstrate the issue. It consists ...
  • <h4>Steps to reproduce the issue <p>Enable Jetpack Publicize to Facebook, Twitter Create a post to be published in the future <h4>What I expected <p>Post gets published, new items appear on Twitter ...
  • <div><p>If cron interval is configured by a config property, scheduling stops working (invoking) after /refresh is called on that property. <p>Tested up to spring-boot-starter-parent 1.5.2.RELEASE and...
  • <div><p>Partially addresses problem from #1439. <p>fyi -donnelly ptal <p>This change is ...该提问来源于开源项目:kubernetes/website</p></div>
  • <div><p>does not work IScheduledExecutorService scheduleAtFixedRate even when I put SpringManagedContext to configure Hazelcast, <p>So instead of just doing attachHazelcastInstance(command); inside ...
  • <div><p>This of course also applies to the skip-pattern. <p>Versions: 2.1.7.RELEASE of sleuth-core and spring boot 2.1.3 <p>This happens tobecause operations are run from the "...
  • <div><h3>Steps to reproduce <ol><li>Configure instant upload of camera images</li><li>take a photo few times</li></ol> <h3>Expected behaviour <ul><li>Instant upload should be triggered shortly after ...
  • <div><p>From #22901</p><p>该提问来源于开源项目:openshift/openshift-docs</p></div>
  • The bulk edit flag options are not working on scheduled transactions. When attempting to set or clear flags, nothing happens. No error is shown, it just doesn't do anything. Works fine for ...
  • <p>Toggle Scheduled and Reconciled Transaction Buttons <h1>System Settings (Required) <ul><li>ToolKit Version: 2.3.0</li><li>Operating System (Mac/Windows/Etc): Windows 10</li><li>Browser (Chrome/Fire...
  • <div><p>GitHub Issue (if applicable): #1677 <h4>Explanation of Bugfix/Feature/Modification: <p>A YNAB change broke this feature. Just modernized the feature itself whilst fixing it.</p><p>该提问来源...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,164
精华内容 865
关键字:

scheduledwork