When used the way you have it, halt uses reboot
syscall.
halt
When called with --force or when in runlevel 0 or 6, this tool invokes the reboot(2) system call itself and directly reboots the system. Otherwise this simply invokes the shutdown(8) tool with the appropriate arguments. Source: https://linux.die.net/man/8/halt
shutdown
, is not a syscall but an application. It goes through other system utilities to gracefully shutdown by closing applications and daemons in a defined order (specific to OS)
From the pov of the SD Card Health, the reboot
syscall will safely halt the kernel and machine, it will also sync
the file system and all that so it will preserve, for most purposes, the systems ability to boot without corruption.
However, any application state that has not been saved or written to kernel buffers will be lost. shutdown
will generally send signals to applications before killing them outright, reboot
bypasses any process level gracefuleness.
IMO for a power consumption experiment, the small risk of corruption is not a big deal, for production use that is another matter. I have used it myself to conduct similar experiments to what you are proposing in a commercial setting. To be more sure, you can explicitly invoke sync before the hard halt
sync && halt -f
Kernel Details
reboot
in this case is a system call implemented in kernel/reboot.c
that will eventually trigger either machine_restart
, machine_halt
, or machine_poweroff
in the arm specific architecture files reboot.c
Note: In kernel land shutdown
is used to restart or switch kernels, and not the same as operating system shutdown utility. reboot
is a system call that handles restart
, halt
and poweroff
The kernel differentiates between halt
and poweroff
but only slightly, the poweroff
goes through any power management system. In the case of the BCM there is no ability to power off externally.
/**
* kernel_halt - halt the system
*
* Shutdown everything and perform a clean system halt.
*/
void kernel_halt(void)
{
kernel_shutdown_prepare(SYSTEM_HALT);
migrate_to_reboot_cpu();
syscore_shutdown();
pr_emerg("System halted\n");
kmsg_dump(KMSG_DUMP_HALT);
machine_halt();
}
EXPORT_SYMBOL_GPL(kernel_halt);
/**
* kernel_power_off - power_off the system
*
* Shutdown everything and perform a clean system power_off.
*/
void kernel_power_off(void)
{
kernel_shutdown_prepare(SYSTEM_POWER_OFF);
if (pm_power_off_prepare)
pm_power_off_prepare();
migrate_to_reboot_cpu();
syscore_shutdown();
pr_emerg("Power down\n");
kmsg_dump(KMSG_DUMP_POWEROFF);
machine_power_off();
}
EXPORT_SYMBOL_GPL(kernel_power_off);
(https://github.com/raspberrypi/linux/blob/rpi-4.14.y/kernel/reboot.c#L241-L268)
On the arm side this is even more straight forward, halt calls poweroff
void machine_halt(void)
{
machine_power_off();
}
/*
* 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();
}
I do not believe that the bcm
implementation defines any further specific pm_power_off
, but that would be very low level, chip clock and power management reset, well after the kernel is done closing up shop.
For an example of how this halt looks in C
, see this answer on so
#include <unistd.h>
#include <linux/reboot.h>
int main() {
reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF, 0);
}
which is equivalent to halt --poweroff -f
sync
command and any other process which may be not be killed before the filesystems are forcibly unmounted, and I'd like to avoid cutting the SDCard power before writes to the SDC are finished to avoid corrupted blocks. Or is that possible? Maybe I don't have to worry about a race condition, maybe it kills all other processes beforesync
is run?