18.3.1.2 uORBDeviceMaster 클래스 인스턴스화 및 전역 메모리 풀(Memory Pool) 관리
앞선 18.3.1.1절에서 uORB::Manager가 시스템 초기에 싱글톤으로 인스턴스화된다는 것을 확인했다. 하지만 Manager 클래스 자체는 외부에 API를 열어주는 얇은 껍질(Wrapper)에 불과하다.
실제로 VFS 드라이버 노드를 장착하고, 현재 시스템에 어떤 토픽들이 얼마나 쏟아져 들어오고 있는지 장부(Ledger)를 관리하며, 토픽 데이터를 담을 물리적 메모리를 확보하는 ‘살림꾼’ 역할은 매니저 내부에서 은밀하게 생성되는 uORBDeviceMaster 클래스 가 전담한다.
1. DeviceMaster의 탄생과 토픽 명부 관리
uORB::Manager::initialize() 가 호출되어 매니저 객체가 탄생하는 바로 그 순간, 생성자 내부에서는 짝꿍처럼 _device_master = new uORBDeviceMaster() 가 즉각적으로 실행된다.
비행 제어기가 구동을 시작하고 각종 센서 드라이버들이 앞다투어 orb_advertise()를 호출하면, 매니저는 이 요청을 모두 자신이 들고 있는 _device_master 에게 전달한다. 마스터 클래스는 내부적으로 연결 리스트(Linked List) 형태의 디바이스 노드 트리(Device Node Tree)를 유지하고 있다.
- 중복 개설 방지: “자이로(Gyro) 센서 토픽 개설해 줘“라는 요청이 들어오면, 마스터는 자신의 리스트를 순회하며
/obj/sensor_gyro0노드가 이미 존재하는지 검사한다. - 노드 인스턴스화: 존재하지 않는 완전히 새로운 토픽이라면, 마스터는 해당 토픽을 처리할 전담 객체인
uORBDeviceNode를 메모리에 새롭게 빚어낸다.
2. 전역 메모리 풀(Memory Pool)의 엄격한 통제
여기서 비행 제어 소프트웨어로서의 PX4의 집요한 안정성 철학이 드러난다. 파이프라인에서 객체를 힙(Heap) 공간에 동적으로 할당하는 new와 delete 연산자는 필연적으로 메모리 파편화(Fragmentation)를 유발하여 장기 비행 시 기체를 추락시키는 시한폭탄이 된다.
uORBDeviceMaster는 이러한 파편화를 막기 위해 단방향 영속성(Persistent) 메모리 할당 정책을 고수한다.
- 한 번 발행자(Publisher)에 의해 개설(Advertise)되어 장부에 등록된
uORBDeviceNode객체와 그 이면의 링 버퍼(Ring Buffer) 데이터 메모리는 기체의 전원이 꺼질 때까지 절대 해제(Free/Delete)되지 않는다. - 개발자가 명시적으로
orb_unadvertise()를 호출하여 발행을 취소하더라도, 데이터가 오가지 않을 뿐 메모리 노드 자체는 파괴되지 않고 재사용(Reuse)을 위해 대기 상태로 유지된다.
이는 C++의 치명적인 약점인 가비지 컬렉션(GC) 부재 상황에서, 힙 메모리의 크기가 늘어날지언정 중간에 구멍이 뚫리게 놔두지는 않겠다는 단호한 아키텍처적 결단이다. 결과적으로 uORBDeviceMaster는 부팅 후 수초 내에 필요한 토픽들의 메모리 블록을 영구적으로 확보(Allocation)해 버린 후 시스템을 극도의 안정 상태(Stable State)로 밀어 넣는 막중한 책임을 완수하게 된다.