linux核心多線程

來源:互聯網
上載者:User

驅動開發中常常會啟動幾個核心線程,在整個驅動生命週期期間執行某些操作,比如USB驅動的控制線程,一直等待SCSI命令,沒有命令的話睡眠,有命令的話就喚醒線程,解析執行相關的命令。還有USB驅動中的掃描線程,如果有新的裝置串連到USB匯流排,則會啟動掃描過程,平時時候讓出CPU資源休眠。

常用的核心線程建立方法有3個,kernel_thread, kthread_create和kthread_run。使用這些函數或宏需要包括如下標頭檔:

#include <linux/sched.h>//wake_up_process()

#include <linux/kthread.h>//kthread_ceate(), kthread_run()

#include <err.h>//IS_ERR(), PTR_ERR()

 

這些方法建立的核心線程必須能夠自己放棄CPU資源,即不要產生死迴圈而不主動調用scheduel()函數,否則這樣CPU會一直忙,因為核心進程/線程是不可搶佔的,所以他必須自己能夠主動的放棄資源,不管通過什麼方式。

1.       標頭檔

#include <linux/sched.h>   //wake_up_process()

#include <linux/kthread.h> //kthread_create()、kthread_run()

#include <err.h>              //IS_ERR()、PTR_ERR()

2.       實現

2.1建立線程

在模組初始化時,可以進行線程的建立。使用下面的函數和宏定義:

struct task_struct *kthread_create(int (*threadfn)(void *data),

                            void *data,

                            const char namefmt[], ...);

#define kthread_run(threadfn, data, namefmt, ...)                     \

({                                                            \

    struct task_struct *__k                                        \

           = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \

    if (!IS_ERR(__k))                                        \

           wake_up_process(__k);                                \

    __k;                                                     \

})

例如:

static struct task_struct *test_task;

static int test_init_module(void)

{

    int err;

    test_task = kthread_create(test_thread, NULL, "test_task");

    if(IS_ERR(test_task)){

      printk("Unable to start kernel thread.\n");

      err = PTR_ERR(test_task);

      test_task = NULL;

      return err;

    }

wake_up_process(test_task);
       return 0;
   }

   module_init(test_init_module);

2.2線程函數

線上程函數裡,完成所需的商務邏輯工作。主要架構如下所示:

int threadfunc(void *data){

        …

        while(1){

               set_current_state(TASK_UNINTERRUPTIBLE);

               if(kthread_should_stop()) break;

               if(){//條件為真

                      //進行業務處理

               }

               else{//條件為假

                      //讓出CPU運行其他線程,並在指定的時間內重新被調度

                      schedule_timeout(HZ);

               }

        }

        …

        return 0;

}

2.3結束線程

在模組卸載時,可以結束線程的運行。使用下面的函數:

int kthread_stop(struct task_struct *k);

例如:

              static void test_cleanup_module(void)

{

            if(test_task){

                kthread_stop(test_task);

                test_task = NULL;

            }

}

module_exit(test_cleanup_module);

3.       注意事項

(1)       在調用kthread_stop函數時,線程函數不能已經運行結束。否則,kthread_stop函數會一直進行等待。

(2)       線程函數必須能讓出CPU,以便能運行其他線程。同時線程函數也必須能重新被調度運行。在例子程式中,這是通過schedule_timeout()函數完成的。

4.效能測試

可以使用top命令來查看線程(包括核心線程)的CPU利用率。命令如下:

       top –p 線程號

可以使用下面命令來尋找線程號:

       ps aux|grep 線程名


可以用下面的命令顯示所有核心線程:
      ps afx


       註:線程名由kthread_create函數的第三個參數指定

 

*****************************************************************************************************

1 使用kthread_create建立線程:
    struct task_struct *kthread_create(int (*threadfn)(void *data),

                                                                  void *data,
                                                                   const char *namefmt, ...);
這個函數可以像printk一樣傳入某種格式的線程名 
線程建立後,不會馬上運行,而是需要將kthread_create() 返回的task_struct指標傳給wake_up_process(),然後通過此函數運行線程。 
2. 當然,還有一個建立並啟動線程的函數:kthread_run 
   struct task_struct *kthread_run(int (*threadfn)(void *data),
                                    void *data,
                                    const char *namefmt, ...);
3. 線程一旦啟動起來後,會一直運行,除非該線程主動調用do_exit函數,或者其他的進程調用kthread_stop函數,結束線程的運行。 
    int kthread_stop(struct task_struct *thread);
kthread_stop() 通過發送訊號給線程。 
如果線程函數正在處理一個非常重要的任務,它不會被中斷的。當然如果線程函數永遠不返回並且不檢查訊號,它將永遠都不會停止。 
參考:Kernel threads made easy

 

代碼

在執行kthread_stop的時候,目標線程必須沒有退出,否則會Oops。原因很容易理解,當目標線程退出的時候,其對應的task結構也變得無效,kthread_stop引用該無效task結構就會出錯。

為了避免這種情況,需要確保線程沒有退出,其方法如代碼中所示:

thread_func()

{

    // do your work here

    // wait to exit

    while(!thread_could_stop())

    {

           wait();

    }

}

exit_code()

{

     kthread_stop(_task);   //發訊號給task,通知其可以退出了

}

這種退出機制很溫和,一切盡在thread_func()的掌控之中,線程在退出時可以從容地釋放資源,而不是莫名其妙地被人“暗殺”。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.