【问题标题】:why does the linux kernel thread hog up cpu为什么linux内核线程占用cpu
【发布时间】:2015-01-13 13:35:38
【问题描述】:

我在内核模块中使用 kthread_run 创建了一个内核线程。 线程很简单,如下所示。

static  int my_thread_func(void * data)
{
    int a;
    DBG_PRINT("policy:%lu; prio:%d", current->policy, current->prio);
    while (!kthread_should_stop()) 
    {
        a++;
    }
}

但是,我加载完模块后,系统就没有反应了。

所以我想知道这个内核线程的调度策略和优先级是什么。 然后我尝试打印出这个内核线程的调度策略和优先级, 并得到以下输出。

政策:0;优先:120

policy:0 表示 SCHED_NORMAL;
prio:120 这个也不高。

虽然线程没有 SCHED_FIFO 或 SCHED_RR 调度策略,为什么它会占用 cpu?

而且我还发现,如果我在线程的循环体中插入一些休眠代码,系统可以保持响应。

我还发现,当我运行如下实现的用户空间程序时,系统也保持响应。

int main(int argc, char *argv[])
{
    int a;
    while (1) a++;
    return 0;
}

那么谁能告诉我,为什么内核线程会占用 CPU。

【问题讨论】:

  • 你的内核线程永远不会产生控制(wait_event_interruptible 和朋友),所以它当然会阻止事件被处理。它也不处理信号。
  • 但是内核线程的调度策略是SCHED_NORMAL,而不是SCHED_FIFO或SCHED_RR,所以一旦内核线程用完它的时间片,其他任务就有机会运行。
  • 只有当你将控制权让给内核时,你才不会。
  • 在我的理解中,内核线程应该被定时器中断所打断。而在定时器中断处理中,内核有机会检查线程的时间片,并调用schedule来选择另一个任务来运行。

标签: linux-kernel


【解决方案1】:

当您说优先级是120 时,您是在观察kthreadd 的优先级,还是为您创建的实际内核线程?

有关用于创建新内核线程的函数,请参阅http://lxr.free-electrons.com/source/kernel/kthread.c#L310

摘录:

struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
                                           void *data, int node,
                                           const char namefmt[],
                                           ...)
{
    ...
        if (!IS_ERR(task)) {
                static const struct sched_param param = { .sched_priority = 0 };
                ...
                /*
                 * root may have changed our (kthreadd's) priority or CPU mask.
                 * The kernel thread should not inherit these properties.
                 */
                sched_setscheduler_nocheck(task, SCHED_NORMAL, &param);
                set_cpus_allowed_ptr(task, cpu_all_mask);
        }
    ...
}

看来sched_priority 设置为0

现在,请看http://lxr.free-electrons.com/source/include/linux/sched/prio.h#L9

摘录:

/*
 * Priority of a process goes from 0..MAX_PRIO-1, valid RT
 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
 * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
 * values are inverted: lower p->prio value means higher priority.
 *
 * The MAX_USER_RT_PRIO value allows the actual maximum
 * RT priority to be separate from the value exported to
 * user-space.  This allows kernel threads to set their
 * priority to a value higher than any user task. Note:
 * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
*/

请注意第二段:This allows kernel threads to set their priority to a value higher than any user task.

总结:

新创建的内核线程似乎设置为sched_priority0,即使使用SCHED_NORMAL0 的优先级不是 SCHED_NORMAL 的正常优先级,因此内核线程将优先于任何其他线程(即不使用 RT 策略——而且我认为内核中没有任何进程默认使用 RT)。

附录:

注意:我不能 100% 确定这是否是原因。但是,如果您在内核中查看内核线程的 cmets,它们似乎都暗示内核线程一直在运行,除非:

  • 内核线程本身产生或调用do_exit
  • 别人打电话给kthread_should_stop()

在我看来,内核线程想运行多久就运行多久,直到它决定停止,或者其他人明确告诉它停止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 2014-09-16
    • 2023-03-06
    • 2017-03-02
    • 1970-01-01
    • 2019-04-08
    • 2013-05-11
    相关资源
    最近更新 更多