linux内核的系统关闭如何在内部工作?

hum*_*ace 35 shutdown linux-kernel

我对用户空间和初始化系统(无论是经典的 init sysV /upstart/systemd)如何在系统关闭时工作有一个粗略的想法。(本质上有“停止!”、“请真正停止”、“过程我需要杀死你才能停止”和等待......事情正在进行中的顺序)。

无论如何,我非常不知道系统关闭在内核中是如何工作的(肯定还有很多事情要做)?

我试图查看内核文档https://www.kernel.org/doc/htmldocs/,甚至使用NSA 的 pal 搜索工具让我先了解它是如何工作的。

我还搜索了 SE U+L 并没有发现任何东西(我是否忽略了它?)

无论如何,这个问题虽然可能有点挑战性,但值得在这个问答网络中得到答案,因为我认为更多的人有兴趣了解关闭时 linux 内核中发生的情况。

可能还有更改以链接到一些更详细的解释。

答案可能包括使用了哪些系统调用和哪些内核信号?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c 似乎是与重启相关的 x86 使用文件(已经接近关闭,嗯?)

也许在这里找到的片段http://lxr.free-electrons.com/source/kernel/reboot.c#L176 可以用来解释

第176话
177 {
第178话
第179话
第180话
第181话
第182话
183 pr_emerg(“断电\n”);
184 kmsg_dump(KMSG_DUMP_POWEROFF);
第185话
第186话
第187话

Gil*_*il' 34

了解 Linux 内核如何工作的主要资源是:

  1. 文档
  2. Linux 每周新闻文章
  3. 来源。这是一个复杂的野兽,通过Linux 交叉引用LXR更容易理解。在lxr.linux.no上运行的 LXR 变体比其他变体更好,但它经常停机。

在这种情况下,我在文档或 LWN 上找不到任何与中心相关的内容,所以是 LXR。

用户态代码所做的最后一件事是调用reboot系统调用。它需要 4 个参数,因此SYSCALL_DEFINE4(reboot在 LXR 上搜索,这会导致kernel/reboot.c. 检查调用者的特权和参数后,系统调用入口点调用的几个功能之一:kernel_restart重新启动,kernel_halt要在紧密的循环停止,kernel_poweroff以关闭系统电源,kernel_kexec通过更换一个新的内核(如编译),或hibernate断电前将内存保存到磁盘。

kernel_restartkernel_halt并且 kernel_power_off非常相似:

  1. Go through reboot_notifier_list,这是内核组件可以注册以在掉电时执行代码的钩子列表。在这个阶段只有少数驱动程序需要执行代码,主要是看门狗。
  2. 设置system_state变量。
  3. 禁用 usermode-helper,以确保不再启动用户代码。(在此阶段仍可能存在现有流程。)
  4. 调用device_shutdown以释放或关闭系统上的所有设备。许多司机都进入了这个阶段。
    请注意,此时仍挂载的任何文件系统都将被有效地强制卸载。系统调用的调用者负责任何干净的卸载。
  5. 仅用于关机,如果配置了 ACPI,可能会执行代码准备进入 ACPI 状态 S5(软关机)。
  6. 在多 CPU 机器中,代码可以在任何 CPU 上运行,无论哪个 CPU 调用系统调用。migrate_to_reboot_cpu注意切换到一个特定的 CPU 并防止调度程序在其他 CPU 上分派代码。在此之后,只有一个 CPU 正在运行。
  7. syscore_shutdown调用已注册的 syscore 操作shutdown方法。我认为这主要是关于禁用中断;很少有钩子有方法。shutdown
  8. 记录信息消息 - 天鹅之歌。
  9. 最后通过调用machine_restart,machine_halt或以某种依赖机器的方式休息machine_power_off

冬眠代码经过以下步骤:

  1. 遍历电源管理挂钩
  2. 同步文件系统。
  3. 冻结所有用户代码
  4. 防止设备热插拔
  5. 将系统状态转储到交换空间。
  6. 如果一切顺利,让硬件休眠。这可能涉及调用kernel_restartkernel_haltkernel_power_off或某些特定于平台的休眠方法。

关闭系统的另一种方法是machine_emergency_restart。这是由神奇的 SysRqB调用的。在O关键的工作方式不同:它调用kernel_power_off

系统也可能因恐慌而关闭,即出现不可恢复的错误。恐慌尝试记录一条消息,然后重新启动系统(通过硬件看门狗或紧急重启)。


hum*_*ace 2

这只是部分答案,我肯定会邀请其他答案,这可能会更详尽和清晰。

这个答案的内容取自3.13 linux内核的kernel/reboot.c文件(这可能不是第一个猜测,因为名称不是shutdown.c而是reboot.c)

无论如何,我们基本上有三个函数来描绘关闭系统的过程

  • void kernel_halt(void)// 以系统处于停止状态结束
  • void kernel_power_off(void)// 以系统关闭结束
  • void kernel_restart(char *cmd)// 结束系统并重新启动它

这些函数非常简短,因此可以完整地粘贴到此处。他们的代码最好地展示了内核关闭过程中所采取的步骤。(这些评论是我写的,可能不是100%理想和正确,请自己检查一下是否确定。这很简单,尝试一下。

void kernel_halt(void)

无效内核停止(无效)
{
    // 第一步:
    // a) 调用函数/回调注册为在重新启动/关闭时运行
    // b) 将 system_sate 设置为 SYSTEM_HALT
    // c) 停止 userspacetool 交互
    // d) 调用 device_shutdown() 函数
    kernel_shutdown_prepare(SYSTEM_HALT);

    // 第二步:我认为这对于多CPU系统来说是必需的
    migrate_to_reboot_cpu();

    // 第三步:
    // syscore_shutdown - 执行所有已注册的系统核心关闭回调
    syscore_shutdown();

    // 第四条消息
    pr_emerg("系统停止\n");
    kmsg_dump(KMSG_DUMP_HALT);

    // 第 5 个调用架构特定的 cpu-halt-code
    machine_halt();
}

整个事情是通过sys_reboot系统调用启动的,考虑到它不仅会重新启动而且还会关闭,无论如何都不是与关闭过程连接的直接事情。