国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Linux > 正文

Linux中的work queue

2024-08-27 23:58:31
字體:
來源:轉載
供稿:網友

工作隊列(work queue)是Linux kernel中將工作推后執行的一種機制,這種機制和BH或Tasklets不同之處在于工作隊列是把推后的工作交由一個內核線程去執行,因此工作隊列的優勢就在于它允許重新調度甚至睡眠.

工作隊列是2.6內核開始引入的機制,在2.6.20之后,工作隊列的數據結構發生了一些變化,因此本文分成兩個部分對2.6.20之前和之后的版本分別做介紹.

1、2.6.0~2.6.19

數據結構,代碼如下:

  1. struct work_struct { 
  2.     unsigned long pending; 
  3.     struct list_head entry; 
  4.     void (*func)(void *); 
  5.     void *data; 
  6.     void *wq_data; 
  7.     struct timer_list timer; 
  8. }; 

pending是用來記錄工作是否已經掛在隊列上;

entry是循環鏈表結構;

func作為函數指針,由用戶實現;

data用來存儲用戶的私人數據,此數據即是func的參數;

wq_data一般用來指向工作者線程,工作者線程參考下文;

timer是推后執行的定時器。

work_struct的這些變量里,func和data是用戶使用的,其他是內部變量,我們可以不用太過關心.

API:

1) INIT_WORK(_work, _func, _data)

初始化指定工作,目的是把用戶指定的函數_func及_func需要的參數_data賦給work_struct的func及data變量.

2) int schedule_work(struct work_struct *work)

對工作進行調度,即把給定工作的處理函數提交給缺省的工作隊列和工作者線程,工作者線程本質上是一個普通的內核線程,在默認情況下,每個CPU均有一個類型為“events”的工作者線程,當調用schedule_work時,這個工作者線程會被喚醒去執行工作鏈表上的所有工作.

3) int schedule_delayed_work(struct work_struct *work, unsigned long delay)

延遲執行工作,與schedule_work類似.

4) void flush_scheduled_work(void)

刷新缺省工作隊列,此函數會一直等待,直到隊列中的所有工作都被執行.

5) int cancel_delayed_work(struct work_struct *work)

flush_scheduled_work并不取消任何延遲執行的工作,因此,如果要取消延遲工作,應該調用cancel_delayed_work.

以上均是采用缺省工作者線程來實現工作隊列,其優點是簡單易用,缺點是如果缺省工作隊列負載太重,執行效率會很低,這就需要我們創建自己的工作者線程和工作隊列.

API:

1) struct workqueue_struct *create_workqueue(const char *name)

創建新的工作隊列和相應的工作者線程,name用于該內核線程的命名.

2) int queue_work(struct workqueue_struct *wq, struct work_struct *work)

類似于schedule_work,區別在于queue_work把給定工作提交給創建的工作隊列wq而不是缺省隊列.

3) int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay)

延遲執行工作.

4) void flush_workqueue(struct workqueue_struct *wq)

刷新指定工作隊列.

5) void destroy_workqueue(struct workqueue_struct *wq)

釋放創建的工作隊列.

下面一段代碼可以看作一個簡單的實作,代碼如下:

  1. void my_func(void *data) 
  2.     char *name = (char *)data; 
  3.     printk(KERN_INFO “Hello world, my name is %s!/n”, name); 
  4.  
  5. struct workqueue_struct *my_wq = create_workqueue(“my wq”); 
  6. struct work_struct my_work; 
  7.  
  8. INIT_WORK(&my_work, my_func, “Jack”); 
  9. queue_work(my_wq, &my_work); 
  10.  
  11. destroy_workqueue(my_wq); 
  12. //開源代碼Vevb.com 

2、2.6.20~2.6.??

自2.6.20起,工作隊列的數據結構發生了一些變化,使用時不能沿用舊的方法,數據結構,代碼如下:

  1. typedef void (*work_func_t)(struct work_struct *work); 
  2. struct work_struct { 
  3.     atomic_long_t data; 
  4.     struct list_head entry; 
  5.     work_func_t func; 
  6. }; 

與2.6.19之前的版本相比,work_struct瘦身不少,粗粗一看,entry和之前的版本相同,func和data發生了變化,另外并無其他的變量.

entry我們不去過問,這個和以前的版本完全相同,data的類型是atomic_long_t,這個類型從字面上看可以知道是一個原子類型,第一次看到這個變量時,很容易誤認為和以前的data是同樣的用法,只不過類型變了而已,其實不然,這里的data是之前版本的pending和wq_data的復合體,起到了以前的pending和wq_data的作用.

func的參數是一個work_struct指針,指向的數據就是定義func的work_struct.

看到這里,會有兩個疑問,第一,如何把用戶的數據作為參數傳遞給func呢?以前有void *data來作為參數,現在好像完全沒有辦法做到,第二,如何實現延遲工作?目前版本的work_struct并沒有定義timer.

解決第一個問題,需要換一種思路,2.6.20版本之后使用工作隊列需要把work_struct定義在用戶的數據結構中,然后通過container_of來得到用戶數據,具體用法可以參考稍后的實作.

對于第二個問題,新的工作隊列把timer拿掉的用意是使得work_struct更加單純,首先回憶一下之前版本,只有在需要延遲執行工作時才會用到timer,普通情況下timer是沒有意義的,所以之前的做法在一定程度上有些浪費資源,所以新版本中,將timer從work_struct中拿掉,然后又定義了一個新的結構delayed_work用于處理延遲執行,代碼如下:

  1. struct delayed_work { 
  2.     struct work_struct work; 
  3.     struct timer_list timer; 
  4. }; 

下面把API羅列一下,每個函數的解釋可參考之前版本的介紹或者之后的實作.

1) INIT_WORK(struct work_struct *work, work_func_t func)

2) INIT_DELAYED_WORK(struct delayed_work *work, work_func_t func)

3) int schedule_work(struct work_struct *work)

4) int schedule_delayed_work(struct delayed_work *work, unsigned long delay)

5) struct workqueue_struct *create_workqueue(const char *name)

6) int queue_work(struct workqueue_struct *wq, struct work_struct *work)

7) int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay)

8) void flush_scheduled_work(void)

9) void flush_workqueue(struct workqueue_struct *wq)

10) int cancel_delayed_work(struct delayed_work *work)

11) void destroy_workqueue(struct workqueue_struct *wq)

其中,1), 2), 4) ,7)和以前略有區別,其他用法完全一樣,實作,代碼如下:

  1. struct my_struct_t { 
  2.     char *name; 
  3.     struct work_struct my_work; 
  4. }; 
  5.  
  6. void my_func(struct work_struct *work) 
  7.     struct my_struct_t *my_name = container_of(work, struct my_struct_t, my_work); 
  8.     printk(KERN_INFO “Hello world, my name is %s!/n”, my_name->name); 
  9.  
  10. struct workqueue_struct *my_wq = create_workqueue(“my wq”); 
  11. struct my_struct_t my_name; 
  12.  
  13. my_name.name = “Jack”; 
  14.  
  15. INIT_WORK(&(my_name.my_work), my_func); 
  16. queue_work(my_wq, &my_work); 
  17.  
  18. destroy_workqueue(my_wq);

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 昂仁县| 西丰县| 云龙县| 长葛市| 建水县| 泸水县| 庆城县| 南开区| 乌兰浩特市| 乌兰浩特市| 浦北县| 仁怀市| 花垣县| 盘锦市| 崇文区| 金乡县| 民和| 凤山县| 集安市| 娱乐| 寻甸| 镇坪县| 扶风县| 云阳县| 延庆县| 南川市| 延川县| 东莞市| 饶平县| 本溪市| 昭觉县| 禄丰县| 育儿| 吉隆县| 苏尼特左旗| 郎溪县| 兖州市| 台东市| 陇南市| 宜兰县| 湘乡市|