19.5.2.1. 여러 개의 Topic을 하나의 Poll Set으로 묶는 방법
앞선 19.5.2 단원에서 거대한 비행 코어 시스템 단에서의 다중 센서 융합 처리(Sensor Fusion) 아키텍처의 필연성을 절감했다면, 이제 C++ 코드로 그 거대한 VFS 미들웨어 감시 그물망(Poll Set)을 런타임 메모리에 직접 직조 결속할 차례이다.
핵심은 19.5.1.2 단원 기초에서 단 하나만을 쩨쩨하게 보았던 px4_pollfd_struct_t 통제 배열의 물리적 메모리 크기(Size)를 스케일 확장하고, 각각의 1차원 인덱스 슬롯(Slot) 방에 전혀 다른 종류와 주파수를 가진 이질적인 토픽 파이프 마스터 키(FD)들을 차곡차곡 하드코딩 매핑(Mapping)하는 물리적 적재 할당 작업이다.
예를 들어, 우리가 그동안 테스트로 만든 우리만의 sensor_test_data 파이프라인과, PX4 코어 프레임워크가 400Hz로 미친 듯이 쏴대는 시스템 기본 뼈대 토픽인 vehicle_acceleration (가속도계 IMU 데이터) 파이프라인이라는 두 개의 생태계를 단 1개의 데몬 스레드로 동시에 묶어 감시하고 제어해보도록 극한 설계해 보자.
1. 다중 파일 디스크립터(Multi-FD) 구조체 배열의 멱살 직조 타설
먼저 무한 루프 밖에서 두 개의 이질적인 파이프라인 노드를 VFS 커널단에서 각각 뚫는다. 그리고 그 물리적 크기가 2로 확장된 감시 그물망 배열에 각각의 얻어낸 파이프라인 핸들을 핀셋처럼 무자비하게 끼워 넣는다. 배열의 하드코딩 인덱스 배열 넘버(0번 슬롯, 1번 슬롯)는 곧 내 스레드가 인터럽트에 귓방망이를 맞고 깨어났을 때 **“도대체 어떤 놈이 나를 깨웠는가?”**를 역추적하여 색출해 내는 가장 고유한 절대 아이디(ID) DNS 역할을 수행하게 될 것이다.
// 1. 완전히 서로 다른 메모리 구조와 물리적 의미를 지닌 두 개의 절대 메타데이터 헤더 인클루드
#include <uORB/topics/sensor_test_data.h>
#include <uORB/topics/vehicle_acceleration.h>
// 2. 두 개의 이질적인 VFS 링 버퍼 수신 파이프라인을 OS단에서 각각 독립적으로 개통 타격
int sensor_test_sub_fd = orb_subscribe(ORB_ID(sensor_test_data));
int accel_sub_fd = orb_subscribe(ORB_ID(vehicle_acceleration));
// 3. [거대 그물망 설계] 2개의 전혀 다른 물리 타겟을 하나의 묶음으로 감시하기 위한 크기 '2'의 배열 힙 타설
px4_pollfd_struct_t fds[2];
// 4. [0번 슬롯 배열 앵커] 커스텀 센서 데이터 감시망 매핑 결속
fds[0].fd = sensor_test_sub_fd; // 아까 얻어낸 첫 번째 파이프 마스터 키 핸들
fds[0].events = POLLIN; // "이 파이프에 새 1바이트 엣지(Edge) 인입 시 무조건 하드웨어 인터럽트 터뜨려!"
// 5. [1번 슬롯 배열 앵커] 400Hz 시스템 가속도계 센서 감시망 듀얼 매핑 결속
fds[1].fd = accel_sub_fd; // 두 번째 가속도계 파이프 마스터 키 핸들
fds[1].events = POLLIN; // 마찬가지로 엣지 인입 시 동일한 인터럽트 락 해제 청부
// ... 이제 이렇게 아름답게 짜인 거대한 다중 fds 배열 단일 덩어리를 px4_poll()의 아가리에 통째로 던져 넣기만 하면
// 커널은 이 2개의 파이프라인 꼬리를 멀티 렌더링으로 실시간 동시 노려보게 된다.
2. Poll Set 멀티플렉싱 아키텍처가 부르는 궁극의 확장성(Scalability) 폭발
위처럼 단 몇 줄의 C++ 배열 구조체 코드를 구축하면, 이 fds 배열 컨테이너는 시스템 커널 메모리 스케줄러 상에서 전혀 다른 2개의 분리된 VFS 버퍼 노드의 꼬리단을 동시에 째려바라보는 단일한 하나의 거대 파수꾼 객체가 된다. 만약 당신이 추후 10개의 이질적 센서를 한 점의 매트릭스에 융합해야 하는 거대한 코어 EKF 항법 데몬을 진두지휘한다 할지라도, 그저 허탈할 정도로 배열 크기를 10으로 늘리고 fds[0]부터 fds[9] 슬롯 방까지 orb_subscribe의 핸들만 10개 할당해 세팅해 주면 모든 아키텍처 준비가 영구히 끝나버리게 된다.
소름 돋게도 커널 스케줄러 엔진 입장에서는 당신이 요청한 이 감시망의 크기가 배열 1칸이건, 배열 10칸이건 px4_poll 시스템 콜을 처리하는 하단 블로킹 큐(Wait Queue)의 동기화 오버헤드는 거의 완벽하게 1(상수)과 같다.
OS 커널은 이 거대한 배열에 수천 개가 등록된 FD들 중, 단 한 놈의 파이프 끄트머리에서라도 물리적인 POLLIN 트리거가 폭발하면 그 즉시 배열 전체에 걸어둔 블로킹 락(Lock)을 산산조각 해제하며 잠든 스레드를 지체 없이 기상시킨다.
우리는 이렇게 단 1개의 초경량 데몬 워커 스레드만으로 무한대에 가까운 미들웨어 토픽 채널 파이프망들을 문어발처럼 장악 제어하는 궁극의 시스템 확장성(Scalability) 권력을 확보 통제한 것이다. 이제 데몬 스레드가 눈을 떴을 때, 그 거대한 배열 방들 안에서 정확히 어떤 1명의 놈 때문에 알람이 울렸는지를 역추적 색출하는 19.5.2.2 단원의 피의 식별(Identify) 로직만 무사히 타설하면 멀티플렉싱(Multiplexing) 시스템의 마지막 조각이 완벽히 아귀를 교합하게 된다.