首页 文章

为什么在Linux内核中繁忙的循环时,为了TOO,进程被剥夺了CPU的权限?

提问于
浏览
11

乍一看,我的问题可能看起来有点微不足道 . 请耐心等待,并完整阅读 .

我在Linux内核模块中发现了一个繁忙的循环 . 因此,其他进程(例如sshd)在很长一段时间内(例如20秒)没有获得CPU时间 . 这是可以理解的,因为我的机器只有单个CPU,繁忙循环没有机会安排其他进程 .

只是为了实验,我在忙循环中的每次迭代后添加了schedule() . 即使这会使CPU保持忙碌,但仍应让其他进程运行,因为我正在调用schedule() . 但是,这似乎并没有发生 . 我的用户级进程仍然在很长一段时间内(20秒)挂起 .

在这种情况下,内核线程得到了很好的值-5和用户级线程得到了很好的值0.即使用户级线程的优先级较低,我认为20秒太长而无法获得CPU .

有人可以解释为什么会发生这种情况吗?

注意:我知道如何完全删除繁忙的循环 . 但是,我想在这里理解内核的行为 . 内核版本为2.6.18,禁用内核抢占 .

1 回答

  • 2

    schedule() 函数只是调用调度程序 - 它没有采取任何特殊措施来安排调用线程将被另一个调用 . 如果当前线程仍然是运行队列中的最高优先级线程,则调度程序将再次选择它 .

    听起来好像你的内核线程在繁忙的循环中做了很少的工作,并且它每次都在调用 schedule() . 因此,它的优先级降低了很多 . 负值较好的值比正值更重,因此-5和0之间的差异非常明显 . 这两种效果的结合意味着我对用户空间进程错失并不感到惊讶 .

    作为一个实验,您可以尝试在循环的每第N次迭代中调用调度程序(您将不得不尝试为您的平台找到N的良好值)并查看情况是否更好 - 通常调用 schedule() 会浪费大量的调度程序中的CPU时间 . 当然,这只是一个实验 - 正如您已经指出的那样,避免繁忙循环是 生产环境 代码中的正确选项,如果您想确保您的线程被另一个替换,那么在调用 schedule() 之前将其设置为 TASK_INTERRUPTIBLE 远离运行队列的远程(正如评论中已经提到的那样) .

    请注意,您的内核(2.6.18)正在使用O(1)调度程序,该调度程序一直存在,直到在2.6.23中添加Completely Fair Scheduler(O(1)调度程序已添加到2.6以替换更旧的O(n) scheduler) . 然而,CFS并不熟悉它,所以我不会看到.1831322_d . 我'd use on heavily loaded SMP systems with a large number of both cores and processes, but I also accept that writing a scheduler is a very tricky task and it'这个词远远不是最糟糕的我在4-8核心台式机上从来没有遇到过重大问题 .

相关问题