进程休眠(被阻塞)的原因有很多种,但都是在等待某一种事件
(1)文件I/O磁盘读取,键盘输入等硬件事件
(2)获取一个已经被占用的内核信号量等。。。
操作
休眠:进程把自己标记成休眠状态,从可运行红黑树中移出,加入等待队列,调用schedule()选择和执行一个其他进程
唤醒:进程被设为可执行状态,从等待队列中移到可执行红黑树
休眠的进程可能出于二种状态,但位于同一等待队列
(1)task_interruptible
(2)task_uninterruptible,忽略信号(所有信号?)
等待队列
休眠通过等待队列进行处理,等待队列是等待某种事件发生的进程的集合。。
内核使用wake_queue_head_t表示等待队列,可以通过DECLARE_WAITQUEUE()静态创建或init_waitqueue_head动态创建。
为避免产生竞争条件,休眠与唤醒的内核实现较为繁杂
比较典型的是先将进程加入等待队列,再去检查等待条件是否满足,这样避免了在条件已经满足的条件下,仍然休眠的问题。
在许多地方,实际的实现要更加的复杂,对条件的检测更为严格,可能要用到锁。。
当某个事件满足后,相应的模块就要调用wake_up来唤醒对应于该事件的等待队列上的所有进程,并将其放入可运行红黑树,若有进程的优先级比当前运行进程的优先级要高,则在抢占式内核当中,需要设置其need_resched标志。
例如如果磁盘数据到达,VFS模块就要负责唤醒工作
另一个概念就是伪唤醒,即如前所述,等待队列中的状态为TASK_INTERRUPTIBLE的进程会对信号进行处理,此时并不是真正的等待事件到达。。。
OVER!!!