linux驅動中的工作隊列理解


工作隊列的作用:用來代替任務隊列.

  他們允許內核函數(像可延遲的函數)激活,而且稍后由一種叫做工作者線程的特殊內核線程來執行.

和可延遲函數的不同:

  可延遲函數運行在中斷上下文中,不一定在創建它的進程當中運行.

  工作隊列中的函數運行在進程上下文中.(但是由內核線程來執行)

  執行可阻塞函數的唯一方式是在進程上下文中運行.

相同點:

  可延遲函數運行時不可能有任何正在運行的進程,而工作隊列又是由內核線程來執行的,所以他們都不能訪問用戶態地址空間.

工作隊列的使用.

1.  創建

2.  提交隊列

3.  刪除

創建:

  創建分為工作隊列的創建和工作函數(任務)的創建.

  (1)  工作隊列的創建需要有其描述符,它的數據結構是 workqueue_struct.該結構定義在<linux/workqueue.h>中.這里我們不需要關心它的具體組成,內核已經寫好了兩個兩個函數幫我們創建隊列:

      struct workqueue_struct *create_workqueue(const char *name);

      struct workqueue_struct * workqueue_singlethread_workqueue(const char *name);

      他們的區別在於實際處理器的多少,如果是單核處理器的話,他們毫無區別.

      因為每個工作隊列都有一個或多個(多核處理器)專用的進程(內核線程),這些進程運行提交到該工作隊列函數.

      create_workqueue內核會在系統中的每個處理器上為該工作隊列創建專用的線程.這樣,如果工作隊列足夠多的話,可能對系統的性能有所殺傷,而create_singlethread_workqueue則只會創建一個專用的線程.所以,如果單個工作線程足夠使用,推薦使用第二個函數來創建工作隊列.

      同樣的,工作任務的創建也需要有其描述符,它的數據結構是work_struct.內核同樣為我們創建好了幾個宏來方便的創建它.

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

          用於在內核編譯時使用.

        INIT_WORK(struct work_struct *work,void(*function)(void *),void *data);

          用於在系統運行時創建.首次創建時使用它.

        PREPARE_WORK(struct work_struct *work,void(*function)(void *),void *data);

          用於在系統運行時創建.沒有INIT_WORK初始化徹底,因為它不會初始化用來將work_struct結構連接到工作隊列的指針.如果結構已經被提交到工作隊列,而只是需要修改該結構,則應該使用PREPARE_WORK而不是INIT_WORK.

提交:

   如果要將工作提交到工作隊列,則可使用如下兩個函數之一:

    int queue_work(struct workqueue_struct *queue,struct work_struct *work);

    int queue_delayed_work(struct workqueue_struct *queue,struct work_struct *work,unsigned long delay);

    它們都會將work添加到給定的queue.但是如果使用queue_delayed_work,則實際工作至少會在經過指定的jiffies(由delay指定)之后才會執行.如果工作被成功添加到隊列,則上述函數的返回值為1,返回值為非零意味着給定的work_struct結構已經等待在該隊列中,從而不能兩次加入該隊列.

刪除:

   結束對工作隊列的使用后,可調用下面的函數釋放相關資源.

    void destroy_workqueue(struct workqueue_struct *queue);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM