19.7.2.2. NuttShell(NSH) 콘솔에서 커스텀 애플리케이션 수동 실행 (px4_uorb_example start)
jMAVSim 3D 가상 드론 창이 성공적으로 떠오르고 리눅스 터미널의 프롬프트가 영문 모를 텍스트들을 마구 쏟아낸 뒤 px4>라는 세 글자로 멈춰 서서 깜빡인다면, 축하한다. 이제 당신은 픽스호크 실시간 운영체제 커널의 심장부로 들어온 것이다.
현재 메모리에는 commander, ekf2, logger 시스템 데몬들이 백그라운드 스레드에서 무시무시한 속도로 돌아가고 있다. 하지만 우리가 심혈을 기울여 코딩하고 default.cmake에 등록까지 마친 px4_uorb_example 데몬 모듈은 여전히 차가운 디스크 파일 시스템 내부에 누워서 깊은 잠을 자고 있다.
왜냐하면 PX4 커널은 아무 모듈이나 부팅하자마자 무작정 다 띄워주지 않기 때문이다. 부팅 스크립트(rcS)에 의해 강제 자동 실행(Auto-start) 구문이 타설되지 않은 어설픈 커스텀 모듈들은 오직 터미널 창에서 개발자가 수동으로 ‘기상(Start)’ 명령을 때릴 때만 백그라운드로 로드(Load)된다.
1. start 트리거의 타격과 C++ main() 함수의 개방
px4> 프롬프트가 깜빡이는 곳에 타이핑을 시작하자. 우리의 목표는 내 모듈의 이름 스페이스를 정확히 호명하여 start 인자를 던지는 것이다. 과거 우리가 ModuleBase를 상속하며 설계했던 C++ 메인 커스텀 함수가 커널에 의해 드디어 깨어나는 순간이다.
px4> px4_uorb_example start
이 고작 두 단어짜리 명령어를 타격하고 엔터를 치는 찰나, 커널 스케줄러 내부에선 거친 폭풍이 휘몰아친다.
- 커널의 이름 탐색: NSH 쉘 해독기는
px4_uorb_example이라는 텍스트가 펌웨어 바이너리 파일 내부의 심볼(Symbol) 맵에 존재하는지 빛의 속도로 스캔한다. 19.7.1.1 단원에서 CMake에 이 이름을 무사히 등록했으므로, 쉘은 “아, 그 C++ 모듈!” 하고 즉각 끄덕인다. custom_main()진입점 타격: 당신의 모듈 텍스트 코드 최하단에 있던extern "C" __EXPORT int px4_uorb_example_main(int argc, char *argv[])함수 포인터를 커널 스레드로 강제 점프(Jump)시켜 버린다.- 옵션 파싱과 인스턴스 생성: 모듈의 메인 함수는 당신이 던진 두 번째 인수인 ‘
start’ 문자열을argv[1]로 스위치 파싱한다. 그리고 마침내new SensorSubscriber()라는 C++ 생성자 코드를 타격해 여러분의 WorkQueue 콜백 데몬 인스턴스를 메모리의 무한 공간(Heap) 속으로 물리적으로 임신(Instantiation)시킨다!
2. 동기식(Synchronous) 실행의 절망
만약 당신의 코드가 19.3 단원 시절의 구식 폴링(Polling) while (!thread_should_exit) 무한 루프 블록을 떡하니 달고 있는 단순 C 스크립트라면, 저 start 명령어를 친 즉시 모듈 스레드는 무한 루프의 수렁에 영원히 빠지게 된다.
이 경우 NSH 콘솔 창은 락(Lock)이 걸리고 더 이상 px4> 프롬프트를 띄우지 않은 채, 무한 루프 안에서 당신이 짠 orb_copy의 결과값 텍스트 구조체들만 터미널 화면 위로 미친 듯이 영구적으로 줄줄이 쏟아내게 될 것이다.
이것을 동기식 전경(Foreground) 실행 모드라고 부른다.
테스트를 진행하려면 반드시 키보드에서 무자비하게 [Ctrl] + [C]를 때려, 방금 메모리에 띄우느라 고생한 나의 무한 루프 스레드를 통째로 목 졸라 죽여버리는(Kill) 자살 행위를 강행해야만, 다시 쉘 제어권(프롬프트)을 얻을 수 있다.
이 끔찍한 전경 락업 현상을 우아하게 피하고, 내 모듈은 백그라운드 뒤편에 살려둔 채 콘솔 프롬프트 명령어 제어권도 잃지 않는 극강의 우회 기법이 바로 이어지는 19.7.2.3 단원의 ‘백그라운드 데몬화 태스크(&)’ 실행과 ‘객체 덤프(status)’ 추적 기술이다.