QNX RTOS: 10-1. Overview of Resource Managers

2026. 1. 23. 17:38운영체제/QNX

1) Resource Manager란?

QNX에서 Resource Manager(리소스 매니저) 는 매우 QNX 특유의 개념으로, “운영체제를 확장하는 것처럼 보이는” 사용자 공간(user space) 프로세스입니다.

핵심 아이디어는 두 가지입니다.

  1. Pathname space(경로 이름 공간) 에 이름을 등록한다
    • 예: /dev/ser1, /dev/con1, /mnt, /home 등
  2. 클라이언트가 그 이름을 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가지로 나눕니다.

  1. Connect messages
    • pathname 기반 호출이 만드는 메시지
    • 대표: open() 계열
    • 기타: unlink(), rename() 등도 connect subtype으로 들어올 수 있음
    • 성공 시 “클라이언트와 RM 사이의 지속 관계”를 만든다(= FD의 기반)
  2. I/O messages
    • file descriptor 기반 호출이 만드는 메시지
    • 대표: _IO_READ, _IO_WRITE, _IO_CLOSE, _IO_DEVCTL, _IO_STAT 등
    • “open 성공”이 선행되어야 발생
  3. 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 프로세스의 전형적인 구조

리소스 매니저는 본질적으로 “메시지 서버” 프로세스입니다.

전형 흐름:

  1. Channel 생성 (보통 프레임워크 래퍼 사용)
  2. procnto에 pathname 등록
  3. 무한 루프:
    • 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과 직접 통신한다.