21.9.3.2. 기체 전원 차단 전 이벤트 수신 및 리소스 완전 반환

21.9.3.2. 기체 전원 차단 전 이벤트 수신 및 리소스 완전 반환

리눅스 데스크톱 환경에서는 컴퓨터 전원을 끌 때 운영체제가 알아서 열려있던 크롬 브라우저를 닫고 램(RAM)을 털어내 준다.
그러나 픽스호크 보드와 같은 임베디드 실시간 운영체제(RTOS) 환경에서는, 펌웨어 코어의 셧다운(Shutdown) 혹은 강제 리부트(Reboot) 시그널이 도달하는 그 찰나의 순간에 데몬들이 자기 입에 물고 있던 센서 버스 락(Lock)이나 구독권(Subscription)을 스스로 뱉어내고 자결하지 않으면, 낸드 플래시 메모리(NAND Flash) 파일 시스템이 통째로 깨져버리는 끔찍한 사태(Corruption)가 벌어지기도 한다.

따라서 PX4에 기생하는 모든 백그라운드 모듈은 전원 코드가 뽑히거나 QGC에서 ‘Reboot’ 버튼이 눌리는 그 비극의 순간을 미리 귀띔받고 옷정리를 할 수 있는 ’최후의 클린업(Cleanup) 시퀀스’를 의무적으로 장착해야 한다.

1. 하드웨어 리부팅 통지 시스템

픽스호크 시스템이 셧다운/리부팅에 돌입할 때, 커맨더(Commander) 모듈은 vehicle_command 토픽을 통해 전역에 VEHICLE_CMD_PREFLIGHT_REBOOT_SHUTDOWN 이라는 긴급 명령어를 브로드캐스팅(Broadcasting)한다.

이 긴급 재난 문자를 수신한 데몬은 즉시 하던 일을(펌웨어 계산이든, 서보 구동이든) 모두 집어 던지고 **파괴자 루틴(Destructor Routine)**으로 진입해야 한다.

우리의 PayloadAutoDrop 클래스에도 이 죽음의 마라카스를 듣는 귀를 달아주자. 우리는 FSM 구동을 위해 이미 만들어두었던 vehicle_command 수신부(_vehicle_command_sub)를 재활용할 것이다.

참고: 앞선 장들에서는 설명의 편의를 위해 vehicle_command_ack만 구독하고 명령 하달 위주로 설명했으나, 실무에서는 외부에서 들어오는 취소(Cancel)/리부팅 명령에 대응하기 위해 모듈 스스로도 vehicle_command 구조체를 구독(Subscription) 해 두는 것이 정석이다.

void PayloadAutoDrop::check_for_shutdown_signals() {
    
    vehicle_command_s cmd{};
    
    // 만약 파이프(uORB)를 타고 누군가 내 모듈이나 전역에 명령을 내렸다면?
    while (_vehicle_command_sub.update(&cmd)) {
        
        // 1. 그 명령이 바로 '전원 차단 / 리부트' 명령인가?
        if (cmd.command == vehicle_command_s::VEHICLE_CMD_PREFLIGHT_REBOOT_SHUTDOWN) {
            
            PX4_WARN("Caught REBOOT_SHUTDOWN command. Commencing safe shutdown!");
            
            // 2. 액추에이터 보호: 셧다운 중 서보가 임의로 튀지 않게 안전 모드(0.0)로 잠금
            close_payload_servo_safely();

            // 3. 스스로 종료(Stop) 커맨드를 자신에게 주입한다.
            // (내부적으로 WorkQueue 태스크를 터뜨리고 객체를 소멸시키는 함수)
            request_stop(); 
        }
    }
}

request_stop() 이라는 방아쇠가 당겨지면, C++ 스코프 소멸자(~PayloadAutoDrop())가 연쇄적으로 호출되며 놀라운 해체 쇼가 벌어진다.

이 해체 쇼의 디테일과, 스케줄러(Worker Thread)의 강제 인터럽트(Interrupt) 기술을 21.9.3.2.1장에서 마저 수술해 보도록 하자.