在上一篇《Linux的高優先級workqueue》中,我們使用 highpri workqueue來實現高優先級,但是這種方法有個缺陷:如果work的執行時間比較長的話,還是會被normal workqueue的其它任務打斷。原因是highpri workqueue只是調整了線程的nice值,只是獲得更多的CPU時間片,而不是佔有CPU直到任務執行完畢。
通過 kthread_worker 和 sched_setscheduler設置爲SCHED_FIFO,從而將線程的優先級設置爲RT級別,以保證任務優先被執行。參考代碼如下:
struct kthread_worker test_kworker;
struct task_struct *test_kworker_task;
struct kthread_work test_kwork;
static void test_kthread_work_handle(struct kthread_work *work)
{
struct timeval t;
u64 usec = 0;
static int cnth = 0;
printk("%s enter\n", __FUNCTION__);
do_gettimeofday(&t);
usec = t.tv_sec*1000000+t.tv_usec;
for (;;)
{
do_gettimeofday(&t);
if (t.tv_sec*1000000+t.tv_usec > usec + 3000)
{
cnth++;
printk("kwork = %d\n", cnth);
if (cnth >= 500)
break;
usec = t.tv_sec*1000000+t.tv_usec;
}
}
printk("%s exit\n", __FUNCTION__);
}
void test_kthread_queue(void)
{
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 10 };
init_kthread_worker(&test_kworker);
test_kworker_task = kthread_run(kthread_worker_fn,
&test_kworker, "test kthread worker");
if (IS_ERR(test_kworker_task)) {
printk("failed to create message pump task\n");
return;
}
init_kthread_work(&test_kwork, test_kthread_work_handle);
sched_setscheduler(test_kworker_task, SCHED_FIFO, ¶m);
}
關於linux的優先級
Linux系統中,進線程優先級是0~139,nice的範圍是 -20 ~ 19。值越小,優先級越高。優先級 0 ~ 99屬於RT級,可以使用SCHED_FIFO調度策略,100 ~ 139屬於普通級,一般使用SCHED_NORMAL/SCHED_BATCH。默認情況下創建的task優先級是120,即對應nice值爲0。
注:不是所有的linux系統都支持SCHED_FIFO調度策略