LINUX_REBOOT_CMD_RESTART2를 사용하여 restart() 명령 문자열 arg를 언제 어떻게 실행합니까?

LINUX_REBOOT_CMD_RESTART2를 사용하여 restart() 명령 문자열 arg를 언제 어떻게 실행합니까?

이것restart() 맨페이지설명하다

LINUX_REBOOT_CMD_RESTART2

(0xa1b2c3d4; Linux 2.1.30부터). "'%s' 명령으로 시스템을 다시 시작하는 중"이라는 메시지를 인쇄하고 즉시 다시 시작합니다(arg에 지정된 명령 문자열 사용). 이전 동기화(2)가 없으면 데이터가 손실됩니다.

종료 프로세스 중에 arg에 제공된 명령 문자열이 정확히 언제 어떻게 실행됩니까?

https://unix.stackexchange.com/a/489651/674에 대해 말하다LINUX_REBOOT_CMD_RESTART2

reboot() 여기서 추가적인 혼란은 시스템 호출이 다시 시작을 수행하는 프로세스를 실행할 수 있는 것처럼 보이기 때문에 발생합니다 (그러나 이것은 작동합니다).

arg에 제공된 명령 문자열은 커널이 종료되기 전에 실행되므로 커널이 종료되기 전에 명령이 일부 정리 작업을 수행할 수 있습니까?

감사해요.

답변1

명령은아니요종료 중에 실행됩니다. 이는 쉘 명령이나 이와 유사한 것이 아닙니다. machine_restart()일부 드라이버(watchdog 등)에 의해 do_kernel_restart()등록된 다시 시작 핸들러에 콜백 데이터( => 를 통해)로 전달되어야 하는 문자열입니다 .register_restart_handler()

그러나 이 메커니즘은 x86에서는 사용되지 않습니다. 거기의 "명령"은 완전히 무시됩니다. ~에서arch/x86/kernel/reboot.c:

void machine_restart(char *cmd)
{
        machine_ops.restart(cmd);

struct machine_ops machine_ops __ro_after_init = {
        ...
        .restart = native_machine_restart,

static void native_machine_restart(char *__unused)
{

이 문자열은 등록된 핸들러에도 전달됩니다.register_reboot_notifier(). 유일하게 (학대) 사용된 드라이버는 다음과 같습니다.EFI 부트로더 제어비휘발성 설정입니다.LoaderEntryOneShotEFI 변수를 사용하면 일부 부트 로더가 다음에 부팅해야 할 운영 체제를 결정하게 됩니다. 이 드라이버는 Android 외부에서 사용된 적이 없는 것 같습니다. 하지만 이전 lml에도 자세히 설명되어 있기 때문에 어쨌든 투박해 보입니다.논의하다이전 버전도 마찬가지입니다.

답변2

구현되지 않았습니다. 이 명령에는 재시작 원인 레지스터에 쓰기 위해 재시작 모드 드라이버로 전달되는 해당 값이 있습니다. 재부팅 후 부트로더는 레지스터에서 원인 값을 읽고 빠른 부팅, 복구 등 선택한 명령에 따라 부팅을 결정합니다.

예를 들어 Qualcomm MSM8916 SOC 기반 전화기에는 재부팅 이유 레지스터가 포함된 전원 켜기 장치가 있습니다. 명령(형식 mode-<command>)과 해당 이유 값은 다음에 설명되어 있습니다.장치 트리:

pon@800 {
        compatible = "qcom,pm8916-pon";
        reg = <0x800>;
        mode-bootloader = <0x2>;
        mode-recovery = <0x1>;

따라서 명령 문자열을 reboot(2)사용하여 호출하면bootloader운전사부팅 장치의 경우 0x2다시 시작 이유 레지스터에 기록합니다.

다음에 부팅할 때 부트로더(예: lk2nd)는 원인 레지스터를 확인하고 적절한 모드로 부팅합니다 aboot_init().aboot.c):

#if USE_PON_REBOOT_REG
    reboot_mode = check_hard_reboot_mode();
#else
    reboot_mode = check_reboot_mode();
#endif
    if (reboot_mode == RECOVERY_MODE)
    {
        boot_into_recovery = 1;
    }
    else if(reboot_mode == FASTBOOT_MODE)
    {
        boot_into_fastboot = true;
    }

RECOVERY_MODEFASTBOOT_MODElk2nd에 정의되어 있습니다 .재시작.h위의 장치 트리와 동일한 값을 갖습니다("fastboot"를 "bootloader"라고 함).

#define RECOVERY_MODE     0x01
#define FASTBOOT_MODE     0x02

이 동작을 테스트하기 위해 restart 명령을 사용할 수 있는 유틸리티에 대해서는 모르지만 ctypes를 사용하여 Python에서 이 작업을 수행할 수 있습니다.

python -c "import ctypes; ctypes.CDLL('libc.so').syscall(142, 0xfee1dead, 0x20112000, 0xa1b2c3d4, b'bootloader')"

142위는 reboot(2)arm64의 시스템 호출 번호입니다. 16진수 매직넘버는 에서 나옵니다 man 2 reboot.

관련 정보