wait

    xiaoxiao2021-12-14  20

    1. 关于 wait_event_interruptible() 和 wake_up()的使用       读一下wait_event_interruptible()的源码,不难发现这个函数先将  当前进程的状态设置成TASK_INTERRUPTIBLE,然后调用schedule(),  而schedule()会将位于TASK_INTERRUPTIBLE状态的当前进程从runqueue  队列中删除。从runqueue队列中删除的结果是,当前这个进程将不再参  与调度,除非通过其他函数将这个进程重新放入这个runqueue队列中,  这就是wake_up()的作用了。     由于这一段代码位于一个由condition控制的for(;;)循环中,所以当由  shedule()返回时(当然是被wake_up之后,通过其他进程的schedule()而  再次调度本进程),如果条件condition不满足,本进程将自动再次被设  置为TASK_INTERRUPTIBLE状态,接下来执行schedule()的结果是再次被  从runqueue队列中删除。这时候就需要再次通过wake_up重新添加到  runqueue队列中。     如此反复,直到condition为真的时候被wake_up.     可见,成功地唤醒一个被wait_event_interruptible()的进程,需要满足:        在 1)condition为真的前提下,2) 调用wake_up()。  所以,如果你仅仅修改condition,那么只是满足其中一个条件,这个时候,  被wait_event_interruptible()起来的进程尚未位于runqueue队列中,因  此不会被 schedule。这个时候只要wake_up一下就立刻会重新进入运行调度。     2. 关于wait_event_interruptible的返回值      根据 wait_event_interruptible 的宏定义知:        1) 条件condition为真时调用这个函数将直接返回0,而当前进程不会        被 wait_event_interruptible和从runqueue队列中删除。        2) 如果要被wait_event_interruptible的当前进程有nonblocked pending        signals, 那么会直接返回-ERESTARTSYS(i.e. -512),当前进程不会        被wait_event_interruptible 和从runqueue队列中删除。        3) 其他情况下,当前进程会被正常的wait_event_interruptible,并从        runqueue队列中删除,进入TASK_INTERRUPTIBLE状态退出运行调度,        直到再次被唤醒加入runqueue队列中后而参与调度,将正常返回0。     附1:wait_event_interruptible  宏     #define wait_event_interruptible(wq, condition)    \  ({                                                 \       int __ret = 0;                                  \       if (!(condition))                               \        __wait_event_interruptible(wq, condition, __ret); \        __ret;                                         \  })     注: C语言中{a,b, ..., x}的的值等于最后一项,即x,因此上述  宏的值是 __ret。        附2:wait_event_interruptible()和 wake_up的等效代码     wait_event_interruptible(wq, condition) /*等效没有考虑返回值*/  {       if (!(condition))       {           wait_queue_t _ _wait;           init_waitqueue_entry(&_ _wait, current);           add_wait_queue(&wq, &_ _wait);           for (;;)           {              set_current_state(TASK_INTERRUPTIBLE);              if (condition)              break;              schedule();  /* implicit call: del_from_runqueue(current)*/           }           current->state = TASK_RUNNING;           remove_wait_queue(&wq, &_ _wait);        }  }        void wake_up(wait_queue_head_t *q)  {        struct list_head *tmp;        wait_queue_t *curr;        list_for_each(tmp, &q->task_list)        {          curr = list_entry(tmp, wait_queue_t, task_list);          wake_up_process(curr->task);          /* implicit call: add_to_runqueue(curr->task);*/          if (curr->flags)            break;        }  }
    转载请注明原文地址: https://ju.6miu.com/read-971471.html

    最新回复(0)