高级字符驱动程序操作之休眠(理论篇)

来源:互联网 发布:mac怎么安装r语言 编辑:程序博客网 时间:2024/05/28 23:22

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,对缓冲区操作应该有清晰的认识

 

需要注意的是: 读写指针都不会读写缓冲区的结尾地址,缓冲区的结尾地址仅仅用于回卷;

                      因为读指针始终在追赶写指针,是写指针让读写指针能够相遇,也就是写指针不可能超过读指针,除非读指针读完所有数据,与写指针重逢;

                       当读写指针相遇,表示缓冲区为空。

           

 

原创粉丝点击