Linux kernel多執行緒的幾種實現

2021-06-22 07:20:22 字數 3771 閱讀 8862

驅動開發中常常會啟動幾個核心執行緒,在整個驅動生命週期期間執行某些操作,比如

usb驅動的控制線程,一直等待

scsi

命令,沒有命令的話睡眠,有命令的話就喚醒執行緒,解析執行相關的命令。還有

usb驅動中的掃瞄線程,如果有新的裝置連線到

usb匯流排,則會啟動掃瞄過程,平時時候讓出

cpu資源休眠。

常用的核心執行緒建立方法有3個,

kernel_thread, kthread_create

和kthread_run

。使用這些函式或巨集需要包括如下標頭檔案:

#include //wake_up_process()

#include //kthread_ceate(), kthread_run()

#include //is_err(), ptr_err()

這些方法建立的核心執行緒必須能夠自己放棄

cpu資源,即不要產生死迴圈而不主動呼叫

scheduel()

函式,否則這樣

cpu會一直忙,因為核心程序

/執行緒是不可搶占的,所以他必須自己能夠主動的放棄資源,不管通過什麼方式。

(1)kernel_thread

原型如下

int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)

該函式的實現與具體的

cpu架構有關,各引數的含義如下: fn

:函式指標,指向要建立的核心執行緒的執行函式

arg:fn

函式的引數,可以沒有,沒有寫

null

flags

:標誌,與建立他的程序共享哪些東西

該函式返回整型數,如果返回的值小於

0則表示核心執行緒建立失敗,否則建立成功。

由該函式建立的程序不需要在模組清除時登出,可能執行過就自動銷毀了。

例子:static declare_wait_queue_head(my_waitqueue);

static int example_kernel_thread(void)

set_current_state(task_running);

remove_wait_queue(&my_waitqueue,&wait);

printk(kern_notice 「new thread running\n」);

return 0; }

static __init int init_hello_world(void)

static __exit void exit_hello_world(void)

module_init(init_hello_world);

module_exit(exit_hello_world);

(2)kthread_create

原型如下:

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

void *data,

const char namefmt, ...)

__attribute__((format(printf, 3, 4)));

該函式返回建立的核心執行緒的程序描述符。

各引數含義:

threadfn

:函式指標,指向核心執行緒所執行的函式

data

:不定型別的指標,指向核心執行緒所需要的引數

namefmt

:核心執行緒名字 …

:類似於

printf引數

例如核心執行緒的名字帶有不確定數字,可以像

printf

函式一樣將數字寫進核心執行緒名字。

這個函式建立的核心執行緒不能立即執行,需要呼叫

wake_up_process()

函式來使執行緒執行,為此定義了巨集

kthread_run

,他是kthread_create()

函式和wake_up_process()

的封裝。

例子:static struct task_struct *test_task;

static __init int test_init_module(void)

wake_up_process(test_task);

return 0; }

模組退出時,需要結束所建立執行緒的執行,使用下面的函式:

int kthread_stop(struct task_struct *k);

int kthread_should_stop(void);

注意:在呼叫

kthread_stop

函式時,執行緒函式不能已經執行結束。否則,

kthread_stop

函式會一直進行等待。

為了避免這種情況,需要確保執行緒沒有退出,其方法如**中所示:

thread_func()

} exit_code()

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

例子**:

static void test_cleanup_module(void)

} module_init(test_init_module);

module_exit(test_cleanup_module);

關於建立的新執行緒的執行緒函式,該函式是要來完成所需要的業務邏輯工作的,其一般框架如下:

int threadfunc(void *data)

else//假

} }另外,有該函式建立的核心執行緒可以指定在不同的

cpu核上執行(如果是多核的話),這個可以通過下面的函式實現:

void kthread_bind(struct task_struct *k, unsigned int cpu); k

:建立的核心執行緒的程序描述符

cpu:cpu編號

(3)kthread_run

這個不是函式,是乙個巨集:

/*** kthread_run - create and wake a thread.

* @threadfn: the function to run until signal_pending(current).

* @data: data ptr for @threadfn.

* @namefmt: printf-style name for the thread. *

* wake_up_process().  returns the kthread or err_ptr(-enomem). */

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

這個巨集完全同

kthread_create()

,只是建立完了執行緒,執行緒能夠馬上執行。

對於(2)

和(3)

需要注意:

執行緒一旦啟動起來後,會一直執行,除非該執行緒主動呼叫

do_exit

函式,或者其他的程序呼叫

kthread_stop

函式,結束執行緒的執行。

int kthread_stop(struct task_struct *thread);

kthread_stop() 

通過傳送訊號給執行緒。

如果執行緒函式正在處理乙個非常重要的任務,它不會被中斷的。當然如果執行緒函式永遠不返回並且不檢查訊號,它將永遠都不會停止。

**:

Linux kernel多執行緒的幾種實現

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

Linux kernel 分析之十 核心執行緒

眾所周知,核心中建立乙個核心執行緒是通過kernel thread實現的。宣告如下 int kernel thread int fn void void arg,unsigned long flags 我們知道,使用者態建立執行緒呼叫clone 如果要在核心態建立執行緒,首先想到的是在核心態呼叫cl...

(多執行緒)多執行緒的併發安全

多執行緒併發操作同乙個資源 同步鎖 多執行緒操作的鎖必須唯一 必須搞清楚 哪些 需要同步?那些在操作共享資源的 只要包含非讀的操作,或者根據共享資源進行條件判斷的,就需要同步!同步 塊解決 package com.gc.thread 多執行緒操作共享資源 併發 執行緒安全問題 同步 鎖 相對而言效能...