linux 等待队列

来源:互联网 发布:暗黑黎明挂机软件 编辑:程序博客网 时间:2024/04/30 17:44

摘自 <<Linux设备驱动开发详解>>(第三版)

在 Linux 驱动程序中,可以使用等待队列(Wait Queue) 来实现阻塞进程的唤醒.等待队列很早就作为一个基本的功能单位出现在 Linux 内核里了,它以队列为基础数据结构,与进程调试机制紧密结合,可以用来同步对系统资源的访问.

Linux 内核提供了如下关于等待队列的操作.

1.定义"等待队列头部"

wait_queue_head_t my_queue;

wait_queue_head_t 是 __wait_queue_head 结构体的一个 typedef

ps:

include/linux/wait.h :

typedef struct __wait_queue_head wait_queue_head_t;

2.初始化"等待队列头部"

init_waitqueue_head(&my_queue);
使用宏定义并初始化等待队列头部:

DECLARE_WAIT_QUEUE_HEAD(name)


3.定义等待队列元素

DECLARE_WAITQUEUE(name, tsk)
定义并初始化一个名为 name 的等待队列元素

4.添加/移除等待队列

void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
add_wait_queue() 用于将等待队列元素 wait 添加到等待队列头部 q 指向的双向链表中,而 remove_wait_queue() 用于将等待队列元素 wait 从由 q 头部指向的链表中移除.

5.等待事件

wait_event(queue, condition)wait_event_interruptible(queue, condition)wait_event_timeout(queue, condition, timeout)wait_event_interruptible_timeout(queue, condition, timeout)
第 1 个参数 queue 作为等待队列头部的队列被唤醒,而且第 2 个参数 condition 必须满足,否则继续阻塞. wait_event() 和 wait_event_interruptible() 的区别在于后者可以被信号打断,而前者不能.加上 _timeout 后綴意味着阻塞等待的超时时间, 以 jiffy 为单位, 在弟 3 个参数的 timeout 到达时, 不论 condition 是否满足, 均返回.

6.唤醒队列

void wake_up(wait_queue_head_t *queue);void wake_up_interruptible(wait_queue_head_t *queue);
上述操作会唤醒以 queue 作为等待队列头部的队列中所有的进程

wake_up() 应该与 wait_event() 或 wait_event_timeout() 成对使用, 而 wake_up_interruptible() 应该与 wait_event_interruptible() 或 wait_event_interruptible_timeout() 成对使用. wake_up() 可唤醒处于 TASK_INTERRUPTIBLE 和 TASK_UNINTERRUPTIBLE 的进程, 而 wake_up_interruptible() 只能唤醒处于 TASK_INTERRUPTIBLE 的进程.

7.在等待队列上睡眠

sleep_on(wait_queue_head_t *q);interruptible_sleep_on(wait_queue_head_t *q);
sleep_on() 函数的作用就是将目前进程的状态置成 TASK_UNINTERRUPTIBLE, 并定义一个等待队列元素, 之后把它挂到等待队列头部 q 指向的双向链表, 直到资源可获得, q 队列指向链接的进程被唤醒.

interruptible_sleep_on() 与 sleep_on() 函数类似, 其作用是将目前进程的状态置成 TASK_INTERRUPTIBLE, 并定义一个等待队列元素, 之后把它附属到 q 指向的队列, 直到资源可获得 (q 指引的等待队列被唤醒) 或者进程收到信号.

sleep_on() 函数应该与 wake_up() 成对使用, interruptible_sleep_on() 应该与 wake_up_interruptible() 成对使用.

0 0
原创粉丝点击