停止运行时如何使linux断电?

fad*_*bee 5 linux halt linux-kernel power-off

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

我也希望 Linuxhalt命令关闭电源。

我怎样才能做到这一点?

对于(ARM)代码machine_halt不具有指针类似于machine_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();
}
Run Code Online (Sandbox Code Playgroud)

我显然可以 hack machine_halt,但如果可能的话,我想“正确地”做到这一点。

我是否错过了可能导致halt命令执行“关闭电源”的某些内容(可能在用户空间中)?


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

我的问题是:

我有一个输入边缘,可用于自定义电源管理单元。把它想象成一个开始按钮,没有停止或重置功能。我可以完全控制 PMU 代码(它是一个作为 i2c 从设备运行的 ATMEGA)。

  1. 如果 Linux 内核正在运行,我希望边缘被忽略。
  2. 如果CPU断电,我想让边缘给CPU加电。
  3. 如果 Linux 内核停止,我希望边缘重置 CPU。

案例1很简单,没什么可做的。

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

情况 3 是问题 - 我正在寻找一个pm_halt来定义,将 i2c 消息发送到 PMU。

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

内核中是否有一个地方可以继续以几赫兹的频率用 i2c 消息刺激 PMU,除非机器被halted?

答案在:https : //unix.stackexchange.com/a/42576/17288内容如下:

“* 现在,如果启用 ACPI,halt 已经足够智能了,可以自动调用 poweroff。事实上,它们现在在功能上是等效的。”

也许有某种方式提供或连接到 ACPI - 我将不得不阅读它。

Sam*_*nko 3

您应该使用poweroff命令或halt -p. 根据man 8halthalt命令(不带参数)不能保证关闭您的机器。原因描述如下

halt在 ACPI 之前使用(今天将为您关闭电源)*。它会停止系统,然后打印一条消息,大意是“现在可以关闭电源了”。当时有物理开关,而不是现代计算机的组合 ACPI 控制电源按钮。

*现在halt已经足够智能,如果启用了 ACPI,可以自动调用关机功能。事实上,它们现在在功能上是等效的。

halt从工具源代码中可以看到,它发出了restart()系统调用,后缀为cmd = RB_POWER_OFF = LINUX_REBOOT_CMD_POWER_OFF.

在内核中,该系统调用在这里实现,在上cmd = LINUX_REBOOT_CMD_POWER_OFF,它调用:
   -> kernel_power_off()
   -> machine_power_off()
   ->pm_power_off()