19.3.3.2. 메시지 큐 사이즈(Queue size) 설정 메커니즘 (orb_advertise_queue())
앞 단원에서 살펴본 가장 퓨어한 기본형 C 전역 API인 orb_advertise()는 압도적으로 빠르고 시스템 효율적이지만, 아키텍처 관점에서 치명적인 구조적 아킬레스건을 단 하나 내포하고 있다. 바로 미들웨어 링 버퍼(Ring Buffer) VFS 파이프 내부에 오직 단 1개의 구조체 덩어리(예: sizeof(sensor_test_data_s)) 공간만을 저장할 수 있는, 아주 비좁고 협소한 메모리 방(Queue Size = 1)만을 강제로 할당한다는 끔찍한 사실이다.
만약 우리의 퍼블리셔가 1000Hz의 미친 속도로 새로운 센서 데이터를 링 버퍼로 쏘아대는데, 정작 그 반대편 파이프 끝에서 데이터를 줍어 먹는 로그(Logger) 데몬이나 서브스크라이버(Subscriber) 스레드가 I/O 병목으로 50Hz 수준으로 굼뜨게 동작한다면 어떤 일이 벌어질까? 버퍼 안의 단 1칸짜리 방에서 새로운 데이터가 계속 덮어씌워지면서(Overwrite/Clash), 그 중간에 끼인 950여 개의 천금 같은 사이클의 센서 샘플링 물리 데이터들은 영구적으로 공중 분해(Drop)되어 영원히 복구할 수 없는 심연으로 증발해 버린다.
1. 버퍼 데이터 과적(Overload) 분쇄 방어를 위한 다중 큐(Multi-Queue) 파이프라인 개통
이러한 치명적인 고주파수 데이터 누락(Data Loss) 시스템 참사를 원천적으로 방어하기 위해 PX4 코어 팀이 제공하는 특수 해킹 무기가 바로 orb_advertise_queue() 매크로 함수이다. 이 함수를 시스템 커널에 날리면, 스케줄러는 코어 개발자가 지정한 고정 크기(Queue Size)만큼의 깊은 메모리 버퍼 큐(Deep Queue) 파이프 길이를 런타임 VFS에 즉시 강제 할당해 준다.
sensor_test_data_s initial_data{};
initial_data.timestamp = hrt_absolute_time();
// 철탑처럼 고립된 일반적인 단일 버퍼 생성이 아닌,
// 트래픽 덤프 병목을 안전하게 누적 보관할 수 있는 딥 큐(Deep Queue) 배열 개통 선전포고
// 세 번째 인자 '5': 서브스크라이버가 좀 늦게 파이프를 열고 읽어가더라도,
// 최대 5층의 데이터 구조체 큐 스택 깊이를 안전하게 누적시켜 버퍼링하겠다는 절대 선언
orb_advert_t sensor_pub_handle = orb_advertise_queue(
ORB_ID(sensor_test_data),
&initial_data,
5 // Queue Depth Size: 이 숫자를 크게 박을수록 희생되는 RAM 메모리는 낭비되지만,
// 외부 충격에 의한 데이터 유실률(Drop rate)은 0%에 극한 수렴하게 된다.
);
if (sensor_pub_handle == nullptr) {
PX4_ERR("Deep Queue Advertisement failed! System Heap Memory might be full or corrupted.");
return -1;
}
2. 큐(Queue) 사이즈 아키텍처 설정의 잔인한 트레이드오프(Trade-off) 딜레마 전략
구글링한 코드나 베껴 대는 하급 초급 개발자들은 센서 데이터의 누락이 그저 두려워 이 큐 사이즈 인자에 무지성으로 100, 1000 같은 거대한 배열 숫자를 교만하게 하드코딩하려 들 것이다.
하지만 뼛속까지 명심하라. 당신이 코딩하고 있는 PX4 픽스호크 마더보드의 SRAM 용량은 데스크탑의 16GB가 아니라, 고작 1MB~2MB 남짓인 지독하게 척박하고 가혹한 임베디드 코어 자원이다.
큐 사이즈를 1 늘릴 때마다 정확히 sizeof(구조체) * Queue Size 바이트만큼의 생동하는 메모리가 시스템 부팅 시점에 힙(Heap)에서 영원히 뜯겨나가 점유되어 버린다. 데몬을 10개만 돌려도 보드의 핵심 램 점유율이 90%를 박살 내며 즉시 OOM(Out of Memory) 커널 패닉 셧다운을 겪게 될 것이다.
따라서, sensor_gyro나 vehicle_local_position처럼 초고속 PID 내부 루프 제어에 필수적이어서 단 1프레임의 누락도 시스템 추락으로 직결되는 끔찍한 크리티컬 고주파 센서 데이터의 경우에만 큐 사이즈를 5~10 수준으로 전략적으로 타설해야 한다.
반대로 배터리 전압 알람(battery_status)이나 비행 모드 텍스트처럼 1초에 단 한 번만 늦게 읽어도 비행에 아무 지장이 없는 느린 스칼라 상태 데이터에는, 절대 이 폭력적인 큐를 메모리 낭비로 사용하지 말고 가장 무식한 orb_advertise() 1칸짜리 단일 버퍼를 써서 타이트한 메모리 공간을 보존(Save)하는 것. 그것이 바로 가혹한 통신 환경을 통제하는 진정한 비행 코어 아키텍트의 피도 눈물도 없는 시스템 설계 철학이다.