본문 바로가기

개발

Real-Time, RTOS, PREEMPT_RT, CPU Isolation 개념 정복 - 실시간 처리

들어가며

'실시간(Real-time)'이라는 용어는 Embedded 및 FactoryAutomation 산업의 핵심이며,

현장에서 다양한 관점과 의미로 혼용되곤 한다.

또한 자연스럽게 따라오는 '처리 속도'는 모든 SW/HW의 핵심 지표이지만, 실시간성과 도일한 개념으로 혼동되기 쉽다.

 

이번 글에서는 개발자의 입장에서 실시간성, RTOS, RT패치, CPU Isolation 등의 개념을 정리하고,

실제 개발 시 고려해야 할 점들을 학습해 보려 한다.

범용 OS가 발전하고 소프트웨어 아키텍처가 복잡해짐에 따라
OS 스케줄링, 인터럽트, 동시성(Concurrency)과 병렬성(Parallelism) 등 성능에 영향을 미치는 요소가 많아진다.
이 글에서는 기초적인 운영체제 지식이 있다고 가정하며, 직관적인 이해를 위해 극단적인 상황을 가정한다.

실시간성 (Real-time)

실시간성(Real-time)이란 데이터 처리나 시스템 응답이 정해진 시간제한(Deadline) 내에 반드시 완료되는 것을 의미한다.

 

예를 들어, 주기적으로 센서 값을 읽고 제어 신호를 출력하는 시스템의 데드라인이 1ms라면,

해당 작업은 반드시 1ms 이내에 완료되어야 한다.

이때는 애플리케이션 내부 로직뿐만 아니라 최대 응답 시간에 직접적인 영향을 주는 요소들을 함께 고려해야 한다.

  • OS Scheduling 지연
  • Interrupt 처리 지연
  • Mutex 등 동기화 메커니즘에 의한 대기 시간
  • Context Switching 비용
  • Garbage Collector와 같은 메모리 등록 및 해제 시간

Hard Real-Time System vs Soft Real-Time System

두 시스템의 차이는 Deadline을 넘겼을 때 얼마나 치명적인 가로 구분된다.

  • Soft Real-Time: deadline가 품질 저하로 이어짐. (ex. 영상/음성 스트리밍, 게임 렌더링, 회복/대응이 가능한 공장시스템 등)
  • Hard Real-Time: deadline miss가 곧 실패. (ex. 미사일, 항공, 의료, 인공위성 제어 등)

프로그램이 Deadline을 만족하는지 확인하고 보장하는 방법에는 두 가지 측면이 있다.

  1. 측정 기반(Measurement-based)
    다양한 조건과 시뮬레이션을 수없이 반복하여 경험적인 최악의 실행 시간(WCET, Worst Case Execution Time)을 도출한다.
  2. 계산 및 증명 기반(Static Analysis)
    코드 수준에서 구조적 실행 횟수가 확정적이라면 수학적으로 WCET를 엄밀하게 계산할 수 있다.
    예를 들어, 다음의 코드에서 최악의 조건 분기에서 반복문을 1,000번 수행함을 보장할 수 있으므로, 하드웨어 명령어 처리 시간을 기반으로 전체 소요 시간을 증명할 수 있다.
// 한 명령어 시간 = CPU 클럭 + 명려어 사이클 수 + 메모리 접근 조건
if(condition) {
  for (int i=0; i<10; i++)
  	sum += i;
} else {
  for (int i=0;i <1000; i++)
    sum += i;
}

 


RTOS (Real-Time Operating System)

RTOS는 실시간 작업에 대해 예측 가능한 응답 시간(Determinism)을 지원하도록 설계된 운영체제이다.

 

범용 OS에 비해 우선순위 기반 스케줄링, 짧고 예측 가능한 인터럽트/스케줄링 지연, 단순한 커널 구조를 갖추어 개발자가 실시간성을 분석하고 보장하기 아주 쉬운 구조와 API를 제공한다.

즉, RTOS는 실시간성을 분석하고 보장하기 쉬운 구조 를 제공한다.

범용OS 와 RTOS의 차이


RTOS에 대해 가지는 오해

첫 번째는 ❌RTOS는 무조건 빠를 것 이라는 생각이다.

OS 동작 측면에서 불필요한 스위칭이나 군더더기가 없어 즉각적이라고 할 수는 있지만,

순수 연산의 실행 속도는 CPU 클럭에 비례한다.

 

오히려 여러 작업을 동시에 처리해야 하는 상황에서는

멀티코어 최적화 및 GPU 가속을 적극적으로 활용하는 범용 OS의 전체 처리량(Throughput)이 훨씬 높고 빠를 수 있다.

따라서 RTOS의 본질은 '단순 속도'가 아니라 '결정성(Determinism)'에 있다.

 

두 번째 오해는 ❌RTOS를 사용하면 Deadline을 절대 넘기지 않는다 는 바람이다.

RTOS 자체가 지연을 없애주지는 않고, 시스템 설계가 잘못되어 인터럽트가 폭주하면 RTOS도 당연히 지연된다.

다만, 범용 OS는 이런 지연의 크기를 계산하기 불가능해 사후 장애로 인지하게 된다면,

RTOS는 그 지연 시간의 최댓값을 사전에 분석 가능하고 통제 가능하게 설계할 수 있다.

  • 범용 OS : 인터럽트 발생 시 얼마나 늦을지 계산이 어려움 → 막연하게 기다리며 사후에 알게 됨
  • RTOS : 인터럽트 실행 전 예측가능함 → 대응 로직 설계 가능

 

RTOS의 종류와 빌드

대표적인 RTOS는 FreeRTOS, VxWorks, Micrium, QNX 등이 있다.

주로 C/C++ 언어로 개발하며 OS별로 호환되는 특정 툴체인을 통해 펌웨어를 빌드하게 된다.

 

RTOS는 커널 코어가 공통된 스케줄링 및 락 메커니즘을 제공하지만, ARM Cortex-M, RISC-V, x86 등 타깃 시스템이 되는 CPU 아키텍처에 맞춘 포팅 계층(Porting Layer)이 필요하다.

저수준의 콘텍스트 스위칭 기법, 타이머 Tick 발상 제어, 스택 프레임 구조 등 하드웨어 의존적인 파트를 이어줘야 하기 때문이다.

 

더불어 타깃 보드의 주변장치(UART, SPI, I2C, GPIO 등)를 제어하려면 하드웨어 초기화 코드와 드라이버 모음인 BSP(Board Support Package) 혹은 HAL(Hardware Abstraction Layer) 과의 결합이 필수적이다.

 

다행히 일반적인 실무 개발에서는 커널을 직접 짜는 대신, 이미 잘 만들어진 RTOS 커널과 벤더의 HAL을 융합해 그 위에서 애플리케이션 Task를 얹어 개발할 것이다.


RT 패치 (PREEMPT_RT)

정식 명칭은 PREEMPT_RT로 기존 리눅스(Linux) 커널의 구조를 수정하여 실시간성을 지원하도록 만든 기술이다.

커널의 선점·락·인터럽트 동작 구성을 변경해 실시간성을 제공한다.

RT 패치라고 용어는 Linux에 덧붙이던 '패치 셋'으로 출발했기 때문에 과거에 불리던 이름이다.
Linux Kernel 6.12 버전부터 공식적으로 병합되어 PREEMPT_RT라는 이름으로 발표되었다.

PREEMPT_RT의 기술적 핵심은 커널 내부의 비선점 구간을 최소화하고, 인터럽트 처리를 스레드로 처리 하여 개발자가 우선순위 기반으로 인터럽트 처리를 스케줄링을 가능하게 만드는 데 있다.

 

실시간성을 가져야 하는 'Task B'가 동작하는 Linux OS의 타임라인을 상상해 보자.

기존 Linux 커널은 Hardware IRQ 처리를 최우선시하여 모든 IRQ를 처리 한 뒤 Task B가 실행된다.

최악의 경우 Interrupt가 많이 발생한다면, Task B는 아예 실행되지 못할 수 있다. (실시간성을 보장하지 못함)

기존 Linux Kernel의 Inturrupt 처리 타임라인

 

반면 PREEMPT_RT 커널은 Kernel이 선점하는 구간을 줄이고 IRQ 후처리를 Thread로 처리하는 구조이다.

따라서 Task B의 우선순위가 높다면 IRQ thread보다 먼저 실행되도록 보장받을 수 있다.

이는 인터럽트 발생 시 TaskB가 실행될 것을 예측할 수 있음을 의미한다. (실시간성 보장)

PREEMPT_RT Kernel의 Inturrupt 처리 타임라인

Jitter (지터)

Jitter의 사전적 의미는 전송 신호가 이상적인 기준 시간으로부터 미세하게 흔들리는 지연시간을 의미한다.
즉, 기존 Linux 커널에서는 하드 IRQ나 커널의 비선점 락에 치여 Task B의 시작 주기가 일정하지 않게 흔들릴 수 있다.
반면, PREEMPT_RT는 태스크를 선점가능하게 만들어 Jitter를 줄이고 분석 가능하게 만들었다는 데 의미를 가진다.

예시) 1ms 주기의 태스크 실행
  Task 실행 1회 차 Task 실행 2회 차 Task 실행 3회 차
범용 OS 1.0ms 1.7ms 2.3ms
RTOS 또는 PREEMPT_RT 1.0ms 1.01ms 1.03ms

 CPU Isolation

앞서 Jitter에 대해 살펴본 내용을 기준으로 보면,

RTOS 또는 PREEMPT_RT는 커널 내부의 비선점 구간과 인터럽트 처리 지연을 줄여 Kernel Jitter를 완화한 것을 알 수 있다.

 

하지만 여전히 다음과 같은 이유로 OS Jitter가 발생할 수 있다.

  • context switch 시간
  • mutex, semaphore 등 동기화 객체 대기 시간
  • 같은 우선순위 태스크 간 round-robin 스케줄링
  • 주기적 timer tick
  • IRQ thread, kworker, RCU callback 등 커널의 housekeeping 작업
  • 드라이버 및 백그라운드 시스템 작업

이러한 수십 마이크로초 수준의 방해마저 용납할 수 없는 환경에서, 멀티코어 자원을 분할하는 CPU Isolation을 고려할 수 있다.

CPU Isolation란 특정 CPU 코어를 특정 작업에 사용하도록 격리 하여 OS작업과 분리하는 기법이다.

일반 CPU 코어 IRQ 처리, 커널 스레드, 백그라운드 작업 수행
Isolated CPU 코어 중요한 실시간 태스크 위주로 실행

이를 통해 태스크가 실행되는 환경을 더 단순하고 조용하게 만들어, OS Jitter를 좀 더 줄일 수 있다.


마치며

이번에는 "실시간성"이라는 단어로 시작해, 평소 막연하던 다가왔던 추상적 개념들을 공부해 보았다.

필요성이 대두될 때 가장 밀도 있게 성장하듯, 현재 개발 중인 SW PLC 프로젝트에 도입하기 위해 집중적으로 학습할 수 있었다.

 

최근에는 생산 설비가 정교하고 민감해짐에 따라, 과거 군사 제어기나 항공 우주 등급에서나 주로 논의되던 이러한 딥다이브 기술들이 일반 Factory Automation 산업에도 빠르게 들어오는 것을 느꼈다.

 

이번 기회를 통해 기초적인 개념을 정확하게 잡았고,

특히 RealTime → RTOS → PREEMPT_RT → CPU Isolation 과정으로 스토리를 가지고 개념을 확실하게 다질 수 있었다.

이제 앞으로 다가올 현장의 시스템 한계점과 장단점을 부딪혀가며 기술 영역을 보다 넓게 확장해 나가야겠다.

 

ps. 작년 Qt Coco 툴을 사용한 Code Coverage 분석교육을 들었는데, 이번에 WCET(Worst Case Execution Time) 개념에서, 프로그램 코드를 통해 최악의 소요시간을 수학적으로 측정하고 증명한다는 포인트가 굉장히 흡사하고 흥미로웠다.

부족한 부분이나 더 궁금한 주제가 있다면 댓글로 남겨주세요.
직접 공부해서 다음 글로 정리해 보려고 합니다.