18.7.3. Logger 시스템의 전역 구독(Global Sniffing) 및 버퍼링 아키텍처

18.7.3. Logger 시스템의 전역 구독(Global Sniffing) 및 버퍼링 아키텍처

로보틱스 자율 비행 R&D 연구 및 상용 드론의 항공 사고원인 분석 등에서 가장 결정적인 원천 증거 능력(Evidence)을 발휘하는 것은 외부에서 비스듬히 찍힌 비디오 영상이 아니라, 드론 제어기 내부에서 0.001초(1ms) 단위 해상도로 기록된 바이너리 비행 로그(ULog)이다. PX4-Autopilot의 핵심 백그라운드 서비스 데몬 중 하나인 logger 모듈(Module)은 기체 메모리 버스 영역 내에서 쉴 새 없이 날아다니는 수십~수백 종류의 센서 및 제어 토픽들을 단 하나의 누락도 없이 가로채어(Sniffing) 외부 SD카드 스토리지에 압축 기록해내는 극한의 I/O 임무를 수행한다. 본 절에서는 C++ 임베디드 통신 시스템 개발자의 관점에서, 어떻게 logger 모듈이 메인 프로세서의 동작 부하율을 극단적으로 취소화하면서도 시스템 전역적인 토픽을 수집하고 버퍼링하는 아키텍처를 선사하는지 심층 분석한다.

1. 시스템 콜 부하 없는 전역 스니핑(Global Sniffing) 패턴

비행 중 수백 개의 상태 제어 및 센서 토픽 노드가 무작위로 동적 생성되고 소멸되는 과정 속에서, logger 모듈 담당자가 그 전체 명단(List)을 미리 코드 내에 하드코딩(Hard-coding)하여 가지고 있는 것은 오픈소스 아키텍처적으로 확장성이 전무한, 불가능에 가까운 방식이다.

이 설계적 한계를 돌파하기 위해 logger 모듈 구조체는 uORB 코어 매니저 데몬이 은밀히 제공하는 특수 디렉토리 트리 감시 체계를 지능적으로 차용한다.

  • logger는 단일 개별 토픽이 아닌, VFS(가상 파일 시스템) 상의 /obj 같은 uORB 통신 노드들이 물리적으로 결집 생성되는 디렉토리 루트의 “생성/변경 이벤트” 자체를 구독 모니터링한다.
  • 하드웨어에 새로운 뎁스(Depth) 카메라 포트 센서가 꽂히거나 새로운 커스텀 제어기가 부팅 시퀀스 중에 orb_advertise를 최초 호출하여 VFS 노드가 생성되면, logger 데몬은 이 인터럽트 이벤트를 즉각 감지하고 내부 루프에서 동적으로 구독(Subscription) 통신 핸들을 생성한 뒤, 자동으로 자신의 스니퍼 목록 배열에 백그라운드 병합(Hot Merge)시킨다.
    이러한 동적 바인딩 시스템 연결고리 덕분에, 프로그래머 개발자가 새로운 토픽을 추가하더라도 로거 클래스의 코드를 단 한 줄도 손댈 필요 없이, 다음번 비행부터 SD카드 ULog 파일에 구조체 분량의 새 데이터가 추가 직렬화되어 기록되는 마법 같은 모듈화(Modularity)가 실현된다.

2. 병목을 막는 거대 로깅 버퍼(Logging Buffer) 아키텍처

항공 비행 데이터 패킷의 순간 생성량은 초당 수 메가바이트(MB/s)에 육박할 수 있지만, 임베디드 보드에 꽂힌 범용 SD카드의 플래시 메모리 보급형 랜덤 쓰기(Random Write) 속도와 오픈소스 파일 시스템(FAT32 등)의 블로킹 지연 시간은 시스템 전체를 다운시킬 수 있는 매우 심각한 병목(Bottleneck) 구간이다.
만일 로터 모터 변속기(ESC)에 제어 PWM 신호를 지금 당장 뿌려야 하는 최상위 EKF2 스레드가 데이터를 VFS에 발행(Publish)하는 그 순간, logger 데몬이 SD카드 섹터 기록 I/O 블로킹 늪에 걸려 시스템 메인 버스가 수십 밀리초간 멈춰버린다면, 드론은 즉시 기체 균형을 잃고 0.1초 안에 추락할 것이다.

이 치명적인 재플 현상을 원천 차단하기 위해 logger 모듈은 내부 힙(Heap) 공간에 거대한 링 버퍼(Ring Buffer) 방파제를 독립 구축한다.

  1. 독립된 스레드와 비동기 큐 (Asynchronous Event Queue): logger 프로세스는 EKF2mc_pos_control 같은 생존 직결 모듈들보다 상대적으로 낮은 우선순위(Priority)로 격리 스케줄링되어 컨텍스트를 분리 받는다.
  2. 초고속 프론트엔드 캐싱 (Frontend Caching): uORB 토픽 데이터가 발생 구역에서 도달하면, logger는 절대로 느려터진 SD카드를 바로 건드리지 않는다. 대신 시스템 부팅 시 미리 RAM에 큼지막하게 연속 할당해 놓은 (보통 수십~수백 KB 규모) 로깅 전용 링 버퍼 블록에 시스템 memcpy 콜만 재빨리 수행하고 즉시 잠들거나 빠져나간다. 이 행위는 불과 수십 나노초만이 소모되므로 메인 CPU 연산 버스에 아무런 타이밍 악영향을 주지 못한다.
  3. 백그라운드 백엔드 플러시 (Backend SD Flush): 이후 SD 카드 드라이버 I/O 스레드가 CPU 유휴 시간 여유가 생길 때마다, 버퍼(Buffer)에 누적된 이진 데이터를 통짜 청크(Chunk) 단위로 뭉텅이로 떠서 파일 마운트 인터페이스(write(), fsync())에 한꺼번에 밀어 부어 넣어 쓰기 효율을 극대화한다.

3. Drop 전략 (데이터 보존과 시스템 생존 간의 처절한 트레이드오프)

비행 테스트 증 SD카드의 물리적 섹터 품질이 불량하여 백엔드 플러시(Flush)가 제때 이루어지지 못해, RAM 내의 링 버퍼가 100% 임계치로 가득 차버리는 아찔한 오버플로우(Overflow) 순간이 도래한다면, logger의 C++ 로직의 정책적 선택은 매우 단호하고 가혹하다. 메모리 확보를 위해 상위 시스템 지연(System Stalling)을 유발하며 블로킹(Block) 대기하는 대신, 과감하게 지금 방금 도착한 최신 귀중한 로깅 데이터 배열을 허공 바닥에 버리는 드롭(Drop)을 감수한다.

이러한 “로깅 파일의 유실(Data Dropout)을 감수하고서라도 기체 메인 루프의 절대적인 하드 실시간성(Hard Real-time)을 최우선으로 옹호한다“는 뼈를 깎는 설계 철학은, PX4-Autopilot이 그 어떤 악하 환경의 외부 하드웨어 결함 속에서도 비행체의 물리적 자세 생존(Survival) 하나만큼은 절대적 가치로 보장하도록 만드는 견고하고 냉혹한 아키텍처의 위대한 산실이다.