19.5.3.1. 타이머 및 인터럽트 기반의 비동기 Work Queue 스케줄링 개념
우리가 앞선 수많은 단원들에서 온 신경을 곤두세워가며 주야장천 다루었던 while (!thread_should_exit) 기반의 블로킹(Blocking) 폴링 데몬들은, 시스템 스케줄러 관점에서 보면 마치 고급 레스토랑에서 웨이터(스레드) 한 명이 1번 테이블 앞에서 주방장(퍼블리셔)이 요리(데이터)를 무작정 내올 때까지 아무것도 안 하고 멍하니 서서 기다리는 극도의 1차원적인 원시 구조와 같다.
만약 PX4 펌웨어 전체 시스템이 이런 식으로 스레드 하나당 센서 파이프 하나씩을 1:1로 전담 마크하는 무식한 방식으로 짜여 구동된다면 어떻게 될까? 기판 위의 수십수백 개의 센서 프레임을 다루기 위해 수백 명의 웨이터(스레드 액터)를 메모리에 고용하여 띄워야만 하고, NuttX RTOS 커널 코어는 이 수많은 웨이터들의 작업 순서를 바꿔주느라(Context Switching Overhead) 정작 실제 요리(비행 매트릭스 데이터 제어 연산)는 단 한 줄도 하지 못하고 폭파되어 버리게 될 것이다.
1. Work Queue: 글로벌 시스템 스레드 풀(Thread Pool)의 혁명적 렌더링
이러한 개별 무한 루프 스레드 병렬화의 참담하고 극악한 오버헤드를 타파하기 위해, 위대한 PX4 아키텍트들은 시스템 코어 최심층부에 글로벌 워크 큐(Global Work Queue) 시스템을 영구 타설 배치했다.
이는 쉽게 말해 레스토랑 전체에 ’단 4명의 초일류 엘리트 웨이터(백그라운드 스레드 풀, Thread Pool)’만을 상주시켜 두고, 주방 어딘가에서 요리가 완성되었다는 ’종소리(Hardware Interrupt Event)’가 울릴 때마다 벤치에서 쉬고 있던 웨이터 중 단 한 명이 잽싸게 달려가 그 요청된 요리 서빙(단발성 Callback 함수 실행) 딱 하나만 즉시 처리하고, 다시 대기실 큐로 쿨하게 돌아오는 극강의 비동기(Asynchronous) 이벤트 드리븐 서버리스 아키텍처이다.
PX4 커널 메모리 내부에는 데이터의 생존 주파수 목적에 따라 여러 종류의 컨테이너 큐(Queue)가 24시간 백그라운드로 맹렬하게 돌아가고 있다.
wq_rate_ctrl: 1000Hz가 넘어가는 초고속 드론 이너 루프 모터 자세 제어만을 전담하는, 다른 걸 다 부수고 선점하는 최상위 마스터 우선순위 큐wq_nav_and_controllers: GPS나 느린 텔레메트리 등 상대적으로 50Hz 미만의 중간 속도 아우터 루프 항법 연산을 처리하는 큐wq_hp_default: 일반적이고 범용적인 고우선순위 센서 데이터 및 비정기적인 인터럽트 이벤트를 처리하는 기본 안전망 큐
2. 내 C++ 모듈 데몬을 큐에 ’탑승’시키는 스케줄링 트리거 메커니즘
이제 당신이 시스템에 런칭하려는 모듈 데몬은 더 이상 무식하게 자신만의 컨텍스트 무한 루프를 힙에 가져서는 원천적으로 안 된다. 대신, 오직 내가 짠 커스텀 C++ 객체 클래스의 메인 코어 함수(Run() 메서드라 부른다) 메모리 포인터만을 통째로 위에서 언급한 저 글로벌 스케줄링 큐 중 하나에 훅업시켜 ‘일회성 스케줄링 예약(Schedule)’ 걸어두기만 하면 펌웨어 개발의 모든 절차가 영구히 끝난다.
이때 시스템 큐에 내 함수 실행을 위임하고 예약을 거는 트리거(Trigger) 조건은 절대적으로 다음 두 가지로 극명하게 나뉜다.
- 타이머 기반(Timer-based Scheduling): “OS님, 내
Run()함수 메모리 블록을 저 큐에 태워서, 데이터가 오든 말든 시계 베이스로 매 10ms(100Hz) 주기로 정기적으로 무조건 한 번씩 단발 실행시켜 주시오.” (이것은 과거px4_usleep타이머 폴링의 메모리 최적화 성향의 고급화 래퍼 버전에 불과하다.) - 하드웨어 인터럽트 기반(Interrupt-based Scheduling): “OS님, 타이머는 개나 줘버리고, 오직 저 건너편
sensor_test_dataVFS 링 버퍼망 끄트머리에 새로운 패킷 데이터가 단 1바이트라도 물리적으로 들어오는(완벽한 POLLIN Edge) 바로 그 찰나의 마이크로초 즉시, 내Run()메모리 블록을 저 큐에 팝업으로 던져서 가장 파괴적인 최우선순위로 실행시켜 주시오.”
우리는 현재 수 마이크로초의 극한 반응성과 캐시 최적화가 동시에 요구되는 시스템 모듈을 개발 중이므로, 이어지는 19.5.3.2 단원의 피의 혈투에서는 오직 2번 인터럽트 기반 콜백을 위해, 최상위 추상 클래스인 px4::WorkItem 인스턴스를 상속받아 이 혁명적이고 거대한 백그라운드 큐 시스템에 영구적으로 올라타서 융합되는 가장 추상화된 핵심 C++ 객체 지향 코딩 프레임워크를 정밀 타설해 볼 것이다.