QNX RTOS: 8-3. Timers

2026. 1. 2. 11:27운영체제/QNX

1. QNX 타이머의 핵심 특징: Tickless 구조

QNX의 타이머 시스템은 본질적으로 tickless 하다.

1.1 일반적인 Tick 기반 OS와의 차이

일반적인 OS에서는:

  • 1ms, 10ms 등 고정 주기(timer tick)
  • 타이머 인터럽트가 주기적으로 발생

하지만 QNX에서는:

  • 주기적인 타이머 인터럽트가 존재하지 않는다
  • 필요할 때만 타이머 인터럽트를 발생시킨다
  • 즉, 다음으로 필요한 타이머 이벤트 시점에 맞춰서만 인터럽트 발생

→  이것이 QNX가 tickless timer 시스템이라 불리는 이유다.


2. Ticksize의 의미 (중요)

Tickless라고 해서 “tick 개념이 아예 없다”는 뜻은 아니다.
QNX에는 여전히 ticksize라는 개념이 존재한다.

2.1 Ticksize란?

  • 부팅 시점부터 누적되는 시간의 해상도(resolution)
  • 하드웨어 타이머 인터럽트가 정렬(alignment) 되는 기준 단위
  • 기본값: 1 ms

Ticksize는:

  • 대부분의 타이머
  • 스케줄링 관련 시간 계산
  • 라운드로빈 타임슬라이스 계산

기준 해상도로 사용된다.

단, High Resolution Timer(HRT) 는 ticksize의 영향을 받지 않는 예외다.


2.2 Round-robin timeslice와 ticksize

QNX에서 round-robin 스케줄링을 사용할 경우:

  • timeslice = ticksize × 4
  • 기본 ticksize가 1ms라면 → timeslice = 4ms

4배 계수는 변경 불가이고,
조정 가능한 것은 ticksize 자체이다.


2.3 Ticksize 변경 방법

Ticksize는 부팅 시점에만 설정 가능하다.

  • procnto 실행 옵션 -c 사용
  • startup 코드에서 설정
procnto -c 2000000   // 예: ticksize = 2ms (2,000,000 ns)

→  즉, 런타임 중에는 ticksize 변경 불가


2.4 현재 ticksize 확인

현재 시스템의 ticksize는 다음 API로 확인 가능하다.

  • ClockPeriod()
  • CLOCK_REALTIME 기준으로 nanosecond 단위 반환

3. Ticksize가 타이머 정확도에 미치는 영향

QNX 타이머는 기본적으로 ticksize 단위로 반올림(round-up) 된다.

3.1 예시: sleep(3.5 ms)

  • ticksize = 1ms
  • 요청: 3.5ms sleep

POSIX 규칙:

  • “요청한 시간보다 덜 자는 것은 안 되지만, 더 자는 것은 가능”

동작 방식:

  • 최소 3 tick은 반드시 지나야 함
  • 결국 4 tick (4ms) 이후에 깨게 됨

3.2 오차 범위

  • 타이머 오차는 최대 ticksize 이내
  • 단, 실제 실행 시점은 스케줄링에 의해 더 지연될 수 있음

예:

  • 타이머 만료 → thread runnable 상태
  • 하지만 더 높은 우선순위 스레드가 실행 중이면
  • 실제 실행은 더 늦어질 수 있음

→ 타이머 오차 ≠ 스케줄링 지연


4. QNX 타이머의 멀티코어 구조

4.1 타이머는 코어별(per-core)로 관리된다

QNX에서 타이머는:

  • 타이머를 생성한 스레드가 실행 중이던 코어의 timer list에 등록
  • 각 코어는 자기만의 타이머 리스트를 가진다

즉:

  • Core 0에서 생성한 타이머 → Core 0의 timer list
  • Core 1에서 생성한 타이머 → Core 1의 timer list

4.2 Core affinity와 타이머 생성 순서 (중요 팁)

스레드에 core affinity를 설정할 경우:

반드시 core affinity 설정 후에 타이머를 생성해야 한다

이유:

  • affinity 설정 전에 타이머 생성 → 다른 코어 timer list에 등록
  • 이후 스케줄링 시 불필요한 코어 간 오버헤드 발생

→ 성능과 예측성을 위해

  • affinity 먼저
  • timer 생성은 나중에

5. 타이머 설정 시 결정해야 할 요소들

타이머를 생성할 때 프로세스는 다음을 결정해야 한다.

  1. 타이머 유형
    • one-shot (1회성)
    • periodic (주기적)
  2. 기준 클록
    • CLOCK_REALTIME
    • CLOCK_MONOTONIC (권장)
  3. 시간 기준
    • absolute time
    • relative time
  4. 초기 만료 시점
  5. 주기(period)
  6. 타이머 만료 시 전달할 이벤트
    • pulse
    • signal
    • thread creation 등

6. POSIX Timer API 기본 흐름

QNX는 POSIX timer API를 그대로 사용한다.

6.1 타이머 생성

timer_create(clockid_t clockid,
             struct sigevent *evp,
             timer_t *timerid);
  • 어떤 clock을 사용할지
  • 타이머 만료 시 어떤 이벤트를 보낼지 결정

6.2 타이머 시작 / 설정

timer_settime(timerid,
              flags,
              const struct itimerspec *new_value,
              struct itimerspec *old_value);
  • itimerspec
    • it_value : 최초 만료 시점
    • it_interval : 주기 (0이면 one-shot)

6.3 타이머 삭제

timer_delete(timerid);

7. 실전 예제: 서버가 주기적으로 Pulse를 받는 타이머

7.1 시나리오

  • 서버 프로세스가 메시지를 처리
  • 동시에 1.2초마다 유지보수/무결성 체크
  • 타이머 만료 시 pulse 형태로 알림

 

 


7.2 핵심 구성 요소

  1. SIGEV_PULSE 이벤트
  2. CLOCK_MONOTONIC 기반 타이머
  3. relative timer
  4. periodic interval = 1.2s

7.3 동작 개념

  • 최초 1.5초 후 타이머 발화
  • 이후 매 1.2초마다 pulse 발생
  • 서버는 MsgReceive()에서
    • 메시지와 pulse를 함께 처리

pulse 판별 기준:

if (rcvid == 0) {
    // pulse
}

7.4 타이머 취소 및 재시작

QNX 타이머는 삭제하지 않고도 취소 가능하다.

  • itimerspec 구조체를 0으로 설정
  • timer_settime() 호출 → 타이머 정지

재시작 시:

  • 다시 원하는 값으로 itimerspec 채워서
  • timer_settime() 재호출

→ timer_delete() 없이 재사용 가능


8. 정리 요약

  • QNX 타이머는 tickless 구조
  • ticksize는:
    • 타이머 해상도
    • 스케줄링 기준 단위
  • 기본 ticksize = 1ms (부팅 시 설정)
  • 타이머 오차 ≤ ticksize
  • 타이머는 코어별(per-core)로 관리
  • core affinity 설정 후 타이머 생성이 중요
  • POSIX timer + pulse 조합은
    • QNX 서버 설계의 핵심 패턴