Monday, April 14, 2008

Real-time Systems

특정 외부요인이 발현된 시점에서 응답이 있기까지의 시간에 대해 deadline이 제한된 상황에서 동작하는 시스템을 realtime system이라 할 수 있다. 책에서는 soft/hard realtime system으로 나누는데, deadline을 넘겨도 system failure가 발생하지 않는 경우는 soft realtime system 으로 보면 된다.

Latency & Jitter 두 단어에 대하 잠깐 짚고 넘어 가면, Latency는 외부요인이 발생한 시점에서부터 response가 일어나기 전까지의 시간이고, jitter는 연속적인 이벤트들 사이의 시간 편차이다.

Linux에서도 realtime 을 지원하는데, scheduling class 라고 불리는 스케쥴링 정책을 통해서 이루어진다. 세가지 정책이 있는데 flag으로는 SCHED_FIFO, SCHED_RR, SCHED_OTHER로 구분된다.

FIFO Class는 더 높은 우선순위를 가진 프로세스가 들어오기 전까지 FIFO순으로 처리하는 방식이고,

Round-robin 은 같은 우선순위를 가진 프로세스들 간에 RR방식으로 timeslice를 가지고 실행되는 스케쥴링 방식이다.

SCHED_OTHER는 일반적인 스케쥴링 정책이다. 이외에 SCHED_BATCH도 있는데, 다른말로 idle scheduling policy라고도 불린다. 이 정책은 runnable한 프로세스가 없을 때 실행되는 방식으로 realtime 과는 반대 개념으로 동작한다. 스케쥴링을 설정하거나 확인할 때는 sched_getscheduler(), sched_setscheduler()를 사용한다. RR 에서 timeslice 값을 확인하고 싶은 경우에는 sched_rr_get_interval()함수를 사용하면 된다.

Real-time Process를 구현할 때 주의할 사항들이 있는데, 요약하면 아래와 같다고 한다.

  • 무한 루프를 돌 경우 시스템이 응답하지 않게 될 수도 있다.

  • 한 프로세스로 인해 다른 프로세스가 starve하지 않도록 주의해야한다.

  • 자신보다 낮은 우선순위의 프로세스를 busy-wait하는 경우를 주의해야한다(deadlock될수 있음)

  • 개발 시에는 터미널 프로세스를 최상위에 두면 좋다.

  • chrt라는 util-linux 패키지를 쓰면 도움이 된다


Realtime 시스템에서는 생각할 게 많다. 미사일 요격 시스템을 만들어서 잘 동작하다가, 갑자기 중요한 코드를 수행하는데 예를들어 ABM(Anti-Ballistic Missile)를 발사하려는 시점에서 갑자기 해당 코드가 하드디스크에 swap되어 있다고 가정하자. 하드에서 읽어와 메모리에 다시 올리는 순간, 이미 미사일이 나아들어 기지를 덮칠 수도 있다 ㅡ.ㅡ;... realtime 에서 동작하는 프로세스라면 해당 메모리는 swap out되지 않도록 lock해 놓을 필요가 있다.

CPU Affinity를 통해서 realtime process를 설정하는 방법도 있다. multiprocessor를 가진 시스템에서 realtime process를 통작시킨다고 해보자. 이 경우에 모든 일반 프로세스를 한 프로세서에서 동작시키고 중요한 rt 프로세스를 다른 프로세서에서 동작시키면 dealine 안에 job을 마치도록 안전하게 설정 시켜 놓을 수 있다. 간단하게 init 프로세스의 CPU affinity를 한쪽으로 고정시키면 이로부터 fork되는 프로세스들도 같은 affinity를 가지므로 한쪽에서만 돈다. 그리고 원하는 RT 프로세스를 다른 CPU에서 돌도록 하면 된다. 샘플코드를 보자.

// #### init process
cpu_set_t set;
int ret;

CPU_ZERO(&set);
ret = sched_getaffinity(0, sizeof(cpu_set_t), &set);
//check error
CPU_CLR(1, &set); // cpu1에서 못돌게함
ret = sched_setaffinity(0, sizeof(cpu_oset_t), &set);
// check error

// #### real-time process
cpu_set_t set;
int ret;

CPU_ZERO(&set)l
CPU_SET(1, &set);
ret = sched_setaffinity(0, sizeof(cpu_oset_t), &set);
// check error

No comments:

Post a Comment