进一步阅读

进一步阅读

我正在读start_kernel函数在/init/main.c.最后调用的函数start_kernel是,并且在的rest_init末尾被调用。rest_initcpu_idle

为什么它被称为start_kernel例程的最后一个函数,它的作用是什么?

答案1

回答你的第一个问题,

有什么cpu_idle作用?

一般来说(不考虑问题的上下文),当CPU处于空闲状态时,这意味着内核当前没有CPU可以执行的工作,因此CPU正在空闲地等待内核的更多工作。

您可以将内核视为管理器,将工作交给 CPU(根据时间表)。当CPU没有可用的工作时,CPU将进入空闲状态并等待中断。您可以阅读有关 CPU 中断的更多信息这里

关于您的问题的上下文,您可以阅读以下内容的确切实现cpu_idle做:

cpu_idle(void)
{
    set_thread_flag(TIF_POLLING_NRFLAG);

    while (1) {
        /* FIXME -- EV6 and LCA45 know how to power down
           the CPU.  */

        while (!need_resched())
            cpu_relax();
        schedule();
    }
}

总而言之,cpu_idle就是让CPU进入空闲状态。这是通过while在需要时使用循环来处理进程调度来实现的;否则,CPU 将处于空闲状态cpu_relax

为什么它被称为start_kernel例程的最后一个函数?

该函数作为例程中的最后一条指令执行的原因start_kernel是因为CPU已经执行了启动内核所需的所有工作 - 不会再执行进一步的指令,因此CPU将变得空闲,等待下一个任务或中断。为了表明这一点,CPU 应置于空闲状态,因为内核初始化不再需要它。

答案2

中央处理器必须始终执行某物。如果无事可做,它就会陷入无限循环,中断(例如系统心跳中断)会将其打破。

在较旧的多进程/多线程操作系统中,如果调度程序(选择并切换到下一个线程以运行可运行线程队列的低级调度程序)发现没有准备好运行的线程,它只会进入这样的无限状态环形。

这是一个困扰多方的问题处理器但是,操作系统,因为无限循环是在调度程序离开的任何线程的上下文中执行的。这可能最终导致同一个线程同时在两个处理器上“运行”,从而导致一系列问题。

因此,更新的(也就是说,相对更新的;因为这个想法已有几十年的历史)设计是,对于系统中的每个处理器,都有一个空闲线程。该线程除了无限循环之外什么也不做,并且是总是可运行。所以有总是调度程序可以选择的线程,并且永远不会出现没有可供处理器运行的可运行线程的情况。

在旧版本的实际 Unix 中,当系统初始化完成时,初始化代码已建立将其描述为进程 #0 的数据结构。由于它的作用,它有“交换进程”的传统名称。它必须做某物初始化完成后,它所做的就是运行在主 RAM 和 DASD 交换区域之间交换进程段的代码。

随着需求分页设计的出现,交换的想法在 20 世纪 70 年代末就消失了。进程 #0 成为第一个空闲进程然后是系统进程包含了所有的空闲线程

这也是 Linux 中正在发生的事情。

当然,电源管理在这一点上已经被考虑了超过四分之一个世纪,而无条件分支指令分支到自身的传统无限循环会导致大量不必要的繁忙工作和电力消耗。现代(又是一个相对术语)空闲线程调用特殊的处理器指令,指示执行处理器等待,可能会降低其时钟速率以节省电量,以使其接收硬件中断。 (多年来,在 x86 指令架构上,这种情况已经从hlt“超线程”处理器中的执行核心完全释放资源pause换取rep nop不涉及中断的跨处理器肩分流,有效地将空闲线程转变为永久线程。等待自旋锁。)

进一步阅读

相关内容