等待队列

我们曾简要的提到进程(也就是正在运行的程序)可以转入休眠状态以等待某个特定事件,当该事件发生时这些进程能够被再次唤醒。内核实现这一功能的技术要点是把等待队列(wait queue)和每一个事件联系起来。需要等待事件的进程在转入休眠状态后插入到队列中。当事件发生之后,内核遍历相应队列,唤醒休眠的任务让它投入运行状态。任务负责将自己从等待队列中清除。

等待队列的功能强大得令人吃惊,它们被广泛应用于整个内核中。更重要的是,实现等待队列的代码量并不大。

wait_queue结构: 单链

@ include/linux/wait.h

struct wait_queue {

    struct task_struct * task;

    struct wait_queue * next;

};

       进程(也就是正在运行的程序)可以转入休眠状态以等待某个特定事件,当该事件发生时这些进程能够被再次唤醒。内核实现这一功能的技术要点是把等待队列(wait queue)和每一个事件联系起来。需要等待事件的进程在转入休眠状态后插入到队列中。当事件发生之后,内核遍历相应队列,唤醒休眠的任务让它投入运行状态。任务负责将自己从等待队列中清除。

等待队列的功能强大得令人吃惊,它们被广泛应用于整个内核中。更重要的是,实现等待队列的代码量并不大。      

wait_event @sched.h

通过使用这个宏,内核代码能够使当前执行的进程在等待队列wq中等待直至给定condition(可能是任何的表达式)得到满足。

如果条件已经为真,当前进程显然也就无需等待了。

否则,进程必须等待给定条件转变为真。这可以通过调用__wait_event来实现(16824行),我们将在下一节介绍它。由于 __wait_event已经同wait_event分离,已知条件为假的部分内核代码可以直接调用__wait_queue,而不用通过宏来进行冗余的(特别是在这些情况下)测试,实际上也没有代码会真正这样处理。更为重要的是,如果条件已经为真,wait_event会跳过将进程插入等待队列的代码。

__wait_event@sched.c

__wait_event使当前进程在等待队列wq中等待直至condition为真。

__wake_up@sched.c

该函数用来唤醒等待队列中正在休眠的进程。它由wake_upwake_up_interruptible调用(请分别参看16612行和16614行)。这些宏提供mode参数,只有状态满足mode所包含的状态之一的进程才可能被唤醒。