21.7. uORB 비동기 메시징 및 이벤트 기반 실행(Event-driven) 최적화
픽스호크라는 작은 몸집 안에서 50개가 넘는 모듈들이 충돌 없이 협동하며 드론을 하늘에 띄울 수 있는 배후에는, PX4 코어 아키텍처의 최고 걸작이자 신경망(Nervous System)인 uORB (Micro Object Request Broker) 통신 시스템이 굳건히 자리 잡고 있다.
지금까지 우리는 내 모듈을 메모리에 띄우고(ModuleBase), 파라미터를 연결하고(ModuleParams), 영구적인 타이머를 돌려 커널의 버스에 올라타는 법(WorkItem, ScheduleOnInterval)을 배웠다.
이것이 모듈의 ’육체’를 조립하는 과정이었다면, 이번 장부터 배우게 될 uORB는 모듈 간에 데이터를 주고받는 ’혈관과 신경’을 엮어내는 과정이다.
1. 동기식(Synchronous) API의 종말
만약 uORB가 없었다면, 자이로 센서 모듈에서 값을 읽어와야 하는 자세 제어 모듈은 어떻게 코드를 짰을까?
아마도 센서 모듈의 헤더 파일을 직접 #include 한 뒤, 센서 객체의 주소를 포인터로 넘겨받아 sensor->get_gyro_data() 같은 함수를 직접(Direct Method Call) 호출했을 것이다.
이런 고전적인 객체 지향적 접근(강결합, Tight Coupling)은 멀티 코어나 멀티 스레드 실시간 시스템에서는 파멸을 부른다.
내가 저 함수를 호출하는 그 순간, 센서 스레드는 I2C 버스에서 데이터를 읽느라 메모리에 락(Mutex Lock)을 걸어두었을 수 있다. 그러면 내 제어기 스레드는 그 락이 풀릴 때까지 하염없이 멈춰서 기다려야(Blocking) 한다.
모듈 하나가 멈추면 거기에 직접 연결된 10개의 모듈이 줄줄이 멈춰서는 블로킹의 연쇄 폭발이 일어난다.
2. Publish-Subscribe (Pub/Sub) 패턴의 마법
이 끔찍한 의존성(Dependency)을 끊어내기 위해 uORB는 철저한 비동기 출판-구독(Publish-Subscribe) 모델을 채택했다.
- 출판자 (Publisher): 자이로 센서 모듈은 자신을 호출하는 제어기가 누구인지, 몇 명인지 알 필요가 없다. 그저 “나 지금 자이로 최신 데이터 뽑았어!“라며
sensor_gyro라는 이름의 토픽(Topic) 게시판에 구조체 데이터(메시지)를 던져놓고 쿨하게 자기 할 일을 하러 떠난다. - 구독자 (Subscriber): 자세 제어 모듈 역시 센서 스레드가 지금 I2C를 읽고 있는지 자고 있는지 알 바 아니다. 자기가 계산을 돌려야 할 타이밍(
Run())이 오면, 그냥 게시판(sensor_gyro토픽)에 쓱 다가가서 가장 마지막에 붙어있는 전단지(데이터 복사본)를 북 뜯어오면 끝이다.
이 과정에서 락(Mutex)을 걸며 상대방 스레드가 깨어나길 대기하는 일은 결코 일어나지 않는다. 철저하게 락-프리(Lock-free)로 작동하는 공유 메모리 캐싱(Shared Memory Caching)의 예술이다.
3. 타이머 스케줄링의 진화: 이벤트 기반 실행 (Event-driven)
게다가 uORB는 단순한 우체부가 아니다. 커널의 스케줄러와 깊숙이 유착되어 엄청난 시너지를 낸다.
이전 챕터(21.6.3)에서 우리는 ScheduleOnInterval(10_ms)을 써서 정기적으로(100Hz) 알람을 무지성으로 때리는 법을 배웠다.
하지만 만약 외부 충격으로 인해 자이로 센서가 5ms 만에 비정상적으로 새로운 데이터를 뽑아내 출판(Publish)했다면?
기존의 10ms 타이머 방식이라면 내 제어 모듈은 남은 5ms 동안 잠을 자느라 그 중요한 데이터를 놓쳐버리거나 심각한 지연(Latency) 뒤에 처리하게 된다.
이를 극복하기 위해 최신 PX4 모듈들은 정주기 타이머(Interval)를 버리고, **“uORB 토픽에 새 데이터가 배달(Publish)되는 그 폭발적인 순간(Event)에만 내 모듈을 즉각 깨워달라”**는 이벤트 기반 실행(Event-driven Execution) 패턴으로 진화했다.
그렇다면 uORB 게시판에 꽂힌 C 구조체 데이터를 어떻게 가장 안전하고 우아하게 내 C++ 메모리로 복사해 올 수 있는지, PX4 코어팀이 깎아낸 C++ 래퍼 클래스들의 변천사(21.7.1)부터 순서대로 해부해 보도록 하자.