目錄
- 一、linux 創建內核線程
- 1.1 kthread_create
- 1.2 kthread_create_worker + kthread_queue_work
- 二、設置線程優先級和調度策略
- 2.1 sched_setscheduler
- 2.2 調度策略
一、linux 創建內核線程
1.1 kthread_create
在 linux 中,可以使用 kthread_create
接口創建內核線程,該接口原型如下:
struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...);
入參含義:
- threadfn:線程函數的入口點。
- data:傳遞給線程函數的參數。
- namefmt:線程的名字,可以用格式化字符串指定。
示例代碼:
#include <linux/kthread.h>
#include <linux/delay.h>// 線程函數
int thread_function(void *data) {while (!kthread_should_stop()) {// 線程的主要工作pr_info("Thread is running\n");ssleep(5); // 休眠5秒}return 0;
}// 在合適的地方創建線程
struct task_struct *task;
task = kthread_create(thread_function, NULL, "my_thread");
if (!IS_ERR(task)) {wake_up_process(task); // 啟動線程
}
1.2 kthread_create_worker + kthread_queue_work
kthread_create_worker
主要用于創建一個用于管理工作隊列的工作線程。
函數原型:
struct kthread_worker *kthread_create_worker(unsigned int flags, const char namefmt[], ...);
入參含義:
- flags:創建worker時的標志。
- namefmt:worker的名稱。
kthread_queue_work
用于將一個工作項添加到由kthread_worker
管理的工作隊列中。
函數原型:
void kthread_queue_work(struct kthread_worker *worker, struct kthread_work *work);
入參含義:
-worker:目標worker。
-work:要執行的工作。
示例代碼:
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>static struct kthread_worker *worker;
static struct kthread_work work;void work_function(struct kthread_work *work) {pr_info("Work function is running\n");
}int __init my_module_init(void) {worker = kthread_create_worker(0, "my_worker");if (IS_ERR(worker)) {pr_err("Failed to create kthread worker\n");return PTR_ERR(worker);}// 初始化工作kthread_init_work(&work, work_function);// 將工作排隊kthread_queue_work(worker, &work);return 0;
}void __exit my_module_exit(void) {kthread_destroy_worker(worker);
}module_init(my_module_init);
module_exit(my_module_exit);
上述示例代碼中,
kthread_create_worker
創建一個工作隊列kthread_worker
;kthread_queue_work
將一個工作項kthread_work
添加到工作隊列kthread_worker
;- 每調用一次
kthread_queue_work(worker, &work);
,工作項kthread_work
對應的執行函數work_function
就會得到一次調用。
二、設置線程優先級和調度策略
2.1 sched_setscheduler
sched_setscheduler
接口是 linux 內核中,設置特定線程或進程優先級和調度策略的接口。函數原型:
int sched_setscheduler(struct task_struct *p, int policy, const struct sched_param *param);
入參說明
- p:指向目標任務(線程或進程)的 task_struct 結構體的指針。
- policy:調度策略。
- param:指向 sched_param 結構體的指針,包含了調度參數,如優先級。
kthread_create_worker + sched_setscheduler 創建線程并設置調度策略和優先級:
static int __init my_module_init(void) {struct sched_param param;int ret;// 創建內核線程工作隊列my_worker = kthread_create_worker(0, "my_worker");// 獲取內核線程的task_structmy_worker_thread = my_worker->task;// 設置調度策略和優先級param.sched_priority = MAX_RT_PRIO - 1; // 設置為最高實時優先級ret = sched_setscheduler(my_worker_thread, SCHED_FIFO, ¶m);return 0;
}
kthread_create + sched_setscheduler 創建線程并設置調度策略和優先級:
// 線程函數
static int thread_function(void *data) {while (!kthread_should_stop()) {}return 0;
}static int __init my_module_init(void) {struct sched_param param;int ret;// 創建內核線程my_thread = kthread_create(thread_function, NULL, "my_thread");// 設置調度策略和優先級param.sched_priority = MAX_RT_PRIO - 1; // 設置為最高實時優先級ret = sched_setscheduler(my_thread, SCHED_FIFO, ¶m);// 啟動內核線程wake_up_process(my_thread);return 0;
}
2.2 調度策略
-
SCHED_NORMAL:普通調度策略,也稱為 SCHED_OTHER。Linux 默認的普通任務調度策略,基于時間片輪轉調度算法,適用于大多數用戶進程和內核線程。
-
SCHED_FIFO:先進先出調度策略。使用該策略時,系統優先調用高優先級的任務,想通優先級的任務按照先到先服務的順序執行,只有在隊列中所有優先級最高的任務都執行完或者放棄 CPU 后,才會執行其他任務。優先級使用 sched_param 結構中的 sched_priority 成員設置,值越小優先級越高(0 最高)。
-
SCHED_RR:循環調度策略。優先高優先級任務+相同優先級先進先出+每個任務時間片輪轉,類似于 SCHED_FIFO,但每個任務有一個時間片,如果任務在該時間片內沒有運行完畢,會將任務移到隊列末尾等待下一輪調度。也可以通過 sched_param 結構的 sched_priority 設置優先級。
-
SCHED_BATCH:用于低優先級任務的批處理。用于大量計算密集型任務,通常在系統負載較低時,調度器會執行 SCHED_BATCH 線程。
-
SCHED_IDLE:專為低優先級的后臺任務設計。只有在沒有其他更重要的任務需要執行時,才會考慮執行 SCHED_IDLE 線程。
-
SCHED_DEADLINE:允許任務在預定的截止時間內完成執行,以滿足實時系統對任務響應時間的嚴格要求。deadline 調度策略為每個任務分配固定的 CPU 時間片(Budget),并指定每個周期內允許執行的最大時間量(Period)。
參考:
SCHED_FIFO與SCHED_OTHER調度機制
【Linux 內核】進程管理 - 進程優先級 ② ( prio 調度優先級 | static_prio 靜態優先級 | normal_prio 正常優先級 | rt_priority 實時優先級 )