QNX RTOS: 4-5. Threads - Creation

2025. 11. 26. 16:25운영체제/QNX

QNX는 표준 POSIX API인 pthread_create()를 사용하여 스레드를 생성함. 커널 함수를 직접 호출하는 것보다 이식성과 편의성 면에서 권장되는 방법임.

1. pthread_create() 함수 해부

스레드를 생성하는 표준 함수이며, 4개의 파라미터를 받음.

C
 
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*func)(void *), void *arg);
  1. Thread ID (thread): 생성된 스레드의 ID가 저장될 포인터.
    • QNX 특징: POSIX 표준에서는 필수지만, QNX에서는 NULL을 넣어서 "난 ID 필요 없음"이라고 명시할 수 있음.
  2. Attributes (attr): 스레드의 속성(우선순위, 스택 등)을 정의한 구조체.
    • NULL 전달 시 시스템 기본값(Default)으로 생성됨.
  3. Start Routine (func): 스레드가 실행할 메인 함수 포인터.
    • OS가 스레드 셋업을 마치면 이 함수를 호출함.
  4. Argument (arg): Start Routine에 전달할 인자(Void Pointer).
    • OS는 이 포인터를 검증하거나 역참조하지 않고, 64비트 값 그대로 스레드 함수에 던져줌.

2. 속성 관리 객체 (pthread_attr_t) 패턴

스레드의 동작을 세밀하게 제어하려면 속성 객체(Attribute Object) 패턴을 따라야 함. 이는 "설정"과 "생성"을 분리하는 방식임.

2.1. 설정 흐름

  1. 초기화 (init): pthread_attr_init()으로 구조체를 기본값으로 초기화.
  2. 설정 (set): pthread_attr_set*() 계열 함수로 필요한 속성만 변경.
  3. 생성 (create): 설정된 구조체를 pthread_create()에 전달.
  4. 파기 (destroy): pthread_attr_destroy()로 구조체 정리. (생성된 스레드에는 영향 없음)

참고: pthread_attr_get*() 함수들도 존재하지만, 설정값을 확인하는 용도라 실무에서는 잘 안 쓰임.

3. 핵심 속성 I: 스케줄링 (Scheduling)

RTOS의 꽃인 우선순위 제어임. 단순히 우선순위만 넣는다고 적용되지 않으므로 주의해야 함.

3.1. 상속 끊기 (PTHREAD_EXPLICIT_SCHED)

기본적으로 자식 스레드는 부모 스레드의 우선순위와 정책을 상속받음. 내가 설정한 값을 적용하려면 상속을 명시적으로 끊어줘야 함.

  • pthread_attr_setinheritsched() 함수에 PTHREAD_EXPLICIT_SCHED 플래그 설정 필수.

3.2. 정책 및 파라미터 설정

  • 정책 (setschedpolicy):
    • SCHED_FIFO: 선점형, 같은 우선순위끼리는 먼저 들어온 놈이 끝날 때까지 돎.
    • SCHED_RR (Round Robin): 같은 우선순위끼리는 타임 슬라이스(Time Slice)를 나눠 씀. (예제에서는 이걸 사용)
    • SCHED_SPORADIC: 예산(Budget)과 주기(Period)를 가진 QNX 특화 스케줄링.
  • 파라미터 (setschedparam):
    • 우선순위 값(Priority)을 설정함. (예: 15)

4. 핵심 속성 II: 스택 메모리 (Stack Memory)

임베디드 시스템은 메모리가 제한적이므로 스택 크기 관리가 중요함.

4.1. 기본 스택 사이즈

  • 생성된 스레드: 기본 256KB 할당.
  • 메인 스레드: 프로세스 시작 시 생기는 최초 스레드는 512KB 할당. (이건 pthread 속성으로 변경 불가, 컴파일/링킹 타임에 설정해야 함)

4.2. 스택 크기 변경 (setstacksize)

  • PTHREAD_STACK_MIN 이상이어야 하며, 페이지 크기(4KB) 단위로 라운드 업(Round-up) 됨.

4.3. 가드 페이지 (Guard Page)

  • 역할: 스택 오버플로우(Stack Overflow) 감지용 안전장치.
  • 동작: 스택 끝에 접근 불가능한 가상 메모리 영역(기본 4KB, 1 Page)을 배치함. 스레드가 스택을 넘쳐서 쓰려고 하면, 이 영역을 건드리게 되고 즉시 **Memory Fault (Crash)**를 발생시켜 시스템 오동작을 막음.
  • setguardsize로 크기 조절 가능.

💡 요약 및 인사이트

  1. 제어권 확보: pthread_create의 두 번째 인자(attr)가 핵심임. NULL을 넣으면 편하지만, RTOS답게 쓰려면 속성 객체를 만들어야 함.
  2. 실수하기 쉬운 포인트: 우선순위를 변경하려면 반드시 inheritsched를 EXPLICIT으로 설정해야 함. 안 그러면 부모 우선순위 그대로 따라감.
  3. 안전장치: 가드 페이지(Guard Page)는 스택 오버플로우가 다른 메모리를 오염시키는 것을 막아주는 최소한의 방어선임. (Zero Trust 관점에서도 메모리 침범 방지는 중요함)