在上一篇《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调度策略