一、概述
等待队列在内核中有很多用途,尤其在中断处理、进程同步及定时。等待队列实现事件上的条件等待;希望等待特定事件的进程把自己放在合适的等待队列,并放弃控制权。
二、相关结构体
-
等待队列由双向链表实现,其元素包括指向进程描述符的指针。每个等待队列都有一个等待队列头,即wait_queue_head_t结构。
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list; //等待进程链表
};
typedef struct __wait_queue_head wait_queue_head_t; -
等待队列链表中的元素,即wait_queue_t结构
等待队列链表中的每个元素代表一个睡眠进程,进程描述符地址存入private字段中。
typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
struct __wait_queue {
unsigned int flags; //标志
define WQ_FLAG_EXCLUSIVE 0x01
void *private; //进程描述符
wait_queue_func_t func; //唤醒函数,缺省为default_wake_function
struct list_head task_list; //链接到等待队列链表中
};
typedef struct __wait_queue wait_queue_t;
A、定义和初始化等待队列头
DECLARE_WAIT_QUEUE_HEAD(wait);//初始化一个等待队列头 wait
或者动态地, 如下:
wait_queue_head_t wait;
init_waitqueue_head(&wait);
B、休眠进程
wait_event(wait, condition) //将当前进程的状态设置为 TASK_UNINTERRUPTIBLE
wait_event_interruptible(wait, condition) //TASK_INTERRUPTIBLE
wait_event_timeout(wait, condition, timeout) //TASK_UNINTERRUPTIBLE
wait_event_interruptible_timeout(wait, condition, timeout) //TASK_INTERRUPTIBLE
备注:
wait 是等待队列头, condition 是条件,如果调用 wait_event 前 condition == 0 ,则调用 wait_event 之后,当前
进程就会休眠。
TASK_INTERRUPTIBLE 与 TASK_UNINTERRUPTIBLE 区别在于,它的休眠是否会被信号打断,别的进程发来一个信号比如 kill ,
TASK_INTERRUPTIBLE 就会醒来去处理。然而 TASK_UNINTERRUPTIBLE 不会。schedule(),进程调度,而 schedule_timeout()
进行调度之后,一定时间后自动唤醒。
C、唤醒进程
void wake_up(wait_queue_head_t *wait);
void wake_up_interruptible(wait_queue_head_t *wait);
备注:
对应于不同的进程状态,使用不同的唤醒函数。比如你调用 wake_up 去唤醒一个使用 wait_event 等,进入休眠的进程,唤醒
之后,它会判断 condition 是否为真,如果还是假的继续睡眠。
网友评论