1. 休眠的原则
第一条: "永远不要在原子上下文中进入休眠" (LDD3 p149)
第二条: 当线程被唤醒时,应当检查等待的条件是否为真
第三条: 确保即将休眠的线程一定会被唤醒
2. 简单休眠
wait_event(queue, condition) // 不可中断的休眠,不符合休眠的原则(第一条)不推荐
wait_event_interruptible(queue, condition) // 接受终端的休眠,推荐
wait_event_timeout(queue, condition, timeout) // 不可中断,定时唤醒
wait_event_interruptible_timeout(queue, condition, timeout) // 接受中断,定时唤醒
约定: 对于不可中断的休眠,使用 wait_up 唤醒,对于接受中断的休眠,使用 wait_up_interruptible
唤醒
3. 阻塞和非阻塞标志
file 文件结构指针 filp 的成员 f_flags 可以设定进程的阻塞和非阻塞标志,如果 filp_flags & 
O_NONBLOCK 为真,进程被标志为非阻塞的,反之进程被标志为可阻塞的
4. 高级休眠
第一步: 初始化 wait_queue_t 结构
静态初始化 DEFINE_WAIT(my_wait);
动态初始化 wait_queue_t my_wait;
init_wait(&my_wait);
第二步: 设置进程状态
void prepare_to_wait(wait_queue_head_t *queue,
wait_queue_t *wait,
int state);
state 就是要设置的新状态,它可以是 TASK_INTERRUPTIBLE(可中断休眠状态)和
TASK_UNINTERRUPTIBLE(不可中断休眠)
第三步: 让出处理器,开始休眠
if (!condition)
 schedule();
第四步: 如果 condition 为 true,表示进程不需要休眠了,要完成一些清理工作
void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait);
5. 独占等待
当调用 wake_up 时,所有在等待队列中的线程都被唤醒,当等待队列中的线程很多的时候,这样唤
醒的代价就会显得很"疯狂"
为了防止这种情况,驱动程序员可以考虑在等待队列入口为休眠线程设置 WQ_FLAG_EXCLUSIVE 标
志,这样在 wake_up 的时候,操作系统唤醒第一个具有 WQ_FLAG_EXCLUSIVE 标志的线程后就停止唤醒操作
6. 缓冲区操作
这里的缓冲区操作是仅仅是策略问题,而非机制问题,为了看懂 scullpipe,对缓冲区操作应该有清
晰的认识
需要注意的是: 读写指针都不会读写缓冲区的结尾地址,缓冲区的结尾地址仅仅用于回卷;
因为读指针始终在追赶写指针,是写指针让读写指针能够相遇,也就是写指针不可能超过读指针,除非读
指针读完所有数据,与写指针重逢;当读写指针相遇,表示缓冲区为空