Wait_Queue------等待队列的唤醒事件

wake_up()与wait_event()或者wait_event_timeout成对使用,

wake_up_intteruptible()与wait_event_intteruptible()或者wait_event_intteruptible_timeout()成对使用。


在 Linux 中, 一个等待队列由一个"等待队列头"来管理, 一个 wait_queue_head_t 类型的结构, 定义在中. 一个等待队列头可被定义和初始化, 使用:

DECLARE_WAIT_QUEUE_HEAD(name);

或者动态地, 如下:

wait_queue_head_t my_queue;

init_waitqueue_head(&my_queue);


1、简单睡眠:   

Linux 内核中睡眠的最简单方式是一个宏定义, 称为 wait_event(有几个变体); 它结合了处理睡眠的细节和进程在等待的条件的检查. wait_event 的形式是:

wait_event(queue, condition)

wait_event_interruptible(queue, condition)

wait_event_timeout(queue, condition, timeout)

wait_event_interruptible_timeout(queue, condition, timeout)

这些东西如何使用?queue 是等待队列头,condition 是条件,如果调用 wait_event 前 condition == 0 ,则调用 wait_event 之后,当前进程就会休眠


wait_event:

将当前进程的状态设置为 TASK_UNINTERRUPTIBLE  ,然后 schedule()


wait_event_interruptible:       

TASK_INTERRUPTIBLE    ,然后 schedule()


wait_event_timeout:             

TASK_UNINTERRUPTIBLE  ,然后 schedule_timeout()


wait_event_interruptible_timeout:

TASK_INTERRUPTIBLE    , 然后 schedule_timeout()


TASK_INTERRUPTIBLE 与 TASK_UNINTERRUPTIBLE 区别在于:

它的休眠是否会被信号打断,别的进程发来一个信号比如 kill ,TASK_INTERRUPTIBLE 就会醒来去处理。然而 TASK_UNINTERRUPTIBLE 不会。schedule(),进程调度,而schedule_timeout()进行调度之后,一定时间后自动唤醒。


对应于不同的进程状态,使用不同的唤醒函数:

void wake_up(wait_queue_head_t *queue);

void wake_up_interruptible(wait_queue_head_t *queue);

唤醒时很有意思,比如你调用 wake_up 去唤醒一个使用 wait_event 等,进入休眠的进程,唤醒之后,它会判断 condition 是否为真,如果还是假的继续睡眠。


2、手动睡眠:

        DECLARE_WAITQUEUE(name, tsk)  创建一个等待队列:

                        tsk一般为当前进行current. 这个宏定义并初始化一个名为name的等待队列.

        将等待队列头 加入/移除 等待队列:

                      void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

                      void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);

                      void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

        设置进程状态:

                      set_current_state(TASK_INTERRUPTIBLE) 等

        进程调度: 

                      schedule() 或者 schedule_timeout()

推荐阅读更多精彩内容