等待队列学习笔记

来源:互联网 发布:淘宝直播视频怎么删除 编辑:程序博客网 时间:2024/05/18 01:04
 

阻塞操作是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作。驱动程序通过等待队列实现这样的能力。

定义“等待队列头”

wait_queue_head_t my_queue;

初始化“等待队列头”

init_waitqueue_head(&my_queue);

 定义与初始化

DECLARE_WAIT_QUEUE_HEAD(name);

添加/移除等待队列

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

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

等待事件

wait_event(queue,condition)

wait_event_interruptible(queue,condition)

wait_event_timeout(queue,condition,timeout)

wait_event_interruptible_timeout(queue,condition,timeout)

int wait_event_killable(queue,condition)

 

驱动程序是通过阻塞其调用的进程来实现阻塞的。而进程的状态与等待队列是有关联的。

wait_event(queue,condition)此函数是通过set_current_state(TASK_UNINTERRUPTIBLE)设置进程状态的(条件为假时)

wait_event_interruptible(),将进程状态设置为TASK_INTERRUPTIBLE

wait_event_killable(queue,condition),将进程的状态设置为TASK_KILLABLE

TASK_INTERRUPTIBLE状态的进程在收到信号与中断时皆不能唤醒

TASK_KILLABLEN收到kill信号时可以被唤醒。

等待队列的系列函数一般是这样工作的,判断条件是否成立,不成立定义一个等待队列,然后将等待队列加入等待队列头,之后放置进程状态,调用schedule();再然后调用signal_pending(current)函数,使用其不打断系统函数的完全调用。设置当前进程状态为TASK_RUNNING.

 

唤醒队列

void wake_up(wait_queue_head_t *queue);

void wake_up_interruptible(wait_queue_head_t *queue);

 

wake_up()应与wait_event()或wait_event_timeout()成对使用

wake_up()应与wait_event_interruptible()或wait_event_interruptible_timeout()成对使用

 

使用步骤

a.在设备结构体中定义中增加两个等待队列头

 wait_queue_head_t r_wait;

 wait_queue_head_t w_wait;

b.在模块初始化中初始化等待队列头

 init_waitqueue_head(r_wait);

 init_waitqueue_head(w_wait);

c.在文件操作函数中定义等待队列

 DECLARE_WAITQUEUE(wait,current);

d.然后将等待队列加入等待队列头

 add_wait_queue(&dev->r_wait,&wait);

 add_wait_queue(&dev->w_wait,&wait);

有一部分驱动程序省掉了c,d两步,没有定义等待队列,只使用了队列头

e.调用等待队列函数

  如wait_event()

 也可以自己写调试函数

       用if语句判断条件

       用__set_current_state();改变进程状态

       schedule();更新进程调度表,挂起进程

       signal_pending();使其回到进程调度时,系统调用完整

       __set_current_state(TASK_RUNNING);

f.另外一个进程会用一个语句wake_up等待函数唤醒本进程,执行本进程以后的程序

 如wake_up_interruptible(w_wait);

g.删除等待队列

  remove_wait_queue(w_wait,&wait);

h.模块注销函数中删除等待队列头。