18.3.2 NuttX 가상 파일 시스템(VFS) 기반 디바이스 노드 등록 메커니즘

18.3.2 NuttX 가상 파일 시스템(VFS) 기반 디바이스 노드 등록 메커니즘

수많은 태스크들이 얽고 설킨 RTOS 환경에서 통로(Channel)를 개설하고 데이터를 동기화하는 작업은 결코 쉬운 일이 아니다. 커스텀(Custom) 메시지 큐를 바닥부터 설계하다 보면 필연적으로 데드락(Deadlock)과 같은 치명적인 버그에 직면하게 된다.

PX4 아키텍트들은 이 난제를 돌파하기 위해 유닉스(UNIX)의 가장 위대한 유산인 “모든 것은 파일이다(Everything is a file)” 라는 패러다임을 uORB 미들웨어에 직수입했다. uORB 코어는 자체적인 라우팅 테이블을 복잡하게 꼬아 만드는 대신, 하부 운영체제(NuttX)가 기본적으로 제공하는 가상 파일 시스템(VFS, Virtual File System) 에 데이터를 싣고 나르는 파이프를 은밀하게 숨겨놓았다.

1. 문자 디바이스(Character Device)로의 우아한 변신

발행자(Publisher)가 특정 토픽을 개설하면, uORBDeviceMaster는 메모리에 uORBDeviceNode 객체를 생성한다(18.3.1.2절 참조). 이 객체는 메모리상에 조용히 머무는 것이 아니라, 커널 수준의 드라이버 등록 함수(NuttX의 경우 register_driver())를 호출하여 자신을 OS에 정식 하드웨어 디바이스인 양 위장하여 등록한다.

이 등록 과정을 거치고 나면, 소프트웨어적인 데이터 덩어리에 불과했던 토픽 구조체는 /obj 라는 가상의 디렉토리 하위에 /obj/sensor_gyro0, /obj/vehicle_gps_position0 와 같은 번듯한 문자 디바이스 노드(Character Device Node) 의 형태를 띠게 된다.

2. POSIX 표준 API와의 기적적인 결합

이러한 VFS 기반 설계가 가져다준 아키텍처적 혜택은 실로 막대하다.

비행 제어 시스템의 수많은 구독자(Subscriber)와 발행자 모듈들은 자신이 통신하고 있는 대상이 복잡한 객체 지향 C++ 클래스의 링 버퍼(Ring Buffer)라는 사실을 전혀 알 필요가 없다. 그저 C 언어 학부 과정에서 배우는 너무나도 친숙하고 표준적인 POSIX 파일 입출력 API를 그대로 사용하여 데이터를 읽고 쓴다.

  • open("/obj/sensor_gyro0", O_RDONLY) : 토픽 구독 시작
  • read(fd, buffer, sizeof(buffer)) : 최신 센서 데이터 읽기
  • write(fd, data, sizeof(data)) : 새로운 센서 데이터 발행
  • ioctl(fd, ORBIOCSETINTERVAL, 20) : 파라미터 제어 (예: 20ms마다 업데이트 받기 설정)

결과적으로 uORB는 복잡한 스레드 동기화와 락(Lock) 처리를 수십 년간 수억 대의 기기에서 검증된 OS 커널의 VFS 레이어에 우아하게 떠넘김(Offloading)으로써, 극도의 시스템 신뢰성을 확보해 냈다.

이어지는 하위 절들에서는 이 /obj 디렉토리가 어떻게 격리되어 마운트되는지(18.3.2.1절) 파헤치고, 어떻게 표준 C 함수(read/write)가 C++ 클래스 메서드 호출로 마법처럼 치환되는지(file_operations 구조체 활용, 18.3.2.2절) 심층적으로 분석할 것이다.