RTOS(Real Time Operating System)과, 일반적으로 OS라고 불리우는 GPOS(General Purpose Operating System)에 대해서 알아봅니다.
RTOS | GPOS |
---|---|
우선순위 기반 스케쥴링 | 우선순위 보다는 스레드와 프로세스 모두 동일한 순서로 수행. 즉, 높은 스루풋을 기준으로 처리 |
프로그램이 실행되는 시간이 중요한 시스템에 적합 | 동시에 많은 응용 프로그램을 실행하기에 좋음. 우선순위가 높은 하나의 작업을 해야하는 프로세스가 있다고 하더라도, 우선순위가 낮은 여러개의 작업을 먼저 수행할 수 있음(preemptive/non-preemptive) |
항상 우선순위를 기반으로 하고(preemptive), 우선순위가 높은 프로세스를 실행할 때 동안 낮은 우선순위를 가진 프로세스는 실행되지 않음 | |
OS는 스케쥴링된 스레드가 많을수록 latency가 생길 수 있는데, RTOS의 경우 프로세스와 스레드가 모두 지정된 시간 제한 내에 실행되어야 하기 때문에 latency가 없음 |
Foreground/Background system
복잡도가 낮은 소형 시스템은 일반적으로 전경/배경 시스템, 또는 super-loop로 설계됩니다.
super-loop는 각 모듈을 호출하여 원하는 작업(함수)을 수행하는 무한루프(while(1))로 구성되어 있으며, 이것을 배경(Background) 시스템이라 부릅니다. 인터럽트 서비스 루틴(ISR)은 비동기 이벤트들(Foreground)를 처리합니다. 즉, Background에서 작업을 수행하다가 꼭 필요한 시기에 우선순위가 높은 작업을 수행해 주어야 한다면 Foreground; ISR(Interrupt Service Routine)를 처리하게 됩니다.
따라서 위의 그림과 같이, Background가 작업을 수행하다가 인터럽트가 걸리게 되면 멈추고 인터럽트부터 처리합니다(꼭!). 그 이후에야 Background로 복귀가 가능합니다.
Pros and Cons
- 간단한 프로그램 짜기에 용이합니다.
- 커널에 의한 메모리손실이나 수행시간 손실이 없습니다.
- 모든 함수는 우선순위가 같기 때문에, 프로그래머 자신이 순서대로 잘 돌 수 있도록 코드를 짜는 것이 중요합니다.
Real-Time Kernel System
커널기반의 프로그램을 이용하면 위의 Background/Foreground system과 다음과 같은 차이점이 존재합니다.
- 커널을 사용하게 되면, 2.5%정도의 시간을 더 허비하게 됩니다
- 커널 사용시 ROM, RAM을 더 많이 사용하게 됩니다.
- Real-Time Kernel은 MCU의 수행 시간을 컨트롤합니다. 즉, 제일 우선순위가 높은 것 부터 처리할 수 있습니다.
- 한 프로그램에 여러개의 Task가 존재합니다. (즉, 무한루프가 여러개 존재합니다.)
- 각각의 Task들은 자기 자신이 온전히 CPU를 독점하여 사용하는 것 처럼 동작합니다.
(1) 우선 순위가 낮은 작업이 실행 중입니다.
(2) 인터럽트가 발생하면, CPU는 인터럽트 서비스를 담당하는 ISR로 벡터(Array);다수의 데이터를 처리하는 명령어를 가진 CPU ㅡ 를 보냅니다.
(3) ISR은 인터럽트 장치를 서비스 하지만 실제로는 거의 작동하지 않습니다. ISR은 일반적으로 높은 우선 순위를 가진 작업에 신호를 보내거나 메시지를 보냅니다.
(4) ISR이 완료되면 높은 우선순위를 가진 Task를 수행 할 준비가 되었으며, 그 전 중단된 낮은 우선순위의 작업으로 돌아가지 않고 대신 더 중요한 작업으로 Context Switch됩니다.
(5) 우선 순위가 높은 작업은 인터럽트에 응답하여 필요한 처리를 실행하고 수행합니다.
(6) 우선순위가 높은 작업이 완료되면 Task의 시작 부분으로 돌아갑니다.
(7) 낮은 우선순위를 갖고 있던 작업은 인터럽트 되었던 지점에서부터 정확하게 다시 시작합니다.
즉, Background/Foreground System은 모든 일을 수행하는 순서와 끝내는 시간, 그 종류 등을 모두 직접 계산하고 결정해야 합니다. 하지만 Kernel System을 이용하면 해야할 작업의 우선순위를 지정한다면 그것을 알아서 진행시킬 수 있다는 이점이 있습니다.
Context Switching
커널의 스케쥴러가 각 Task를 수행하는 작업을 하게 됩니다. 이 때 원칙에 따라 커널의 종류가 선점형(preemptive)과 비선점형(non-preemptive)로 나뉘게 됩니다.
이 때 Context Switching이 빠른 커널이 꼭 장점만 있는 것은 아닙니다. 왜냐하면, CPU가 가지고 있는 레지스터의 양에 따라서 부과되는 오버헤드의 양이 달라지기 때문입니다. 즉, Context Switching이 Kernel Dependent하면서도 CPU Dependent하므로 이것만으로 커널의 성능을 결정 지을 수는 없게 됩니다.
또한 각각의 Task들은 선언되어 컴파일 되는 순간 스택에 자신의 공간을 갖습니다. 이 때 레지스터 정보를 스택에 Push하고, 수행할 Task의 레지스터 정보를 Pop하여 일을 수행합니다. 이후에 Context Switching을 해야할 때 다시 현재의 레지스터 정보를 스택에 저장하고, 빼내어 수행하는 일을 매우 빠르고 효율적으로 수행하면서 멀티 태스킹을 하게 됩니다.
Non-preemptive v.s Preemptive
비선점형 커널은 ISR로 바로 넘겨주기 전에 돌고 있던 Task로 다시 CPU 점유권을 넘기는 커널입니다. 따라서 아무리 우선순위가 높은 Task가 점유하고자 해도 현재 작업을 수행하고 있는 Task에게 CPU 점유권이 주어집니다. 따라서 이러한 커널은 멀티태스킹을 하기 위해서, Task가 자체적으로 자신의 CPU 점유권을 놓아야 합니다. ex) OS_Dly_wait(100)…
따라서 다음과 같은 특징이 존재하게 됩니다.
- 인터럽트의 지연시간이 짧습니다(응답시간과 복귀시간이 짧아지게 됩니다).
- Task레벨에서도 비재진입 함수를 사용할 수 있게 됩니다(Task에서 제어권을 넘겨주기 전에는 절대로 다른 Task로 제어권이 넘어가지 않기 때문).
- Task의 응답성이 떨어집니다(수행시간이 긴 Task가 점유하게 된다면, 우선순위가 높은 Task가 오랜시간 동안 대기해야 될 가능성).
선점형 커널은 이와 반대로, ISR에서 복귀할 때 최 우선순위를 갖는 Task에게 CPU 점유율을 넘기게 됩니다. 따라서 로직이 조금 더 복잡하지만, 프로그램의 응답성이 매우 개선됩니다.
선점형 커널에서는 최상위 우선순위 Task가 언제 CPU를 받을 수 있을지 알 수 있게 되는데, 그로 인하여 Critical Section, 비재진입 함수의 사용 등에서 문제가 발생하게 됩니다. 아직 Task의 작업이 끝나지 않은 상태에서 더 중요한 Task에 CPU 점유권이 넘어갔는데 비재진입 함수를 호출한다면 데이터가 꼬이게 될 가능성이 존재하게 됩니다(전역변수, …). 따라서 상호 배제적으로 공유자원에 접근하기 위한 방법이 필요하게 됩니다.
그 방법은 다음과 같습니다.
- 인터럽트 enable/disable
- Semaphore의 사용
- TAS(Test and Set)
- Scheduler Lock/Unlcok
Clock Tick, Jitter
Clock Tick이란 정기적으로 일어나는 특별한 인터럽트입니다. Clock Tick을 통하여 CPU의 점유권을 스케쥴러에게 양도하고, 지정한 틱이 지나면 Ready List에 들어가게 됩니다.
하지만 위와 같이 높은 우선순위의 Task와 ISR이 1틱(20ms)만큼 딜레이 하려는 Task보다 선행되어 실행되는 경우, 실제로는 불규칙적인 간격을 보이게 됩니다. 이러한 현상을 Jitter라고 합니다. 따라서 Jitter현상은 Hard Real-Time OS에서 조금 덜한 현상을 보입니다.
Reference
- https://doc.micrium.com/
- http://www.circuitstoday.com/gpos-versus-rtos-for-an-embedded-system
- ‘Operating Systems : Three Easy Pieces’, Remzi H. Arpaci-Dusseau, Andrea C. Arpaci-dusseau