### 0.0.1 GPS 데이터 수집 스케줄링 및 I/O 블로킹(Blocking) 처리

### 0.0.1 GPS 데이터 수집 스케줄링 및 I/O 블로킹(Blocking) 처리

PX4-Autopilot과 같은 경성 실시간 운영체제(Hard RTOS) 환경에서, 외부 장치 하드웨어와 직렬(Serial) 통신을 수행하며 겪게 되는 가장 치명적인 함정은 바로 **I/O 블로킹(Blocking)**이다. GPS 칩셋이 위도/경도를 계산하느라 바이트를 내려보내지 않는데 CPU가 그 수신 버퍼 레지스터를 쳐다보고 무한정 대기하게 되면, 그 즉시 제어기의 전체 비행 루프(Flight Loop)가 멈춰 서고 드론은 추락(Crash)한다.

이러한 재플린(Zeppelin)급 재앙을 미연에 방지하기 위해, src/drivers/gps 디렉토리 코드는 GPS 파싱 엔진을 시스템의 메인 동맥으로부터 안전하게 분리(Isolation)해 낼 수 있는 섬세한 스케줄링 구조를 채택했다.

0.1 스레드 분리(Thread Isolation)와 독립된 타임 슬라이스(Time Slice)

드라이버 진입점 절에서 살펴본 바와 같이, 사용자 명령(gps start)이 들어오면 PX4 시스템은 메인 스크립트를 멈추지 않고 즉시 task_spawn()을 호출하여 별도의 백그라운드 스레드(gps_thread_main)를 띄운다.

  • 메인 루프의 보호: 이 분리(Isolation) 행위는 매우 중요하다. 커맨더(Commander)나 자세 제어기(Attitude Controller) 루프는 1밀리초(ms) 단위의 퀀텀(Quantum)을 다투는 반면, GPS 모듈은 아무리 빨라 봐야 10Hz(100ms 간격)로 굼뜨게 데이터를 뱉어내기 때문이다.
  • GPS 스레드는 오직 GPS 직렬 포트 관리에만 100% 매달린다. 포트 읽기 버퍼가 잠시 말라붙어 블로킹 현상이 발생하더라도, 그것은 그 작은 백그라운드 스레드 하나의 휴면(Sleep)일 뿐(Context Switch), 메인 쿼드콥터 모터 출력 제어 루프의 스케줄링에는 단 1%의 영향도 주지 않는다.

0.2 uORB를 통한 비동기(Asynchronous) 생산자-소비자 모델

그렇다면 고립된 섬(Island)에 갇힌 GPS 스레드가 어떻게 400Hz로 폭주하는 EKF2 추정기 스레드에게 최신 데이터를 안전하게 전달할까? 여기서 로봇 운영체제의 허브(Hub)인 uORB 데이터 버스가 개입한다.

  • GPS 드라이버 루틴은 오직 **생산자(Publisher)**의 역할만 한다. 데이터가 온전히 1세트 모여 파싱이 성공한 그 찰나의 순간에만 구조체를 채운 뒤 orb_publish() 명령으로 데이터를 허브에 던져버린다. 그리고 수신자가 그것을 먹었는지 체했는지 전혀 기다리지 않은 채 다시 자신의 직렬 수신 버퍼 대기 모드로 돌아간다.
  • 반대편에 있는 EKF2 추정기(Estimator) 스레드는 소비자(Subscriber) 역할을 한다. 추정기는 자신의 루프 연산을 수행하다가 특정 토픽(sensor_gps)에 새로운 깃발(Data Ready Flag)이 올라가 있으면 그제야 버스에서 데이터를 orb_copy() 해간다.
  • 즉 이 두 톱니바퀴는 서로의 얼굴(Thread ID)조차 모르며, I/O 스케줄링 상 완벽하게 비동기(Asynchronous) 결합되어 있어 블로킹 데드락(Deadlock)의 위협을 구조적으로 근절한다.

0.3 POSIX 멀티플렉싱 API의 구동 (poll)

고립된 스레드를 띄웠다고 할지라도, 그 안에서 계속해서 코어를 잡고 무한 반복문(while(true) { read() ... })을 맹렬히 회전시키는 행위(Busy-waiting)는 배터리와 CPU 자원을 갉아먹는 비효율의 극치이다. PX4는 영리하게도 운영체제의 인터럽트(Interrupt) 체계를 활용한다.

  • gps_main 스레드는 직렬 포트에서 데이터를 긁어오기 직전, px4_poll() (NuttX 기반 멀티플렉싱 시스템 콜) 함수를 호출한다. 지정된 파일 디스크립터(UART Port)에 데이터가 들어오기 전까지, 스케줄러는 이 스레드를 완전히 강제 기절(Sleep/Yield)시켜 버려 CPU 점유율을 0%로 떨어뜨린다.
  • 모듈 쪽에서 1바이트라도 데이터 스트림이 유입되어 하드웨어 RX 인터럽트가 발생하면, OS 커널 스케줄러가 번쩍 깨어나 기절해 있던 GPS 스레드의 멱살을 잡고 실행 대기 큐(Ready Queue)로 다시 끌어올린다.
  • 이를 통해 오직 실제 데이터가 버퍼에 존재할 때만 CPU 사이클을 소비하는 가장 우아한 I/O 이벤트 구동(Event-driven) 상태 머신의 스케줄링 모델이 완성된다.