21.6.2. 타겟 스레드 풀(Thread Pool)의 전략적 선택
CustomApp을 커널의 워크 큐(Work Queue) 화물로 만들어 던질 준비를 마쳤다면, 이제 가장 중요한 아키텍처적 결단이 하나 남았다.
“내 모듈을 어떤 버스(스레드 풀)에 태워서 돌릴 것인가?”
21.6.1.1 단원에서 우리는 생성자 초기화 리스트에 px4::wq_configurations::rate_ctrl 이라는 버스 번호표를 무심하게 적어 넣었다. 하지만 이 버스 노선의 선택은 단순히 취향의 문제가 아니라, PX4 펌웨어 전체의 시스템 부하(System Load)와 제어 성능을 통째로 좌지우지하는 가장 핵심적인 설계 스텝이다.
1. 버스 노선의 계급 사회: 우선순위(Priority)
PX4가 부팅될 때 생성되는 5~6개의 메인 워크 큐 스레드들은 병렬로 평등하게 도는 것이 아니다. 이 버스들은 철저한 RTOS(실시간 운영체제)의 우선순위(Priority) 계급 사회를 이루고 있다.
NuttX 운영체제의 스케줄러(SCHED_FIFO 또는 SCHED_RR)는 항상 우선순위 숫자가 가장 높은 스레드에게 무자비할 정도로 CPU 독점권을 부여해 버린다.
즉, 가장 높은 우선순위의 버스(rate_ctrl)가 화물을 내려놓고 잠시 숨(Sleep)을 고르거나 uORB 메시지를 기다릴 때에만, 그 틈새를 타서 하위 버스(nav_and_cmds나 lp_default)들이 찌꺼기 CPU 클럭을 주워 먹고 돌아갈 수 있는 구조다.
2. 내 모듈의 계급 자가 진단 테스트
개발자는 자신의 커스텀 모듈이 무슨 일을 하는지에 따라 아주 냉정하게 타깃 스레드 풀을 골라잡아야 한다.
- “내 모듈이 0.001초(1ms)라도 늦게 계산되면 드론이 땅에 박혀 박살 나는가?”
- Yes: 이 모듈은 초고우선순위(rate_ctrl) 버스를 타야만 한다. (예: 자이로 센서 필터링, PID 자세 제어기, 모터 믹서)
- “내 모듈은 1초에 한 10번쯤만 돌면 되고 조금 밀려도 비행에는 지장 없는가?”
- Yes: 이 모듈은 저우선순위(lp_default) 버스를 타고 가야 한다. (예: SD 카드 로깅, LED 깜빡임 제어, 배터리 전압 알림)
- “내 모듈은 GPS를 쳐다보며 길을 찾거나, 텔레메트리 무선 모뎀과 통신하는가?”
- Yes: 이 모듈은 중간 우선순위(nav_and_cmds) 버스에 타 적당한 속도로 데이터를 처리해야 한다. (예: 네비게이터, 커맨더, MAVLink)
만약 초보 개발자가 “내 커스텀 모듈은 너무나 소중하니까!“라며 단순한 LED 제어 모듈을 최고 등급인 rate_ctrl 버스에 강제로 태워버린다면 어떤 일이 벌어질까?
LED 배선에 약간의 딜레이(예: I2C 통신 지연)가 걸리는 순간, 한 버스를 타고 있던 PID 자세 제어기까지 함께 멈춰 서게(Blocking) 되고, 눈부시게 빛나는 LED를 자랑하며 드론은 메가파스칼 단위로 땅바닥에 곤두박질칠 것이다.
따라서 어떤 버스 티켓을 끊을지는 모듈의 태생적인 주파수(Frequency)와 요구 인내 한계(Latency)에 따라 철저히 수학적으로 결정되어야 한다.
다음 단원인 21.6.2.1장부터는, 각 티켓 등급(wq_rate_ctrl, wq_nav_and_cmds, wq_hp_default, wq_lp_default) 별로 요구되는 통과 기준과 스레드 스택 할당의 비밀을 상세히 분류해 보도록 하겠다.