35.1.2.1. 코어 계층: 포식스(POSIX) 스레드 기반 비동기 이벤트 루프(Asynchronous Event Loop) 및 입출력 다중화(I/O Multiplexing) 스케줄링
MAVSDK 아키텍처의 가장 근간을 이루는 코어(Core) 계층은 운영 체제의 커널 자원을 직접적으로 통제하여 고성능 네트워크 입출력을 달성한다. PX4-Autopilot(v1.14.x)으로부터 쏟아지는 수십~수백 헤르츠(Hz)의 MAVLink 스트림을 병목 현상 없이 청취(Listening)하고 처리하기 위해, MAVSDK 코어 라이브러리는 포식스(POSIX) 스레드(std::thread 백엔드 호환) 및 비동기 이벤트 루프 체계를 중심으로 설계되었다. 본 절에서는 이러한 코어 계층의 스케줄링 기법 및 입출력 다중화(I/O Multiplexing) 메커니즘을 소스 코드 수준의 아키텍처 관점에서 해부한다.
1. POSIX 스레드(pthreads) 기반 백그라운드 구동 환경
MAVSDK 코어는 초기화 시점에 운영 체제 커널에 최소 2개 이상의 메인 백그라운드 스레드를 요구한다.
- 네트워크 수신 스레드(Receive Thread): 통신 인터페이스(UDP, TCP, UART Serial) 자체의 I/O 블로킹 대기(Blocking Wait)를 담당한다.
- 타이머 및 이벤트 디스패처 스레드(Timeout & Dispatch Thread): 플러그인 모듈에서 등록한 비동기 타이머(예: MAVLink
COMMAND_LONG재시도 타임아웃 500ms)를 검사하고, 수신된 메시지에 매핑된 사용자(또는 gRPC 서버) 측 콜백 함수를 실행(Dispatch)하는 역할을 수행한다.
이러한 멀티 스레딩 환경은 단일 스레드 구조에 갇혀있던 기존 드론 관제 스크립트 도구들(DroneKit 등)과 차별화되는 결정적 요인이다. 하나의 큰 while (true) 루프가 I/O 수신과 CPU 집약적인 연산(예: 체크섬 계산)을 번갈아 수행하게 될 경우, 연산 중에 도착한 네트워크 버퍼 패킷은 OS 수준에서 드롭(Drop)될 위험이 크다. 코어 계층은 수신 스레드의 작업 단위를 오로지 “MAVLink 파싱 후 스레드-세이프(Thread-safe) 큐 삽입“만으로 극도로 제한하여 이러한 오버헤드를 원천 차단한다.
2. 입출력 다중화(I/O Multiplexing) 설계와 파일 디스크립터(FD) 감시
PX4와 통신할 때 MAVSDK는 종종 단일 UDP 포트만 사용하지 않는다. 시뮬레이션 환경(SITL, HITL)의 다수 에이전트 브로드캐스팅 수신, 혹여나 컴패니언 컴퓨터와 비행 제어기 간의 다중 시리얼 채널 텔레메트리 보장 등 여러 개의 소켓 자원이 동시에 개방된다.
코어 계층은 이를 비동기적으로 처리하기 위해 리눅스/유닉스 환경의 select() 혹은 epoll() 기반 입출력 다중화(I/O Multiplexing) 시스템 콜(System Call)을 이용한다.
- 동작 매커니즘: 모든 네트워크 인터페이스(UDP 소켓, /dev/ttyACM0 등)는 OS 커널 레벨에서 각각의 파일 디스크립터(FD) 번호를 부여받는다. 수신 스레드는
select()함수에 감시 대상 FD 집합 집합을 등록한 후 수면(Sleep) 상태에 진입한다. - 인터럽트 깨어남(Wake-up): PX4로부터 단 1바이트의 페이로드라도 도착하면, 커널은 이더넷/시리얼 드라이버 하드웨어 인터럽트를 수신한 뒤 즉각 MAVSDK 수신 스레드를 깨워 해당 FD 버퍼의 데이터를 읽어(Read) 들인다.
- CPU 점유율 억제: 타임 레이스 루프(e.g.,
while(!data_available)) 기반의 Busy-waiting 방식 대비 이 다중화 방식은 CPU 사이클을 전혀 소모하지 않고 이벤트를 기다릴 수 있으므로, 임베디드 리눅스와 같은 저전력 에지 디바이스(Edge Device) 환경에서 배터리 소모를 줄이는데 크게 기여한다.
3. 비동기 이벤트 루프(Asynchronous Event Loop) 큐잉 및 콜백 구조
수신 스레드와 더불어 코어 계층의 핵심을 이루는 컴포넌트는 콜백 디스패치 루프이다. 통신이 다수일 경우 데이터 침범(Data-Race)을 방지하기 위한 강력한 뮤텍스(Mutex) 동기화 전략이 수반된다.
| 아키텍처 구성 요소 | 역할 및 동작 특징 |
|---|---|
| Concurrent Queue | 파싱 큐. std::mutex 및 std::condition_variable 조합. |
| Subscription Registry | 특정 MAVLink 메시지 ID(예: HEARTBEAT) 단위로 다수의 구독자 콜백 포인터를 등록 \vert 해제 관리. |
| Worker Pool 제한 | 사용자 콜백 함수 내부에서 강제 지연(sleep)이 발생할 경우 코어 파이프라인 전체가 마비되는 것을 방지하기 위해, 병렬 스레드 객스를 제한적으로 할당하여 처리. |
4. 결론
MAVSDK 코어 계층의 POSIX 스레드 기반 분산 폴링(Polling) 아키텍처는 C++ 언어가 가진 메모리와 스레드 제어권의 강점을 극한으로 끌어올린 결과물이다. 지상 관제 시스템 최상단의 프론트엔드가 아무리 복잡한 가상 비동기 처리(asyncio, RX 등)를 수행하더라도, 그 바닥에서는 OS 레벨의 이진 파일 디스크립터 시스템 콜(epoll)과 std::thread가 로우 레벨 블로킹 장벽을 철저히 막아내고 있다. 이는 멀티로터나 고정익 드론의 극한 환경 비행 중 발생하는 통신 지연(Jitter) 환경 하에서도, 제어 명령 루프의 시분할(Time-sharing) 보장성을 획득하게 해 주는 기술적 초석이다.