리눅스 커널은 다양한 작업을 처리하기 위해 스케줄러를 사용한다. 스케줄러는 시스템에서 실행되는 여러 프로세스와 스레드의 우선순위를 관리하고, 이들 작업이 CPU를 효율적으로 사용할 수 있도록 배치한다. Preempt RT 패치는 리눅스 커널의 스케줄러를 실시간 성능을 극대화하기 위해 최적화하는 것을 목표로 한다. 이 장에서는 리눅스 스케줄러의 기본 구조와 실시간 스케줄링이 어떻게 구현되는지에 대해 알아본다.
리눅스 스케줄러의 기본 개념
리눅스 스케줄러는 각 프로세스와 스레드의 우선순위와 정책에 따라 CPU 시간을 할당한다. 일반적으로 사용되는 스케줄링 정책은 SCHED_OTHER (기본 공정 스케줄링), SCHED_FIFO, SCHED_RR 등이 있다. Preempt RT에서는 실시간 작업의 경우 SCHED_FIFO와 SCHED_RR이 주로 사용된다.
SCHED_FIFO와 SCHED_RR
SCHED_FIFO와 SCHED_RR은 리눅스에서 제공하는 실시간 스케줄링 정책으로, 고정된 우선순위 기반 스케줄링을 수행한다. 이들 정책은 다음과 같은 특징을 갖는다:
-
SCHED_FIFO (First-In, First-Out): 우선순위가 높은 작업이 먼저 실행되며, 동일한 우선순위의 작업들은 먼저 들어온 작업이 먼저 실행된다. 한 번 실행되면 자발적으로 CPU를 내놓기 전까지 계속 실행되며, 이는 선점 불가(non-preemptible) 특성을 갖는다.
-
SCHED_RR (Round Robin): SCHED_FIFO와 비슷하지만, 동일한 우선순위의 작업들이 일정한 시간 퀀텀(quantum) 동안 번갈아가며 CPU를 점유한다. 각 작업이 퀀텀 동안 실행되면, 다른 동일 우선순위 작업으로 CPU가 넘겨진다.
실시간 스케줄링에서 우선순위
실시간 스케줄링에서 우선순위는 매우 중요한 요소이다. 리눅스에서는 각 작업이 가질 수 있는 우선순위 범위가 다음과 같다:
- 일반 작업: 우선순위 0~99
- 실시간 작업: 우선순위 100~139
실시간 작업은 일반 작업보다 항상 높은 우선순위를 가지므로, 실시간 스케줄링이 중요한 시스템에서는 실시간 작업이 일반 작업보다 우선적으로 처리된다.
스케줄링 클래스
리눅스 커널은 각 스케줄링 정책을 스케줄링 클래스로 구분한다. 예를 들어, CFS(Completely Fair Scheduler)는 일반 작업을 위한 스케줄링 클래스이고, RT 스케줄러는 실시간 작업을 위한 스케줄링 클래스이다.
스케줄링 클래스는 각 작업에 할당된 정책에 따라 결정되며, 각 클래스는 자체적인 스케줄링 규칙을 적용한다. Preempt RT에서는 RT 스케줄러가 강화되어 실시간 시스템의 요구사항을 충족하도록 설계되었다.
스케줄링 알고리즘
리눅스의 RT 스케줄러는 고정된 우선순위 스케줄링을 사용하며, 이를 통해 실시간 응답성을 보장한다. RT 스케줄러의 주요 알고리즘은 다음과 같다:
-
우선순위 기반 스케줄링: 작업이 준비 상태에 있을 때, 가장 높은 우선순위를 가진 작업이 먼저 CPU를 할당받는다.
-
선점(Preemption): 높은 우선순위 작업이 준비 상태로 전환되면, 현재 실행 중인 작업을 중단시키고 높은 우선순위 작업을 즉시 실행한다.
-
스케줄링 퀀텀: SCHED_RR 정책의 경우, 동일한 우선순위를 가진 작업들이 일정한 퀀텀 동안 CPU를 번갈아가며 사용한다.
우선순위 역전과 해결 기법
실시간 시스템에서는 우선순위 역전(priority inversion)이라는 문제가 발생할 수 있다. 이는 낮은 우선순위의 작업이 높은 우선순위의 작업보다 먼저 실행되어, 높은 우선순위 작업의 실행이 지연되는 상황을 말한다. 우선순위 역전은 실시간 시스템의 안정성과 응답성을 저해할 수 있으므로 이를 해결하기 위한 기법이 필요하다.
우선순위 상속(priority inheritance)은 우선순위 역전을 해결하기 위한 대표적인 기법 중 하나이다. 이 기법에서는 낮은 우선순위의 작업이 높은 우선순위의 작업이 필요로 하는 자원을 소유할 때, 낮은 우선순위 작업이 임시로 높은 우선순위를 상속받아 자원을 사용하는 동안 계속 실행되도록 한다. 자원 사용이 끝나면 원래의 우선순위로 되돌아간다.
커널 선점과 Preempt RT의 역할
리눅스 커널은 기본적으로 비선점 커널(non-preemptive kernel)이다. 이는 커널 모드에서 실행되는 작업이 스케줄러에 의해 강제로 중단되지 않는다는 것을 의미한다. 그러나 실시간 시스템에서는 낮은 레이턴시와 높은 응답성이 중요하기 때문에, Preempt RT 패치는 커널을 선점 가능(preemptible)하도록 변경한다.
Preempt RT 커널은 커널이 사용자 공간뿐만 아니라 커널 공간에서도 선점 가능하도록 수정된다. 이를 통해 실시간 작업이 더 낮은 레이턴시로 커널 자원에 접근할 수 있게 되어 실시간 성능이 크게 향상된다.
실시간 스케줄링 정책의 적용 사례
실시간 스케줄링 정책은 다양한 실시간 응용 프로그램에서 적용될 수 있다. 대표적인 예로는 다음과 같다:
-
로봇 제어 시스템: 로봇 제어 시스템은 높은 응답성과 정밀한 제어가 요구되므로, SCHED_FIFO 또는 SCHED_RR 정책을 사용하여 제어 루프의 스케줄링을 관리한다.
-
오디오/비디오 스트리밍: 오디오 및 비디오 데이터는 시간에 민감한 처리가 필요하므로, 실시간 스케줄링 정책을 사용하여 스트리밍 데이터를 처리한다.
-
산업 자동화 시스템: 산업 자동화에서는 실시간으로 센서 데이터를 처리하고 제어 명령을 내리는 것이 중요하므로, RT 스케줄러를 사용하여 각 작업의 우선순위를 관리한다.
RT 스케줄러의 튜닝
실시간 성능을 극대화하기 위해서는 RT 스케줄러의 튜닝이 필요하다. 다음은 튜닝을 통해 실시간 성능을 향상시킬 수 있는 방법들이다:
-
우선순위 설정: 실시간 작업의 우선순위를 적절히 설정하여 중요한 작업이 적시에 실행될 수 있도록 한다.
-
커널 파라미터 조정: 커널 파라미터 중, 시스템 틱(tick)이나 타이머 해상도 등을 조정하여 더 나은 실시간 성능을 얻을 수 있다.
-
IRQ 핸들링 최적화: 인터럽트 요청(IRQ) 핸들링을 최적화하여 실시간 작업이 인터럽트로 인해 지연되지 않도록 한다.
스케줄링 디버깅과 모니터링
실시간 시스템의 스케줄링 성능을 검증하고 최적화하기 위해서는 스케줄링 동작을 디버깅하고 모니터링할 필요가 있다. 리눅스에서는 이러한 목적으로 여러 도구를 제공한다:
-
ftrace: 커널 내부의 함수 호출과 실행 경로를 추적할 수 있는 도구로, 실시간 스케줄링의 정확성을 검증하는 데 유용하다.
-
perf: 실시간 작업의 CPU 사용량과 실행 시간을 분석할 수 있는 도구로, 스케줄링 효율성을 모니터링할 수 있다.
-
cyclictest: 주기적인 타이머 지터(jitter)를 측정하여 실시간 성능을 평가하는 도구이다. 이는 Preempt RT 시스템의 레이턴시를 측정하는 데 자주 사용된다.
이와 같은 도구들을 활용하면, 실시간 스케줄링의 성능을 면밀히 분석하고 필요한 최적화를 수행할 수 있다.