19.6.2.1. orb_advertise_multi() 함수 호출 및 인스턴스 포인터 전달
다중 인스턴스의 세계관에서 퍼블리셔 데몬이 자신이 평생 몸담을 VFS 링 버퍼 방을 개통하는 유일무이하고 합법적인 수단은 바로 orb_advertise_multi() C API 함수를 타격하는 것뿐이다. 초창기 단일 인스턴스에서 쓰던 낡은 orb_advertise() 함수는 이제 기억 속에서 완전히 지워버려야 한다.
이 함수의 파괴적인 강력함은 커널 스케줄러와의 동적 포인터(Dynamic Pointer) 핸드셰이킹(Hand-shaking) 아키텍처에서 비롯된다. 퍼블리셔 스레드가 커널을 향해 “나에게 빈방 하나만 다오“라고 이 함수를 던질 때, 데몬은 단순히 빈손으로 요청하는 것이 아니라, 자신의 메모리 스택에 아주 깨끗이 초기화해 둔 int instance 정수형 껍데기 변수의 메모리 주소(포인터 &instance)를 뇌물처럼 함께 찔러 넣는다.
그러면 OS 커널은 0번 방부터 N번 방까지 쭉 스캐닝하며 비어있는 최초의 번호를 낚아챈 뒤, 내가 찔러넣은 그 포인터 주소를 따라 역으로 타고 들어와 로컬 메모리 변수 안에 **“너의 방 번호는 1번이야”**라고 텍스트 번호표를 쾅 찍어 강제 각인시켜 버리는 소름 돋는 콜백(Callback-like) 할당 메커니즘을 수행한다.
1. orb_advertise_multi()의 물리적 타설 및 동적 번호표 획득
우리가 만든 커스텀 센서 데몬(sensor_test_data) 2호기가 VFS 시스템에 최초로 다중 인스턴스 등록을 시도하는 절대적인 초기화(Initialization) 코드를 감상해 보자. 이 코드는 데몬의 while 루프가 시작되기 전, 부팅 스택의 가장 윗단에서 단 한 번만 물리적으로 치명하게 실행되어야 한다.
#include <uORB/uORB.h>
#include <uORB/topics/sensor_test_data.h>
// 1. [퍼블리셔의 영구 렌더링 자산] 내가 개통받을 파이프라인 마스터 키 핸들과, 내가 할당받을 인스턴스 방 번호 ID 변수를 스택에 선언
orb_advert_t sensor_pub_fd = nullptr;
// 2. [가장 치명적인 동적 할당용 빈 껍데기]
// 커널이 내 방 번호를 역으로 찍어줄 정수형 빈 그릇. 반드시 ORB_MULTI_UNASSIGNED라는 코어 매크로 상수로 영 초기화(Zero-init)해 두어야 한다.
// 이걸 안 하고 쓰레기 더미(Garbage) 메모리를 넘기면 커널은 내가 특정 방 번호를 억지로 요구한다고 오해하여 시스템을 폭파시킨다.
int my_sensor_instance = ORB_MULTI_UNASSIGNED;
// 3. 내가 발행할 첫 번째 센서 페이로드 구조체를 깨끗하게 세팅 (값은 0 초기화)
sensor_test_data_s initial_data{};
initial_data.timestamp = hrt_absolute_time();
// 4. [명운을 건 동적 멀티플렉싱 타격]
// - 첫 번째 인자: 내가 개통을 청원하는 토픽의 메타데이터 ID
// - 두 번째 인자 &initial_data: 방 개통과 동시에 일단 쑤셔 넣을 첫 번째 보증금(초기화 데이터) 스냅샷 포인터
// - 세 번째 인자 &my_sensor_instance: 커널이 빈방을 찾아보고 그 방 번호를 텍스트로 찍어 반환해 줄 역추적 메모리 주소(포인터)!
// - 네 번째 인자 ORB_PRIO_DEFAULT: 여러 개의 똑같은 방이 쪼개졌을 때, 내 방의 등급(우선순위). 대체로 디폴트를 준다.
sensor_pub_fd = orb_advertise_multi(ORB_ID(sensor_test_data), &initial_data, &my_sensor_instance, ORB_PRIO_DEFAULT);
// 5. 커널 할당 여부의 절대 검증 타설
if (sensor_pub_fd == nullptr) {
PX4_ERR("Multi-instance Advertisement Fatal Failed! Out of VFS Memory or Locked!");
return -1; // 데몬 즉각 자살 트리거
}
// 6. [커널의 응답 확인] 이 라인까지 무사히 내려왔다면, my_sensor_instance 변수 안에는
// 더 이상 ORB_MULTI_UNASSIGNED가 아닌, 커널이 내려준 '0', '1', '2' 등의 절대 숫자가 찍혀있다!
PX4_INFO("Successfully Advertised. Kernel designated Instance ID [%d] to my thread.", my_sensor_instance);
2. 동적 인스턴스 ID(my_sensor_instance)의 불멸적 보존 의무
위 방벽 코드가 무사히 뚫리고 나면 당신의 메모리 힙 스택에 선언된 my_sensor_instance 변수는, 당신의 데몬 스레드가 죽기 직전까지 절대 다른 값으로 덮어씌워져 쓰레기로 훼손되어선 안 되는 가장 거룩한 마스터 키(Master Key) 숫자 서명으로 격상된다.
만약 이 백그라운드 스레드가 메인 루프에서 이제 센서 데이터를 무한 속도로 1000Hz씩 미친 듯이 발행(Publish)할 때, 그 orb_publish 파이프 파라미터에는 무조건 아까 위에서 얻어낸 sensor_pub_fd 핸들이 인자로 들어가게 된다.
OS 배후의 uORB 커널은 이 sensor_pub_fd 핸들 내부의 메타 맵핑 주소를 스캔하여, **“아, 이 녀석 아까 내가 sensor_test_data의 1번 방(Instance 1) 열쇠를 던져줬던 그 데몬 놈이구나”**라고 즉각 식별을 끝낸다.
그리고 당신이 보낸 1000Hz 데이터 폭격을 한 치의 L1 캐시 레이스 컨디션 충돌도 없이, 오직 1번 방 버퍼 파이프에만 안전하고 잔혹하게 때려 박아주는 극한의 다중 격리(Isolation) 데이터 송출을 완성해 내는 것이다.