Linux-2.6提供如下關於等待隊列的操作:
(1) 定義"等待隊列頭",
wait_queue_head_t my_queue;
defined in linux/wait.h
50 struct __wait_queue_head {
51 spinlock_t lock; 52 struct list_head task_list; 53 }; 54 typedef struct __wait_queue_head wait_queue_head_t;
(2) 初始化"等待隊列頭"
init_waitqueue_head(&my_queue);
defined in linux/wait.c header file
13 void init_waitqueue_head(wait_queue_head_t *q)
14 { 15 spin_lock_init(&q->lock); 16 INIT_LIST_HEAD(&q->task_list); 17 }
定義和初始化的快捷方式:
DECLARE_WAIT_QUEUE_HEAD(my_queue);
linux/wait.h
70 #define __WAIT_QUEUE_HEAD_INITIALIZER(name) { / 71 .lock = __SPIN_LOCK_UNLOCKED(name.lock), / 72 .task_list = { &(name).task_list, &(name).task_list } }
74 #define DECLARE_WAIT_QUEUE_HEAD(name) / 75 wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
(3) 定義等待隊列
DECLARE_WAITQUEUE(name, tsk);
定義並初始化一個名爲name的等待隊列(wait_queue_t);
linux/wait.h
32 struct __wait_queue { 33 unsigned int flags; 34 #define WQ_FLAG_EXCLUSIVE 0x01 35 void *private; 36 wait_queue_func_t func; 37 struct list_head task_list; 38 }; 28 typedef struct __wait_queue wait_queue_t;
62 #define __WAITQUEUE_INITIALIZER(name, tsk) { / 63 .private = tsk, / 64 .func = default_wake_function, / 65 .task_list = { NULL, NULL } } 66 67 #define DECLARE_WAITQUEUE(name, tsk) / 68 wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
(4) 添加/移除等待隊列
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);
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);
等待第一個參數queue作爲等待隊列頭的等待隊列被喚醒,而且第二個參數condition必須滿足,否則阻塞。wait_event()和wait_event_interruptible()的區別在於後者可以被信號打斷,而前者不能。加上timeout後的宏意味着阻塞等待的超時時間,以jiffy爲單位,在第三個參數的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_interruptble()只能喚醒處於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()