linux 內核wait queue

在Linux驅動程序中,可以使用等待隊列(waitqueue)來實現阻塞進程的喚醒。waitqueue很早就作爲一種基本的功能單位出現在Linux內核裏了,它以隊列位基礎數據結構,與進程調度機制緊密結合,能夠用於實現內核中異步事件通知機制。等待隊列可以用來同步對系統資源的訪問。(信號量在內核中也依賴等待隊列來實現)。
    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()
發佈了10 篇原創文章 · 獲贊 4 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章