日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux驱动开发之内核线程

發布時間:2023/12/8 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux驱动开发之内核线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內核經常需要在后臺執行一些操作,這種任務就可以通過內核線程(kernle thread)完成--獨立運行在內核空間的標準進程。內核線程和普通的進程間的區別在于內核線程沒有獨立的地址空間,mm指針被設置為NULL;它只在 內核空間運行,從來不切換到用戶空間去;并且和普通進程一樣,可以被調度,也可以被搶占。實際上,內核線程只能由其他內核線程創建,在現有的內核線程中創建一個新的內核線程的方法:

kthread_create:創建線程。
struct?task_struct?*kthread_create(int?(*threadfn)(void?*data),void?*data,const?char?*namefmt,?...);
線程創建后,不會馬上運行,而是需要將kthread_create()?返回的task_struct指針傳給wake_up_process(),然后通過此函數運行線程。
kthread_run?:創建并啟動線程的函數:
struct?task_struct?*kthread_run(int?(*threadfn)(void?*data),void?*data,const?char?*namefmt,?...);
kthread_stop:通過發送信號給線程,使之退出。
int?kthread_stop(struct?task_struct?*thread);
線程一旦啟動起來后,會一直運行,除非該線程主動調用do_exit函數,或者其他的進程調用kthread_stop函數,結束線程的運行。
但如果線程函數正在處理一個非常重要的任務,它不會被中斷的。當然如果線程函數永遠不返回并且不檢查信號,它將永遠都不會停止。

1.?????? 頭文件

#include ?? //wake_up_process()

#include //kthread_create()、kthread_run()

#include //IS_ERR()、PTR_ERR()

2.?????? 實現

2.1創建線程

kernel thread可以用kernel_thread創建,但是在執行函數里面必須用daemonize釋放資源并掛到init下,還需要用completion等待這一過程的完成。為了簡化操作kthread_create閃亮登場。

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

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

???????????????????????? ?? void *data,

???????????????????????? ?? const char namefmt[], ...);

kthread_create源碼詳解見http://blog.sina.com.cn/s/blog_6237dcca0100gq67.html


#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線程名

??????注:線程名由kthread_create函數的第三個參數指定。?


代碼:
?#include?
#include?
#ifndef?SLEEP_MILLI_SEC
#define?SLEEP_MILLI_SEC(nMilliSec)\
do?{?\
long?timeout?=?(nMilliSec)?*?HZ?/?1000;?\
while(timeout?>?0)?\
{?\
timeout?=?schedule_timeout(timeout);?\
}?\
}while(0);
#endif
static?struct?task_struct?*?MyThread?=?NULL;
static?int?MyPrintk(void?*data)
{
char?*mydata?=?kmalloc(strlen(data)+1,GFP_KERNEL);
memset(mydata,'\0',strlen(data)+1);
strncpy(mydata,data,strlen(data));
while(!kthread_should_stop())
{
SLEEP_MILLI_SEC(1000);
printk("%s\n",mydata);
}
kfree(mydata);
return?0;
}
static?int?__init?init_kthread(void)
{
MyThread?=?kthread_run(MyPrintk,"hello?world","mythread");
return?0;
}
static?void?__exit?exit_kthread(void)
{
if(MyThread)
{
printk("stop?MyThread\n");
kthread_stop(MyThread);
}
}
module_init(init_kthread);
module_exit(exit_kthread);
MODULE_AUTHOR("YaoGang");
這個內核線程的作用就是每隔一秒打印一個“hello?world”。
值得一提的是kthread_should_stop函數,我們需要在開啟的線程中嵌入該函數并檢查此函數的返回值,否則kthread_stop是不起作用的......

總結

以上是生活随笔為你收集整理的linux驱动开发之内核线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。