CFS로 다중 프로세스 관리하기

출처 : http://www.ibm.com/developerworks/kr/library/l-cfs/index.html


CFS 다중 프로세스 관리하기 (한글)

리눅스를 위한 CFS 소개

http://www.ibm.com/i/c.gif

 

http://www.ibm.com/i/c.gif

난이도 : 중급

Avinesh Kumar, 시스템 소프트웨어 엔지니어, IBM 

2008 4 08

리눅스(Linux®) 커널 2.6.23에는 모듈화된 스케줄러 코어와 스케줄링 모듈로 구현된 CFS(Completely Fair
Scheduler)
탑재되어 있습니다. 기사에서는 CFS 주요 기능을 다루며, 동작 원리를 살펴보고, 2.6.24 버전에 기대하는 가지 변화를 미리 짚어보기로 합니다.

커널 2.6.23 탑재된 스케줄러는 코어와 병렬로 움직이는 다른 스케줄링 모듈을 탑재하도록 길을 열어 놓았다. (여기서모듈이라는 의미는 스케줄러를 메모리에 적재 가능한 모듈로 쪼갠다는 뜻이 아니라 코드 자체가 모듈로 구성되어 있다는 뜻이다.) 스케줄러 동작 방법이 궁금하다면 (뒤에 나올 참고자료 절에 링크를 제시한) “Inside the Linux
scheduler”
라는 developerWorks 기사를 살펴보기 바란다.

주요 기능과 정책

최신 스케줄러에 들어간 주요 기능은 다음과 같다.

  • 모듈화된 스케줄러
  • CFS(Completely
    Fair Scheduler)
  • CFS
    그룹 스케줄링

모듈화된 스케줄러

스케줄링 클래스 도입은 코어 스케줄러를 확장 가능하게 만들어준다. (스케줄러 모듈) 클래스는 스케줄링 정책을 캡슐화한다. 이런 스케줄러는 스케줄링 정책을 모듈화하지만 플러그인 방식으로 동작하는 CPU 스케줄러 프레임워크처럼 스케줄러 자체를 모듈화 방식으로 구현하지는 않았다. (스케줄러 자체를 모듈화 방식으로 구현하면 기본 스케줄러는 커널 빌드 시점에 선택되며, 다른 CPU 스케줄러는 시동 시점에서 커널에 인수로 넘어간다).

CFS

CFS CPU 시간을 필요한만큼 사용하도록 태스크를 돌리려고 시도한다. 이런 방식은 모든 프로세스가 CPU 공평하게 사용하도록 만든다. CFS 태스크가아주짧은 시각 동안 잠든다면 태스크가 오랫동안 잠들 것이라고 간주하지 않는다. 짧게 잠드는 태스크에 보너스 시간을 받는 자격을 부여하지만 잠들지 않았을 때와 비교해 유리하게 보너스 시간을 늘이지는 않는다.

CFS 그룹 스케줄링

컴퓨터 대에서 작업을 돌리고 있는 사용자 A B 생각해 보자. A 단지 작업 개만 돌리고 있는 반면에, B 작업을 48개나 돌리고 있다. 그룹 스케줄링은 시스템에서 돌아가는 작업 50 전부를 공평하게 취급하는 대신 사용자 A B에게 공평하게 CPU 배분한다. 사용자 모두 50 50으로 CPU 공유한다. B 48 작업에 자신의 공유몫인 50% 투입하며, A 확보한 50% 빼앗아가지는 못한다.

(kernel/sched_fair.c 구현된) CFS 스케줄링 모듈은 SCHED_NORMAL, SCHED_BATCH, SCHED_IDLE이라는 스케줄링 정책을 사용한다. SCHED_RR SCHED_FIFO 정책이 필요하면 (kernel/sched_rt.c 구현된 모듈인) 실시간 스케줄링 모듈을 사용한다.

스케줄러에 변화가 생긴 이유는 다음과 같다.

  • 데스크톱은 물론이고 서버에서도 스케줄링을 좀더 강화하기 위한 목적
  • 요청받은 새로운 기능을 제공하기 위한 목적
  • 휴리스틱을 개선하기 위한 목적. 표준 스케줄러에 사용하던 휴리스틱은 간단한 구현으로 인해 공격 받기 쉬웠다. 또한 휴리스틱이 시나리오를 잘못 판단할 경우 원하지 않는 부작용이 생길 수도 있었다.

 

http://www.ibm.com/i/v14/rules/blue_rule.gif

http://www.ibm.com/i/c.gif

 

RSDL 비교한 CFS

http://www.ibm.com/i/c.gif

RSDL(Rotating Staircase DeadLine Scheduler)
RSDL
휴리스틱으로 미래를 예측하려고 시도하기 위해(물론 실패했지만) 통계 정보를 사용했던 과거 리눅스 프로세스 스케줄러 알고리즘에서 상호대화식 추정 코드를 제거한 프로세스 스케줄러다.
RSDL
공평함이라는 개념에 기반을 둔다. 프로세스를 동등하게 취급하며 동일한 시간 구획을 할당해 놓았다. 스케줄러는 프로세스가
CPU
묶여있는지
I/O
묶여있는지 신경을 쓰지도 심지어 추측조차 하지도 않는다. RSDL 사용자가 느끼는상호대화성 개선했고, 원본 O(1) 프로세스 스케줄러 아버지인 Ingo Molnar CFS 만들 RSDL로부터 공평한 스케줄링이라는 기본적인 설계 요소를 참고했으며, 한창 리눅스 커널 2.6으로 통합 중이다. (Con Kolivas 만든) RSDL 물론 인기가 좋지만, CFS 많은 해커들이 특별히 인정하는 알고리즘이다.

상호 대화성 측면에서 지연 시간을 단축하려는 목표와 충돌을 일으키지 않고서공평한 스케줄링 달성할 있다는 증명의 영광은 Con Kolivas에게 돌아갔다. Kolivas RSDL/SD 스케줄러로 프로세스의 상호 대화성을 추정하기 위한 복잡한 휴리스틱이 없이도 공평성을 달성할 있다는 사실을 증명했다.

CFS 우선순위 배열을 사용하지 않으며 표준 스케줄러의 배열 전환 편법을 제거했다. RSDL CFS 사이에 존재하는 가지 중요한 차이점은 다음과 같다.

  • RSDL엄격한 공평성 기반을 둔다. 하지만 CFS 상호 대화식 프로세스에서 잠든 시간을 고려하므로 짧게 잠드는 프로세스가 많은 CPU 시간을 얻게 된다.
  • RSDL 표준 스케줄러처럼 우선 순위 큐를 사용하지만
    CFS
    그렇지 않다.
  • RSDL 표준 스케줄러는 배열 전환 편법에 영향을 받지만 CFS 그렇지 않다.

CFS 잠든 시간을 추적하지 않으며 비활성 태스크를 인식하기 위한 휴리스틱도 사용하지 않는다. CFS CPU에서 실행가능한 프로세스 숫자에 맞춰 주어진 시간 동안 CPU 공평하게 사용하도록 만든다.

중요한 CFS 자료 구조

CFS CPU마다 시간 순서로 배열한 레드블랙 트리를 사용한다.

http://www.ibm.com/i/c.gif

위키백과에 정의된 레드블랙 트리
위키백과
따르면, 레드블랙 트리는 스스로 균형을 잡는 이진 탐색 트리로 연상 배열을 구현하는 사용하는 자료 구조다. 모든 실행 중인 프로세스에 대해, 레드블랙 트리 내부에 노드가 정해진다. 레드블랙 트리의 가장 좌측 위치에 존재하는 프로세스는 바로 다음에 스케줄된다. 레드블랙 트리는 복잡하지만, 연산 과정에서 최악의 경우에도 실행 시간을 보장하며, 실전에서 효율적으로 동작한다. 레드블랙 트리는 O(log n) 시간에 탐색, 삽입, 삭제가 가능한데 여기서 n 트리에 속한 원소 개수다. 잎사귀 노드는 의미가 없으며 자료를 포함하지 않는다. 메모리 절약을 위해 때로 단일 마지막 표식 노드가 모든 잎사귀 노드의 역할을 수행하기도 한다. 내부 노드에서 잎사귀 노드를 참조할 경우 마지막 표식 노드를 가리킨다.

레드블랙 트리 접근 방식은 다음과 같은 이유 때문에 CFS 적합하다.

  • 레드블랙 트리는 항상 균형이 잡혀있다.
  • 레드블랙 트리는 이진 트리이므로 탐색 연산에 들어가는 시간이 로그를 따른다. 하지만 가장 좌측을 벗어난 검색은 거의 수행하지 않으며 가장 좌측을 따라가는 포인터를 항상 캐시한다.
  • 레드블랙 트리는 대다수 연산 과정에서
    O(log n)
    따르지만, 과거 표준 스케줄러는 고정된 우선 순위 숫자만큼 우선 순위 배열을 만드는 방법으로
    O(1)
    따른다. O(log n) 상당이 느리게 보이지만 태스크 숫자가 아주 많을 경우에만 표가 난다. 이는 CFS 스케줄러를 만든 Molnar 트리 접근 방법을 시도하면서 가장 먼저 테스트해 내용이다.
  • 레드블랙 트리는 내부 저장소로 구현할 있다. 따라서 자료 구조 저장을 위해 외부 할당이 필요하지 않다.

여기서 신형 스케줄러 구현에 필요한 몇몇 핵심 자료 구조를 살펴보자.

struct task_struct에서 일어난 변화

CFS struct prio_array 제거했으며, struct
sched_entity
 struct
sched_class
각각 정의하는 스케줄링 엔티티와 스케줄링 클래스를 도입했다. 동시에 task_struct sched_entity sched_class라는 가지 다른 구조체에 대한 정보를 포함한다.


Listing 1. task_struct
구조체

struct task_struct { /*
Defined in 2.6.23:/usr/include/linux/sched.h */

….

   struct prio_array *array;

+  struct sched_entity se;

+  struct sched_class *sched_class;

   ….

   ….

};

 

struct sched_entity

구조체는 태스크나 태스크 그룹의 스케줄링 작업을 실제 달성하기 위해 충분한 정보를 포함한다. 구조체는 그룹 스케줄링을 구현하는 쓰인다. 스케줄링 엔티티는 프로세스와 연관이 없을 수도 있다.


Listing 2. sched_entity
구조체

struct sched_entity { /*
Defined in 2.6.23:/usr/include/linux/sched.h */

 long wait_runtime;   /* Amount of time the entity must run to
become completely */

                      /* fair and
balanced.*/

 s64 fair_key;

 struct load_weight   load;         /* for load-balancing */

 struct rb_node run_node;            /* To be part of Red-black tree
data structure */

 unsigned int on_rq;

 ….

};

 

struct sched_class

스케줄링 클래스는 코어 스케줄러를 돕는 모듈을 연결해 놓은 고리처럼 보인다. 스케줄러 모듈은 struct sched_class 제안하는 기능 집합으로 구현할 필요가 있다.


Listing 3. sched_class
구조체

struct sched_class { /*
Defined in 2.6.23:/usr/include/linux/sched.h */

      struct sched_class *next;

      void (*enqueue_task) (struct rq *rq,
struct task_struct *p, int wakeup);

      void (*dequeue_task) (struct rq *rq,
struct task_struct *p, int sleep);

      void (*yield_task) (struct rq *rq,
struct task_struct *p);

 

      void (*check_preempt_curr) (struct rq
*rq, struct task_struct *p);

 

      struct task_struct *
(*pick_next_task) (struct rq *rq);

      void (*put_prev_task) (struct rq *rq,
struct task_struct *p);

 

      unsigned long (*load_balance) (struct
rq *this_rq, int this_cpu,

                 struct rq *busiest,

                 unsigned long max_nr_move,
unsigned long max_load_move,

                 struct sched_domain *sd,
enum cpu_idle_type idle,

                 int *all_pinned, int
*this_best_prio);

 

      void (*set_curr_task) (struct rq
*rq);

      void (*task_tick) (struct rq *rq,
struct task_struct *p);

      void (*task_new) (struct rq *rq,
struct task_struct *p);

};

 

Listing
3
나온 몇몇 함수를 살펴보자.

  • enqueue_task: 태스크가 실행 가능한 상태로 진입할 함수가 호출된다. 함수는 스케줄링 엔티티(프로세스) 레드블랙 트리에 집어넣고 nr_running 변수값을 하나 증가시킨다.
  • dequeue_task: 태스크가 이상 실행 가능한 상태가 아닐 , 레드블랙 트리에서 해당 스케줄링 엔티티를 제외하기 위해 함수가 호출된다. 함수는 nr_running 변수값을 하나 감소시킨다.
  • yield_task: compat_yield sysctl 켜지 않는 이상 함수는 기본적으로
    dequeue
    따라오는
    enqueue
    . 경우 스케줄 엔티티를 레드블랙 트리의 가장 우측 부분에 집어넣는다.
  • check_preempt_curr: 함수는 현재 동작 중인 태스크가 선점당할 있는지를 점검한다. CFS 스케줄러 모듈은 실제로 동작 중인 태스크를 선점하기 앞서 공평성 테스트를 수행한다. 함수는 깨우기 선점을 수행한다.
  • pick_next_task: 함수는 다음으로 실행하기에 가장 적합한 프로세스를 선택한다.
  • load_balance: 스케줄러 모듈은 모듈의 load_balance() 루틴에서 호출하는 반복자(iterator) load_balance_start() load_balance_next()라는 함수 쌍을 구현하고 있다. 코어 스케줄러는 메서드를 활용해 스케줄링 모듈이 관리하는 프로세스 부하를 분산한다.
  • set_curr_task: 함수는 태스크가 스케줄링 클래스를 바꾸거나 태스크 그룹을 바꿀 호출된다.
  • task_tick: 함수는 주로 타임 함수가 호출하며 프로세스 전환이 일어날지도 모른다. 함수는 동작 선점을 수행한다.
  • task_new: 코어 스케줄러는 새로운 태스크 시동을 관리할 기회를 스케줄러 모듈에 부여한다.
    CFS
    스케줄링 모듈은 함수를 사용해 그룹 스케줄링을 처리한다. 반면에 실시간 태스크를 위한 스케줄링 모듈은 함수를 사용하지 않는다.

runqueue에서 CFS 관련있는 필드

runqueue마다 연관된 레드블랙 트리에 대한 정보를 담고 있는 구조체가 있다.


Listing 4. cfs_rq
구조체

struct cfs_rq {/*
Defined in 2.6.23:kernel/sched.c */

      struct load_weight load;

      unsigned long nr_running;

 

      s64 fair_clock; /* runqueue wide
global clock */

      u64 exec_clock;

      s64 wait_runtime;

      u64 sleeper_bonus;

      unsigned long wait_runtime_overruns,
wait_runtime_underruns;

 

      struct rb_root tasks_timeline; /* Points
to the root of the rb-tree*/

      struct rb_node *rb_leftmost; /*
Points to most eligible task to give the CPU */

      struct rb_node *rb_load_balance_curr;

#ifdef
CONFIG_FAIR_GROUP_SCHED

      struct sched_entity *curr; /*
Currently running entity */

      struct rq *rq;      /* cpu runqueue to which this cfs_rq
is attached */

     

     

#endif

};

 

http://www.ibm.com/i/v14/rules/blue_rule.gif

http://www.ibm.com/i/c.gif

 

CFS 동작 원리

CFS 스케줄러는 공평성을 보장하기 위한 유화 정책을 활용한다. 태스크가 실행 큐에 들어오면 현재 시각을 기록하고, 프로세스가 CPU 기다리는 동안 wait_runtime 값은 현재 실행 큐에 들어있는 프로세스 숫자에 따라 특정 값만큼 증가한다. 이런 계산 과정에서 태스크마다 붙어있는 우선 순위 또한 고려한다. 태스크가 CPU 스케줄링이 일어날  wait_runtime 값은 줄어들기 시작하며, 값이 다른 태스크가 레드블랙 트리의 가장 좌측 태스크가 되는 수준까지 떨어지면 현재 태스크는 선점된다. 이런 방식으로 CFS wait_runtime 0 되는 이상적인 상황을 연출하려 노력한다.

CFS fair_clock(cfs_rq->fair_clock)이라는 실행 전반을 다루는 시계에 상대적인 태스크 실행 시간을 유지한다. fair_clock 실시간으로 아주 짧은 시간 동안 동작하므로 단일 태스크를 위한 이상적인 속력을 유지한다.

http://www.ibm.com/i/c.gif

정밀도와 지연 시간이 무슨 관계일까?
정밀도와 지연 시간 사이에 연관 관계를 간단한 수식으로 나타내면 다음과 같다. 

gran = (lat/nr) – (lat/nr/nr) 
여기서 gran = 정밀도, 
lat =
지연 시간, 
nr =
실행 중인 태스크 숫자.

예를 들어 실행 가능한 태스크가 가지 있다면, fair_clock 일반 시계 속력의 1/4 움직인다. 태스크는 이런 이상적인 시간을 따라잡기 위해 노력한다. 결국 이는 시분할 멀티태스킹이라는 양자화된 특성이 낳은 결과가 된다. 다시 말해, 단지 단일 태스크만 특정 시간에 동작하므로 다른 태스크는 (wait_runtime) 축적한다. 일단 태스크가 스케줄링이 되고 나면 쌓아 놓은 빚을 해소한다(fair_clock 빚을 갚는 순간에도 멈추지 않고 똑닥거리므로 이자도 갚아야 한다).

우선순위는 태스크 가중치를 두는 방법으로 처리한다. 태스크 개가 있다고 가정하자. 태스크 하나는 다른 태스크와 비교해 CPU 시간을 배로 소모해 2:1 비율을 유지한다. 산수 계산을 이용해 태스크에 가중치 0.5 부여해 시간이 배로 빨리 지나가버리도록 만든다.

fair_clock 기반으로 트리에 태스크를 밀어넣는다.

시간 구획(time slice) 놓고 보면, 우선 순위 결정에 CFS 이를 적극적으로 활용하지 않는다. CFS에서 시간 구획은 가변 길이이며 동적으로 결정된다.

부하 균등을 위해 스케줄링 모듈은 반복자를 구현해 부하 균등 작업을 하는 방식으로 스케줄링 모듈이 관리하는 모든 태스크를 순회하도록 만든다.

실행 조율값

실행 스케줄러를 조율하기 위한 중요한 sysctls 다음과 같다(이름이 ns 끝나는 항목은 나노초 단위임을 나타낸다).

  • sched_latency_ns: CPU 밀접한 태스크를 위한 선점 지연 목표 시간
  • sched_batch_wakeup_granularity_ns: SCHED_BATCH 위한 깨우기 정밀도
  • sched_wakeup_granularity_ns: SCHED_OTHER 위한 깨우기 정밀도
  • sched_compat_yield: sched_yield() 행동 양식에 크게 의존하는 응용 프로그램은 값을 바꾸는 CFS 특성 때문에 성능 편차가 생길 있다. 이럴 경우 하위 호환성을 유지하기 위해 sysctls 값을 활성화하도록 권장한다.
  • sched_child_runs_first: 기본값은 1 fork 후에 자식을 먼저 스케줄한다. 값이 0이면 어버이에게 바통을 넘긴다.
  • sched_min_granularity_ns: CPU 밀접한 태스크를 위한 최소 선점 정밀도
  • sched_features: 여러 디버깅 관련 기능에 대한 정보를 포함
  • sched_stat_granularity_ns: 스케줄러 통계 수집을 위한 정밀도

여기에 시스템에서 사용하는 전형적인 실행 매개변수 값을 정리했다.


Listing 5.
전형적인 실행 매개변수

[root@dodge ~]# sysctl
-A|grep “sched” | grep -v “domain”

kernel.sched_min_granularity_ns
= 4000000

kernel.sched_latency_ns
= 40000000

kernel.sched_wakeup_granularity_ns
= 2000000

kernel.sched_batch_wakeup_granularity_ns
= 25000000

kernel.sched_stat_granularity_ns
= 0

kernel.sched_runtime_limit_ns
= 40000000

kernel.sched_child_runs_first
= 1

kernel.sched_features =
29

kernel.sched_compat_yield
= 0

[root@dodge ~]#

 

새로운 스케줄러 디버깅 인터페이스

새로운 스케줄러는 상당히 뛰어난 디버깅 인터페이스로 무장하고 있으며, 실행 시간 통계 정보 역시 제공하는데, 각각 kernel/sched_debug.c kernel/sched_stats.h 구현되어 있다. 스케줄러와 디버깅 정보를 위한 실행 시간 통계를 제공하기 위해 proc 가상 파일 시스템에 몇몇 파일이 추가되었다.

  • /proc/sched_debug:
    실행 스케줄러 현재 조율 , CFS 통계, 모든 사용 가능한 CPU에서 실행 정보를 출력한다. proc 파일을 읽을 sched_debug.c 정의된 sched_debug_show() 함수를 호출한다.
  • /proc/schedstat:
    실행 큐와 밀접한 통계와 연결된 모든 CPU 대한 SMP 시스템 관련 통계를 출력한다. proc 파일을 읽을 kernel/sched_stats.h 정의된 show_schedstat() 함수를 호출한다.
  • /proc/[PID]/sched:
    연관된 스케줄링 엔티티에 대한 정보를 출력한다. proc 파일을 읽을 kernel/sched_debug.c 정의된 proc_sched_show_task() 함수를 호출한다.

 

http://www.ibm.com/i/v14/rules/blue_rule.gif

http://www.ibm.com/i/c.gif

 

커널 2.6.24 위한 변경

커널 2.6.24 버전에 기대되는 몇몇 변경 사항이 무엇일까? 전역 시계(fair_clock) 추적을 대신해 태스크는 서로서로를 추적한다. (스케줄러 엔티티인) 태스크 시계인 vruntime 도입했고(wall_time/task_weight), 근사치 평균으로 새로운 태스크용 시계를 초기화한다.

다른 중요한 변화는 핵심 자료 구조체에 영향을 미친다. 여기에 struct sched_entity에서 일어난 스케줄러 관련 변경 사항을 정리한다.


Listing 6.
커널 2.6.24 위한 sched_entity 구조체 스케줄러 관련 변경 사항

struct sched_entity { /*
Defined in /usr/include/linux/sched.h */

– long    wait_runtime;

– s64     fair_key;

+ u64     vruntime;

– u64     wait_start_fair;

– u64     sleep_start_fair;

     

     

}

 

struct
cfs_rq
에도 변화가 있다.


Listing 7.
커널 2.6.24 위한 cfs_rq 구조체 스케줄러 관련 변경 사항

 struct cfs_rq { /* Defined in
kernel/sched.c */

         s64 fair_clock;

         s64 wait_runtime;

         u64 sleeper_bonus;

         unsigned long
wait_runtime_overruns, wait_runtime_underruns;

+        u64 min_vruntime;

 

+        struct sched_entity *curr;

 

+#ifdef
CONFIG_FAIR_GROUP_SCHED

      

+        struct task_group *tg;    /* group that “owns” this
runqueue */

      

#endif

 };

 

태스크를 그룹으로 묶기 위해 새로운 구조체를 도입했다.


Listing 8.
새롭게 추가된 task_group 구조체

struct task_group { /*
Defined in kernel/sched.c */

    #ifdef CONFIG_FAIR_CGROUP_SCHED

        struct cgroup_subsys_state css;

   #endif

        /* schedulable entities of this
group on each cpu */

        struct sched_entity **se;

        /* runqueue “owned” by
this group on each cpu */

        struct cfs_rq **cfs_rq;

        unsigned long shares;

        /* spinlock to serialize
modification to shares */

        spinlock_t lock;

        struct rcu_head rcu;

};

 

태스크는 실행 시간을 추적하며 태스크는 값에 따라 큐에 들어간다. 가장 최근에 실행된 태스크가 가장 좌측에 있음을 의미한다. 다시 한번 말하지만, 가중치에 따라 우선 순위가 정해진다. 태스크는 다음 시간 동안 정확하게 한번 스케줄되도록 노력한다.

sched_period
= (nr_running > sched_nr_latency) ? sysctl_sched_latency : ((nr_running *
sysctl_sched_latency) / sched_nr_latency)

여기서 sched_nr_latency = (sysctl_sched_latency /
sysctl_sched_min_granularity)
이다. 다시 말해 latency_nr 실행 가능 태스크보다 많으면 스케줄링 주기는 선형으로 늘어난다. sched_fair.c 정의된 sched_slice() 이런 계산을 맡고 있다.

따라서 실행 가능한 태스크가 sched_slice() 시간 동안 동작하면, sched_period 시간을 소비한 결과가 되므로 태스크는 가중치에 비례하는 시간만큼 동작하게 것이다. 걸음 나가, 어떤 시점에서도 CFS sched_period 앞서 동작하리라 약속하는 이유는 마지막으로 스케줄된 태스크는 해당 윈도우 내에서 다시 한번 동작하기 때문이다.

따라서 새로운 태스크가 실행 가능한 상태가 재배치에는 엄격한 요구 조건이 따른다. 태스크는 다른 모든 태스크가 동작하기 전에는 동작하지 못한다. 그렇지 않다면 태스크 사이에 맺어진 약속이 깨져버린다. 하지만 이런 태스크가 큐에 들어가므로 실행 큐에 할당된 추가 가중치가 모든 다른 태스크 슬라이스의 시간 구획을 줄여버리며, sched_priod 무렵에 새로운 태스크가 필요로 하는 정확한 크기로 슬롯을 비워버리게 된다. 이제 새로운 태스크가 여기에 위치한다.

2.6.24에서 그룹 스케줄링 개선 사항

커널 2.6.24에서 태스크뿐만 아니라 사용자나 그룹에 공평하게 스케줄러를 조율할 있다. 엔티티를 형성하도록 태스크를 함께 그룹으로 묶어 놓으면, 스케줄러는 이런 엔티티와 엔티티에 속하는 태스크에 공평하게 동작한다. 이런 기능을 활성화하려면, 커널 빌드 과정에서CONFIG_FAIR_GROUP_SCHED 선택해야 한다. 현재까지는 SCHED_NORMAL SCHED_BATCH 태스크만 그룹으로 묶을 있다.

그룹 태스크를 지정하는 가지 독립적인 방법은 다음에 기반한다.

  • 사용자 ID
  • cgroup
    가상 파일 시스템: 옵션은 관리자가 필요에 따라 그룹을 생성하게 만든다. 세부 사항은 커널 원시 코드 문서 디렉터리에 있는 cgroups.txt 읽어보기 바란다.

커널 환경 설정 매개변수인 CONFIG_FAIR_USER_SCHED CONFIG_FAIR_CGROUP_SCHED 옵션 선택을 돕는다.

 

http://www.ibm.com/i/v14/rules/blue_rule.gif

http://www.ibm.com/i/c.gif

 

정리

새로운 스케줄러는 스케줄링 클래스 도입으로 스케줄링 기능을 확장했으며, 스케줄 통계를 개선하는 방법으로 디버깅 작업을 간단하게 만들었다. CFS 3D 게임을 비롯해 스레드를 많이 사용하는 응용 프로그램 테스트 과정에서 좋은 평가를 받고 있다.

감사글

CFS 스케줄러 개발에 중요한 공헌을 Peter Zijlstra에게 감사한다. Zijlstra 바쁜 일정에도 불구하고 기사에 대한 조언과 제안을 아끼지 않았다. CFS 그룹 스케줄링 구현에 Srivatsa Vaddagiri RSDL 만든 Con Kolivas에게도 감사한다. 또한 기사에 관심을 보여준 리눅스 스케줄러 메인테이너인 Ingo Molnar에게도 특별히 감사의 말을 전한다.

 

참고자료

교육


제품 기술 얻기

  • DB2®,
    Lotus®, Rational®, Tivoli®, WebSphere®
    같은 최신 IBM 시험판 소프트웨어를 포함하는 장짜리 DVD 세트인 SEK for Linux 주문하자. 
  • IBM 평가판 소프트웨어:
    developerWorks
    에서 직접 내려 받아 다음번 리눅스 프로젝트에 활용하자.


토론

 

Leave a Reply