피드로 돌아가기
RTOS Scheduling — What Nobody Told You
Dev.toDev.to
Backend

RTOS Scheduling — What Nobody Told You

임베디드 엔지니어가 우선순위 역전(Priority Inversion)으로 인한 모터 제어기 주기적 정지 현상을 2일 간의 로직 분석 끝에 발견해 RTOS 스케줄링 메커니즘 이해의 필요성 제시

Shyam Kumar2026년 3월 26일12intermediate

Context

RTOS 기반 모터 제어 시스템이 6시간 주기로 예측 불가능하게 정지되고 워치독이 리셋하는 현상이 발생했다. 낮은 우선순위의 로깅 태스크가 뮤텍스를 점유한 상태에서 높은 우선순위의 모터 태스크가 필요로 하는 리소스를 획득할 수 없었고, 중간 우선순위의 CAN 핸들러가 로거를 계속 선점하면서 모터 태스크가 완전히 기아 상태에 빠졌다.

Technical Solution

  • 스케줄러 작동 원리 명확화: 고정 우선순위 시스템에서 스케줄러는 '현재 준비 상태의 가장 높은 우선순위 태스크'를 선택하는 단일 원칙으로 작동하며, ARM Cortex-M에서 CLZ 어셈블리 명령어 하나로 O(1) 시간에 최고 우선순위 태스크를 선택
  • 태스크 상태 모델 정확한 이해: BLOCKED 상태는 태스크가 동작하지 않고 0 CPU 사용하며 특정 이벤트를 대기하는 효율적인 대기 상태임을 명확히 함
  • vTaskDelay() vs vTaskDelayUntil() 구분: vTaskDelay()는 깨어난 시점부터 지연을 계산해 실행 시간 누적으로 주기 드리프트가 발생하므로, 주기 태스크는 마지막 깨어남 시점 기준으로 정확한 주기를 유지하는 vTaskDelayUntil() 사용
  • 명확한 에러 처리 패턴: 인터럽트 핸들러에서 xHigherPriorityTaskWoken 플래그를 검사해 portYIELD_FROM_ISR()로 즉시 컨텍스트 스위칭하여 실시간 응답성 보장
  • 스택 오버플로우 조기 감지: configCHECK_FOR_STACK_OVERFLOW = 2로 설정해 모든 컨텍스트 스위칭 시점에 0xA5 패턴 검사 수행 및 uxTaskGetStackHighWaterMark()로 런타임 여유 공간 모니터링

Impact

  • Cortex-M4 @ 168MHz에서 10µs 이하의 컨텍스트 스위칭 지연
  • 스케줄러의 태스크 선택이 태스크 개수와 무관하게 단일 CLZ 명령어로 완료되어 O(1) 시간 복잡도
  • Rate Monotonic Analysis(RMA) 기준 n→∞일 때 최대 CPU 사용률 69.3%

Key Takeaway

RTOS의 진정한 가치는 시스템을 빠르게 만드는 것이 아니라 예측 가능한 타이밍을 제공하는 데 있으며, 스케줄링 메커니즘의 구체적 작동 원리(컨텍스트 스위칭, 태스크 상태 전이, 우선순위 역전)를 정확히 이해해야만 임베디드 실시간 시스템의 예측 불가능한 장애를 효과적으로 진단할 수 있다.


FreeRTOS 기반 임베디드 시스템을 개발하는 팀에서 vTaskDelayUntil()을 모든 주기 태스크에 적용하고, 각 태스크의 스택 크기를 configCHECK_FOR_STACK_OVERFLOW = 2로 설정된 오버플로우 감지와 uxTaskGetStackHighWaterMark() 모니터링으로 검증하면, 예측 불가능한 타이밍 오류와 메모리 손상으로 인한 워치독 리셋을 사전에 방지할 수 있다.

원문 읽기