linux 工作隊列(轉載)

  1. 工作、工作隊列和工作者線程

如前所述,我們把推後執行的任務叫做工作(work),描述它的數據結構爲work_struct,這些工作以隊列結構組織成工作隊列(workqueue),其數據結構爲workqueue_struct,而工作線程就是負責執行工作隊列中的工作。系統默認的工作者線程爲events,自己也可以創建自己的工作者線程。

  1. 表示工作的數據結構

工作用中定義的work_struct結構表示:

struct work_struct{

unsigned long pending;

struct list_head entry;

void (*func) (void *);

void *data;

void *wq_data;

struct timer_list timer;

};

這些結構被連接成鏈表。當一個工作者線程被喚醒時,它會執行它的鏈表上的所有工作。工作被執行完畢,它就將相應的work_struct對象從鏈表上移去。當鏈表上不再有對象的時候,它就會繼續休眠。

3. 創建推後的工作

要使用工作隊列,首先要做的是創建一些需要推後完成的工作。可以通過DECLARE_WORK在編譯時靜態地建該結構:

DECLARE_WORK(name, void (*func) (void *), void *data);

這樣就會靜態地創建一個名爲name,待執行函數爲func,參數爲data的work_struct結構。

同樣,也可以在運行時通過指針創建一個工作:

INIT_WORK(struct work_struct *work, woid(*func) (void *), void*data);

這會動態地初始化一個由work指向的工作。

4. 工作隊列中待執行的函數

工作隊列待執行的函數原型是:

void work_handler(void *data)

這個函數會由一個工作者線程執行,因此,函數會運行在進程上下文中。默認情況下,允許響應中斷,並且不持有任何鎖。如果需要,函數可以睡眠。需要注意的是,儘管該函數運行在進程上下文中,但它不能訪問用戶空間,因爲內核線程在用戶空間沒有相關的內存映射。通常在系統調用發生時,內核會代表用戶空間的進程運行,此時它才能訪問用戶空間,也只有在此時它纔會映射用戶空間的內存。

5. 對工作進行調度

現在工作已經被創建,我們可以調度它了。想要把給定工作的待處理函數提交給缺省的events工作線程,只需調用

schedule_work(&work);

work馬上就會被調度,一旦其所在的處理器上的工作者線程被喚醒,它就會被執行。

有時候並不希望工作馬上就被執行,而是希望它經過一段延遲以後再執行。在這種情況下,可以調度它在指定的時間執行:

schedule_delayed_work(&work, delay);

這時,&work指向的work_struct直到delay指定的時鐘節拍用完以後纔會執行。

6. 工作隊列的簡單應用

#include
#include
#include

staticstructworkqueue_struct*queue=NULL;
staticstructwork_struct work;

staticvoidwork_handler(structwork_struct*data)
{
printk(KERN_ALERT"work handler function./n");
}

staticint__init test_init(void)
{
queue=create_singlethread_workqueue("helloworld");
if(!queue)
gotoerr;

INIT_WORK(&work,work_handler);
schedule_work(&work);

return0;
err:
return-1;
}

staticvoid__exit test_exit(void)
{
destroy_workqueue(queue);
}
MODULE_LICENSE("GPL");
module_init(test_init);
module_exit(test_exit);

上文來源:http://blog.csdn.net/zyhorse2010/article/details/6455026linux工作隊列(補充)

走入Linux的殿堂已經有一年有餘了,在這裏我想將Linux的各種實現機制分析一遍,一方面對自己來說也是溫故而知新,另一方面,促進大家的交流,最好能夠給大家一些拋磚引玉的啓迪。我是硬件出身,搞硬件已經好多年了,從是專門軟件開發也接近兩年了,在這一段時間內我越發認爲軟硬件協同設計是未來發展的主流,軟硬件的界限越來越模糊,軟硬件的設計思想是相通的,實現方法是各異的,實現的結果上當然也存在較大差別,因此,很有必要做好軟硬件的協同設計。本着這樣的想法,我想將我所認識的Linux分析一遍,特別是一些我認爲精華和重要的機制,另外在討論過程中,我會插入一些其他的OS實現機制,進行對比分析,我把這一類blog文章劃歸爲“Linux機制分析”,希望大家支持。

 

什麼是workqueue?

Linux中的Workqueue機制就是爲了簡化內核線程的創建。通過調用workqueue的接口就能創建內核線程。並且可以根據當前系統CPU的個數創建線程的數量,使得線程處理的事務能夠並行化。

workqueue是內核中實現簡單而有效的機制,他顯然簡化了內核daemon的創建,方便了用戶的編程,

 

Workqueue機制的實現

Workqueue機制中定義了兩個重要的數據結構,分析如下:

1、 cpu_workqueue_struct結構。該結構將CPU和內核線程進行了綁定。在創建workqueue的過程中,Linux根據當前系統CPU的個數創建cpu_workqueue_struct。在該結構主要維護了一個任務隊列,以及內核線程需要睡眠的等待隊列,另外還維護了一個任務上下文,即task_struct。

2、 work_struct結構是對任務的抽象。在該結構中需要維護具體的任務方法,需要處理的數據,以及任務處理的時間。該結構定義如下:

struct work_struct {

unsigned long pending;

struct list_head entry;

void (*func)(void *);

void *data;

void *wq_data;

strut timer_list timer;

};

 

當用戶調用workqueue的初始化接口create_workqueue或者create_singlethread_workqueue對workqueue隊列進行初始化時,內核就開始爲用戶分配一個workqueue對象,並且將其鏈到一個全局的workqueue隊列中。然後Linux根據當前CPU的情況,爲workqueue對象分配與CPU個數相同的cpu_workqueue_struct對象,每個cpu_workqueue_struct對象都會存在一條任務隊列。緊接着,Linux爲每個cpu_workqueue_struct對象分配一個內核thread,即內核daemon去處理每個隊列中的任務。至此,用戶調用初始化接口將workqueue初始化完畢,返回workqueue的指針。

 

在初始化workqueue過程中,內核需要初始化內核線程,註冊的內核線程工作比較簡單,就是不斷的掃描對應cpu_workqueue_struct中的任務隊列,從中獲取一個有效任務,然後執行該任務。所以如果任務隊列爲空,那麼內核daemon就在cpu_workqueue_struct中的等待隊列上睡眠,直到有人喚醒daemon去處理任務隊列。

 

Workqueue初始化完畢之後,將任務運行的上下文環境構建起來了,但是具體還沒有可執行的任務,所以,需要定義具體的work_struct對象。然後將work_struct加入到任務隊列中,Linux會喚醒daemon去處理任務。

 

上述描述的workqueue內核實現原理可以描述如下:


在Workqueue機制中,提供了一個系統默認的workqueue隊列——keventd_wq,這個隊列是Linux系統在初始化的時候就創建的。用戶可以直接初始化一個work_struct對象,然後在該隊列中進行調度,使用更加方便。

 

 

 

Workqueue編程接口

序號

接口函數

說明

1

create_workqueue

用於創建一個workqueue隊列,爲系統中的每個CPU都創建一個內核線程。輸入參數:

@name:workqueue的名稱

2

create_singlethread_workqueue

用於創建workqueue,只創建一個內核線程。輸入參數:

@name:workqueue名稱

3

destroy_workqueue

釋放workqueue隊列。輸入參數:

@ workqueue_struct:需要釋放的workqueue隊列指針

4

schedule_work

調度執行一個具體的任務,執行的任務將會被掛入Linux系統提供的workqueue——keventd_wq輸入參數:

@ work_struct:具體任務對象指針

5

schedule_delayed_work

延遲一定時間去執行一個具體的任務,功能與schedule_work類似,多了一個延遲時間,輸入參數:

@work_struct:具體任務對象指針

@delay:延遲時間

6

queue_work

調度執行一個指定workqueue中的任務。輸入參數:

@ workqueue_struct:指定的workqueue指針

@work_struct:具體任務對象指針

7

queue_delayed_work

延遲調度執行一個指定workqueue中的任務,功能與queue_work類似,輸入參數多了一個delay。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章