我在Linux内核模块中确定了一个繁忙的循环.因此,其他进程(例如sshd)在长时间(如20秒)内没有获得cpu时间.这是可以理解的,因为我的机器只有单个cpu,而忙环没有机会安排其他进程.
只是为了实验,我在忙碌的循环中每次迭代后添加了schedule().即使这样做会使cpu处于繁忙状态,但是它仍然会让其他进程运行,因为我正在调用schedule().但是,这似乎并没有发生.我的用户级别进程长时间悬停(20秒).
在这种情况下,内核线程得到不错的值-5,用户级别线程得到很好的值0.即使用户级别线程的优先级低,我认为20秒太长,不能得到cpu.
有人可以解释为什么会发生这种情况吗?
注意:我知道如何彻底清除繁忙的循环.但是,我想在这里了解内核的行为.内核版本为2.6.18,内核抢占功能被禁用.
解决方法
听起来好像你的内核线程在繁忙的循环中做的很少,每次都调用schedule().因此,它本身可能没有使用太多的cpu时间,因此没有将其优先级降低很多.负的漂亮值比正面值更重,所以-5和0之间的差异是相当明显的.这两个效果的结合意味着我不会惊讶于用户空间进程错过了.
作为一个实验,您可以尝试在循环的第N次迭代中调用调度器(您必须尝试为您的平台找到N的良好值),并查看情况是否更好 – 调用schedule()太频繁,将浪费调度程序中有大量cpu时间.当然,这只是一个实验 – 正如你已经指出的那样,避免繁忙的循环是生产代码中的正确选项,如果你想确保你的线程被另一个替换,然后在调用schedule之前将其设置为TASK_INTERRUPTIBLE )从运行队列远程本身(如在注释中已经提到的).
请注意,您的内核(2.6.18)正在使用存在的O(1)调度程序,直到在2.6.23中添加了Completely Fair Scheduler(在2.6中添加了O(1)调度程序以替换较旧的O(n) scheduler). CFS不使用运行队列并以不同的方式工作,所以您可能会看到不同的行为 – 但我不太熟悉,所以我不想准确地预测你会看到什么差异.我已经看到足够的知道,“完全公平”不是我在大量的核心和进程的大量加载的SMP系统上使用的术语,但是我也接受写一个调度器是一个非常棘手的任务,远远不及我见过的最糟糕的一面,而我在4-8核心台式机上从未遇到过重大问题.