如何在运行halt命令时使Linux系统关机?

5

我已经成功使用pm_power_off函数指针通过i2c调用自定义Linux板的电源管理芯片(关闭电源)。

我希望Linux的halt命令也可以关闭电源。

我该如何实现这个功能?

machine_halt的(ARM架构)代码没有像pm_power_offpm_power_off那样的指针。

arch/arm/kernel/reboot.c:

/*
 * Halting simply requires that the secondary CPUs stop performing any
 * activity (executing tasks, handling interrupts). smp_send_stop()
 * achieves this.
 */
void machine_halt(void)
{
    local_irq_disable();
    smp_send_stop();

    local_irq_disable();
    while (1);
}

/*
 * Power-off simply requires that the secondary CPUs stop performing any
 * activity (executing tasks, handling interrupts). smp_send_stop()
 * achieves this. When the system power is turned off, it will take all CPUs
 * with it.
 */
void machine_power_off(void)
{
    local_irq_disable();
    smp_send_stop();

    if (pm_power_off)
        pm_power_off();
}

我显然可以直接修改machine_halt,但如果可能的话,我想要以“正确”的方式解决这个问题。

我是否错过了什么东西(也许在用户空间中),会导致halt命令执行“关机”操作?


更新: 感谢答案和你们所有的评论,它们帮助我意识到实际问题是什么。

我的问题是:

我有一个输入边缘,可用于自定义电源管理单元。将其视为一个启动按钮,没有停止或重置功能。我完全控制PMU代码(它作为i2c从设备运行)。

  1. 如果Linux内核正在运行,我希望忽略这个边缘。
  2. 如果CPU已关闭电源,我希望这个边缘可以开启CPU电源。
  3. 如果Linux内核已停止,我希望这个边缘可以重置CPU。

情况1很容易,无需做任何事情。

情况2很容易,在我的驱动程序中定义pm_power_off,向PMU发送一条i2c消息。幸运的是,在调用pm_power_off时,i2c子系统仍处于工作状态。

情况3是问题所在-我正在寻找一个pm_halt进行定义,向PMU发送一条i2c消息。

也许有另一种方法,正如0andriy的评论那样?

在内核中是否有一个位置,可以以几个赫兹的频率不断地向PMU发送i2c消息,除非机器已停止halt

答案在这里:https://unix.stackexchange.com/a/42576/17288 :

"* 现在的halt足够聪明,如果启用了ACPI,会自动调用poweroff。实际上,它们现在在功能上是等价的。"

也许有一些方法可以提供或连接到ACPI-我将需要研究一下它。


正确的方式是不去碰它。当然,你可以设置看门狗,在超时后产生相同的效果。 - 0andriy
我非常确定你不想黑进 machine_halt();这个想法似乎是为了让用户模式能够对 pm_power_off() 不起作用做出反应,此时它可以通过系统调用记录并调用 machine_halt()。 - Joshua
@0andriy,你能给我指一些定期执行某些活动的内核驱动程序代码吗?我能否使用100Hz的滴答作为发送保持活动的提示方式? - fadedbee
2个回答

3
您应该使用poweroff命令或halt -p。根据man 8 halt的说法,halt命令(没有参数)不能保证关闭您的计算机电源。原因在这里描述:here:
“在ACPI之前使用halt(现在会为您关闭电源)*。它将停止系统,然后打印一条消息:“现在可以关闭电源了”。当时有物理开关,而不是现代计算机所控制的组合ACPI电源按钮。”
“*如今,如果启用了ACPI,则halt足够聪明,会自动调用poweroff。实际上,它们现在具有相同的功能。”
正如您从halt工具源代码中看到的那样,它发出带有cmd = RB_POWER_OFF = LINUX_REBOOT_CMD_POWER_OFFreboot()系统调用。
在内核中,该系统调用在此处实现,对于cmd = LINUX_REBOOT_CMD_POWER_OFF,它调用:
   -> kernel_power_off()
   -> machine_power_off()
   -> pm_power_off()

你正在关注用户空间/内核边界的错误方面。OP已经在内核中工作了 - 他们正在尝试实现LINUX_REBOOT_CMD_POWER_OFF的内核端。 - user149341
等等,我误读了问题。我对你的回答进行了空编辑,以便我可以取消我的错误点赞。 - user149341
@duskwuff 现在你提到了这个,我重新阅读了问题,但我不确定 OP 想知道什么(他是误用了 halt 工具,还是即使使用正确的命令也无法关闭他的板子,因为内核代码不完整)。我会等待一些回应,如果我误解了问题,我会删除我的答案。 - Sam Protsenko
@SamProtsenko 我不知道 RB_HALT_SYSTEM 不是关机所必需的 - 它可以关闭我的 x86 台式系统,可能是因为 ACPI。我已经提出了一个相关的问题:https://askubuntu.com/questions/870999/halt-is-not-powering-off-as-shutdown-h-now-does - fadedbee
似乎内核不在问题的范围之内。主要问题是您的用户空间应用程序。 - 0andriy
显示剩余2条评论

1
在Debian/Ubuntu系统上(我不知道其他Linux操作系统是否适用),如果您希望halt命令执行poweroff,您可以创建此文件:
/etc/default/halt

写下该文件的内容:

# Default behaviour of shutdown -h / halt. Set to "halt" or "poweroff".
HALT=poweroff

如该注释所述,你现在可以设置halt的工作方式。如果将其设置为halt,则仅会关闭计算机而不断电。如果设置为poweroff,则会像poweroff命令一样,在关闭所有内容后关闭计算机。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接