운영체제#6

LeeMir, 05 April 2021

2강 - Processes and Threads(이어서)


Traditional Unix Scheduling
  • Multilevel Feedback Queue(priority queue)를 사용
  • 매 Time Quantum마다 우선순위를 다시 계산함
  • Bands
    • 우선 순위
      • Swapper(가장 높음)
      • Block I/O device control
      • File manipulation
      • Character I/O device control
      • User processes(가장 낮음)
BSD and SVR3 scheduling
  • 기존 UNIX의 decay factor는 1/2였음
    • 따라서 감소 속도가 너무 빨라 몇 번 수행 안해도 CPU Time이 전부 0이 되어버려 우선순위가 모호해짐
  • BSD에서는 decay factor를 (2 * load_avg / 2 * load_avg + 1)로 사용
Linux Scheduling
  • Scheduling Classes
    • SCHED_FIFO
      • First-In-First-Out real-time threads
      • thread가 스스로 멈출 때까지 실행함
    • SCHED_RR
      • Round-Robin real-time threads
    • SCHED_OTHER
      • Other, non-real-time thread
  • O(1) : SCHED_OTHER Scheduling
    • Active Queue와 Expired Queue가 존재
      • 각 Thread는 우선순위가 높은 순서대로 Active Queue에서 실행돼 Timeslice를 모두 소비하면 Expired Queue로 이동
      • 모든 Thread가 Active Queue에서 Expired Queue로 이동하면, Expired Queue가 Active Queue가 되고 Active Queue가 Expired Queue가 됨
    • I/O-Bound Process에게 높은 우선순위를 주는 정책
    • Task의 실행시간 대비 휴면시간 비율(sleep_avg) 유지
      • Linux에서는 Thread를 Task라고 표현
    • 우선순위와 Time Slice 계산식
      • effective prio = interactive 정도(sleep_avg로 계산) + 정적 우선순위(nice 값에 비례)
      • 새로운 Time Slice = effective prio에 비례
    • Interactive Task는 Timeslice를 모두 소비한 후 Expired Queue로 가지 않고 다시 Active Queue에 넣음
    • 문제점
      • Nice 값이 Timeslice 절대값을 결정
        • Nice = 0인 두 Task는 Timeslice 100ms를 가지며 100ms마다 문맥교환 발생
        • Nice = 20인 두 Task는 Timeslice 20ms를 가지며 20ms마다 문맥교환 발생
      • Nice 값의 차이가 Timeslice 차이에 비례하지 않음
        • Nice 0과 1의 Timeslice는 100ms와 95ms
        • Nice 18과 19의 Timeslice는 10ms와 5ms
      • Timeslice와 Timertick의 정밀도 문제
        • Timer Interrupt
      • Interactive Task 우선 문제
        • Sleep에서 깨어나면 무조건 Active Queue로 들어오는 문제
  • CFS(Complete Fair Scheduler)
    • Con Kolivas가 O(1) 스케쥴러를 개선한 RSDL(Rotating Staircase Deadline Scheduler) 개발
      • I/O-Bound와 CPU-Bound 프로세스 구분을 없애고 CPU 할당시간을 공평하게 분배
    • Ingo Monlar가 CFS 스케쥴러 개발
      • Runqueue를 없애고 RB-Tree 사용
      • Jiffies와 HZ 상수를 이용하지 않고 나노초 단위로 동작
      • 통계적 기법이나 휴리스틱을 이용하지 않음
    • Nice 값에 비례하여 weight 할당, Task들의 weight로부터 Proportion of Processor를 계산
      • 프로세서 실행 시간이 100ms일 때 nice값이 같은 task가 둘이면 Timeslice 50ms 할당, 4개이면 25ms 할당
    • Nice 값 차이가 weight 차이와 비례
      • Nice 0과 5의 weight는 1024와 335, 각 Task의 weight 비율은 1024 / (1024 + 335), 335 / (1024 + 335)로 약 3:1임
      • Nice 5와 10의 weight 비율도 약 3:1임
    • Virtual Runtime : Timeslice와 Timertick의 정밀도 문제 해결
      • 문맥교환 주기가 20ms, 두 Task가 45ms, 15ms씩 수행해야 하면, 실제로는 40ms, 20ms 수행함
      • 이를 해결하기 위해 다음 스케쥴 주기에 각 수행시간(40ms, 20ms)에 Scale Factor(1:3)을 곱하여 Virtual Runtime을 구함
      • 두 Task의 Virtual Runtime(40ms, 60ms)이 같지 않으면 뒤쳐진 Task(40ms)를 수행하여 시간을 보상
    • Sleep에서 깨어난 Task의 Virtual Runtime을 현재 실행되고 있는 Task가 가진 Virtual Runtime중 가장 작은 값으로 설정
    • CFS Run Queue
      • RB(Red-Black) Tree 사용, Task를 Virtual Runtime 기준으로 정렬
      • RB Tree에서 가장 작은 Virtual Runtime을 가진 Task(RB Tree에서 가장 왼쪽 Task) 실행
    • Scheduling Latency Period
      • 모든 Runnable Task가 적어도 한 번씩 실행되기 위한 Interval
    • Task의 Timeslice와 Vruntime 갱신
      • Timeslice = (se->load.weight / cfs_rq -> load.weight) * period
      • Vruntime += (NICE_0_LOAD / se-load.weight) * delta_exec
        • NICE_0_LOAD = 1024
        • delta_exec = Task가 실제 CPU에서 실행된 시간
UNIX SVR4 Scheduling
  • 160개의 Scheduling Queue가 존재하고 이를 세 Priority Class로 나눔
  • Preemption points가 존재
    • Preemption point에 도달하면 우선순위가 더 높은 Process가 있는지 탐색 후 있으면 그 자리에서 Scheduling을 다시함
Windows Scheduling
  • 32개의 Priority가 존재
    • 상위 16개는 Real Time Thread를 위한 Priority
    • 하위 16개는 Valiable Thread를 위한 Priority
  • Thread의 Priority를 동적으로 바꾸면서 실행
  • 철학자 식사 문제
    • 내가 포크를 들고 식사를 하면 내 왼쪽에 있는 사람과 오른쪽에 있는 사람은 식사를 하지 못하는 문제
  • Readers and Writers 문제
    • Reader는 많아도 상관 없으나 Writer는 한 명만 해야하는 문제
    • 그리고 Write가 진행되는 동안 Read는 없어야 함