2026. 1. 23. 17:38ㆍ운영체제/QNX
1) Resource Manager란?
QNX에서 Resource Manager(리소스 매니저) 는 매우 QNX 특유의 개념으로, “운영체제를 확장하는 것처럼 보이는” 사용자 공간(user space) 프로세스입니다.
핵심 아이디어는 두 가지입니다.
- Pathname space(경로 이름 공간) 에 이름을 등록한다
- 예: /dev/ser1, /dev/con1, /mnt, /home 등
- 클라이언트가 그 이름을 POSIX 인터페이스(open/read/write/lseek 등) 로 접근하게 만든다
- 클라이언트 입장에서는 “파일/디바이스를 다루듯” 동일한 호출 방식을 사용
리소스는 하드웨어에 대응할 수도 있고(대부분의 드라이버), 순수 소프트웨어 엔터티일 수도 있습니다.
- 하드웨어 예: Serial, Disk/File system, CAN, I2C 등 (QNX의 드라이버 다수가 RM 형태)
- 소프트웨어 예: Queueing system, Logging system 등
2) Pathname Space(Pathname space)와 Prefix Tree(프리픽스 트리)
2.1 Pathname space의 의미
QNX의 pathname space는 “/로 구분되는 이름(경로)”을 어떤 프로세스(리소스 매니저) 가 처리하는지에 대한 매핑(mapping) 입니다.
예시(스크립트 기반):
- /dev/con1 → devc-con (콘솔/키보드/스크린 드라이버)
- /dev/ser1 → devc-ser8250 (시리얼 드라이버)
- /(slash) → 파일시스템(devb-*) + procnto(일부 기능) 등 여러 프로세스가 걸릴 수 있음

2.2 Prefix tree는 누가 관리하나?
- procnto(Process Manager) 가 prefix tree(프리픽스 트리)를 관리합니다.
- 의미: “open이 성공 가능한 모든 경로”는
- procnto가 직접 관리하는 prefix entry 이거나
- 그 entry의 descendant(하위 경로)입니다.
즉, 리소스 매니저는 procnto에게 “이 prefix를 내가 처리할게” 라고 등록(register)하고, 필요 시 해제(unmount 등)할 수 있습니다.
등록 정보에는 보통:
- PID(Process ID)
- Channel ID
- Handle(동일 프로세스의 여러 등록을 구분)
- Flags(등록 특성)
3) /proc/mount로 보는 실제 매핑(디버그 인터페이스)
QNX는 등록된 prefix entry를 /proc/mount 아래에서 확인할 수 있게 제공합니다(강의에서는 “숨겨진 mount”처럼 설명).
예를 들어 /proc/mount/dev/con1를 보면 “쉼표로 구분된 숫자 5개” 형태가 보이고, 의미는 대략 다음과 같습니다.
- (1) 첫 값: 사용 안 함(항상 0)
- (2) PID: 해당 경로를 등록한 프로세스 ID
- (3) Channel ID: 그 프로세스가 등록 시 사용한 채널
- (4) Index/Handle: 해당 프로세스의 몇 번째 등록인지(등록 식별)
- (5) Flags: 특수 플래그 여부
pidin -p <PID>로 PID를 조회하면 어떤 프로세스가 등록했는지 확인할 수 있습니다(예: devc-con).

4) open()은 어떤 리소스 매니저로 라우팅되는가?
4.1 기본 규칙: “가장 긴 whole-word prefix 매칭”
open("/dev/ser1", ...)을 예로 들면 가능한 후보 prefix:
- / : 매칭 가능(하지만 가장 길지 않음)
- /dev : 이론상 후보지만 “등록자가 없으면” 후보 아님
- /dev/ser1 : 가장 긴 매칭 → 이 경로를 등록한 RM(예: devc-ser8250)이 1순위
중요 포인트:
- /dev/ser 는 /dev/ser1에 대해 whole-word match가 아니므로(ser vs ser1) 그 RM로 가지지 못하고 더 짧은 후보(/ 등)로 fallback 될 수 있습니다.

4.2 /에 다수 등록자가 있을 때(후보 리스트)
open("/home/bill/spud.dat")처럼 구체 prefix가 없고 /만 매칭되는 경우:
- /에 등록된 여러 프로세스(예: procnto, 파일시스템 RM 등)가 후보가 될 수 있음
- 이때 라이브러리(open 내부 구현)는 후보를 순차 시도합니다.
시도/중단 기준:
- ENOENT(file not found) → “이 RM이 담당이 아닌 것 같음”으로 보고 다음 후보 시도
- 그 외 오류(예: EACCES(permission denied), EIO 등) → “찾았는데 실패”로 보고 중단

5) open 경로 해석의 실제 IPC 단계(중요)
QNX에서 open은 단일 시스템 콜처럼 보여도 내부적으로 최소 다음 두 단계를 거칩니다.

5.1 1단계: procnto에게 “어디로 가야 하나?” 질의
- 클라이언트 라이브러리(open)가 procnto에 메시지를 보내
- “이 pathname을 처리할 RM 후보 리스트를 달라”
- procnto는 “긴 prefix 우선”으로 후보 리스트를 반환
5.2 2단계: 후보 RM에 ConnectAttach 후 IO_CONNECT* 전송
- 라이브러리가 첫 후보 RM에 대해:
- ConnectAttach(...)
- connect message(예: _IO_CONNECT_OPEN) 전송
- 성공하면 file descriptor를 얻고 종료
- 실패(ENOENT)면 다음 후보로 넘어가며 반복
추가로 심볼릭 링크 같은 경우:
- RM이 “실제 경로는 다른 경로로 재해석하라”를 반환할 수 있고,
- 그러면 다시 procnto로 돌아가 “새 pathname”으로 해석을 재시작할 수 있습니다.
5.3 open 이후(read/write 등)는 procnto가 빠진다
open이 성공하여 file descriptor가 생기면:
- 이후 read(fd), write(fd), devctl(fd) 등은
- 직접 해당 RM으로 메시지 송수신(send/receive/reply)
- 더 이상 procnto를 거쳐 “검색”하지 않음

6) Resource Manager가 처리하는 메시지 타입 3종
RM이 처리해야 할 이벤트/메시지를 크게 3가지로 나눕니다.
- Connect messages
- pathname 기반 호출이 만드는 메시지
- 대표: open() 계열
- 기타: unlink(), rename() 등도 connect subtype으로 들어올 수 있음
- 성공 시 “클라이언트와 RM 사이의 지속 관계”를 만든다(= FD의 기반)
- I/O messages
- file descriptor 기반 호출이 만드는 메시지
- 대표: _IO_READ, _IO_WRITE, _IO_CLOSE, _IO_DEVCTL, _IO_STAT 등
- “open 성공”이 선행되어야 발생
- Everything else(기타)
- timer pulse, interrupt pulse, private message, worker message 등
- 소개 단계에서는 주로 connect/I/O 중심으로 다룸
7) Connect message 세부: subtype
Connect 메시지는 공통 타입(예: _IO_CONNECT) 아래에 subtype 으로 구분됩니다.
정의는 <sys/iomsg.h>에 있습니다.
예시:
- _IO_CONNECT_OPEN
- _IO_CONNECT_UNLINK
- _IO_CONNECT_RENAME
일반적인 단순 드라이버/디바이스 RM은:
- open 계열만 처리하고(나머지는 기본 동작으로 두거나),
파일시스템형 RM처럼 “이름의 생성/삭제/변경”이 필요한 경우에만 unlink/rename 등을 본격 처리하는 경우가 많습니다.
8) I/O message 예시
I/O 메시지는 각 기능이 별도 타입을 갖는 경우가 많고, 역시 <sys/iomsg.h>에 정의됩니다.
예:
- _IO_READ (read/pread/readdir 등 read 계열 공유 가능)
- _IO_WRITE
- _IO_CLOSE
- _IO_TRUNCATE
- _IO_DUP / dup2
- chmod/chown 등도 FD 기반이면 대응 메시지가 있음

9) Resource Manager 프로세스의 전형적인 구조
리소스 매니저는 본질적으로 “메시지 서버” 프로세스입니다.
전형 흐름:
- Channel 생성 (보통 프레임워크 래퍼 사용)
- procnto에 pathname 등록
- 무한 루프:
- blocking receive(메시지/펄스 대기)
- 메시지 디코드 및 핸들러 디스패치
- 필요 시 resmgr_msgread로 추가 데이터 수신(수신 버퍼보다 큰 write 등)
- MsgReply로 응답(즉시 응답이 일반적)
응답 패턴:
- 오류 반환(예: EPERM/EACCES/EIO 등)
- 성공(상태만)
- 성공 + 데이터(예: read 결과 바이트와 payload)
“지연 응답”(클라이언트 블로킹 유지)도 가능하지만, 이는 고급 주제로 소개 단계에서는 생략하는 것이 일반적입니다.
10) Resource Manager Framework(프레임워크)의 역할(핵심 가치)
QNX는 RM 작성 부담을 줄이기 위해 C 라이브러리 기반 Resource Manager Framework 를 제공합니다.
프레임워크가 해주는 일:
- 기본 데이터 구조 제공
- receive loop/dispatch 편의 함수 제공
- 대부분 메시지 타입에 대해 “합리적 기본 동작(default handler)” 제공
- 개발자는 필요한 부분만 점진적으로 override
- 예: “read만 특화”, “read/write 특화”, “devctl 추가”, … 처럼 단계적 확장
또한 상태 관리:
- 클라이언트 측: FD(file descriptor)
- RM 측: OCB(Open Control Block)
- “클라이언트별/오픈별 상태”를 추적하는 구조체로 이해하면 정확합니다.

11) 설계 관점에서의 한 줄 요약
QNX의 Resource Manager는 “pathname 기반의 객체를 사용자 공간 프로세스가 소유하고, POSIX 호출을 메시지 패싱으로 처리하는 구조” 이며, open 시점에만 procnto가 “가장 긴 prefix 매칭”으로 라우팅을 결정하고, 그 이후 I/O는 해당 RM과 직접 통신한다.
'운영체제 > QNX' 카테고리의 다른 글
| QNX RTOS: 10-3. Handling read() and write() - read() (0) | 2026.01.23 |
|---|---|
| QNX RTOS: 10-2. A Simple Resource Manager (0) | 2026.01.23 |
| QNX RTOS: 9-1. Images & Buildfiles (0) | 2026.01.02 |
| QNX RTOS: 8-6. Kernel Timeouts (0) | 2026.01.02 |
| QNX RTOS: 8-4. High-Resolution Timers (0) | 2026.01.02 |