CPU 스케줄링

CPU-I/O 버스트 주기 (CPU-I/O Burst Cycle)

CPU 스케줄링의 성공은 프로세스의 관찰된 특성, 즉 CPU 실행 주기와 I/O 대기 주기의 반복에 달려 있습니다. 프로세스는 이 두 상태 사이를 번갈아 가며 실행됩니다. 프로세스 실행은 CPU 버스트(burst)로 시작하여, I/O 버스트가 뒤따르고, 다시 다른 CPU 버스트, 다른 I/O 버스트 등이 반복됩니다. 궁극적으로 마지막 CPU 버스트는 실행 종료를 위한 시스템 요청으로 끝납니다1.

CPU 버스트의 지속 시간은 광범위하게 측정되었습니다. 프로세스와 컴퓨터마다 크게 다르지만,

대부분 짧은 CPU 버스트와 적은 수의 긴 CPU 버스트를 특징으로 하는 지수 또는 초지수(hyperexponential) 형태의 빈도 곡선을 보입니다2. I/O 중심 프로그램은 일반적으로 짧은 CPU 버스트를 많이 가지는 반면, CPU 중심 프로그램은 몇 개의 긴 CPU 버스트를 가질 수 있습니다3. 이러한 분포는 CPU 스케줄링 알고리즘을 구현할 때 중요하게 작용할 수 있습니다4.

CPU 스케줄러 (CPU Scheduler)

CPU가 유휴(idle) 상태가 될 때마다 운영체제는 준비 큐(ready queue)에 있는 프로세스 중 하나를 선택하여 실행해야 합니다5. 이 선택 과정은

CPU 스케줄러가 수행하며, CPU 스케줄러는 메모리에 있는 실행 준비 상태의 프로세스 중에서 하나를 선택하여 CPU를 할당합니다6.

준비 큐는 반드시 선입선출(FIFO) 큐일 필요는 없습니다7. 다양한 스케줄링 알고리즘에 따라 준비 큐는 FIFO 큐, 우선순위 큐, 트리 또는 단순히 정렬되지 않은 연결 리스트로 구현될 수 있습니다8. 개념적으로는 준비 큐의 모든 프로세스가 CPU에서 실행될 기회를 기다리며 줄을 서 있습니다9. 큐의 레코드는 일반적으로 프로세스의 PCB(Process Control Block)입니다10.

선점형 및 비선점형 스케줄링 (Preemptive and Nonpreemptive Scheduling)

CPU 스케줄링 결정은 다음 네 가지 상황에서 발생할 수 있습니다11:

  1. 프로세스가 실행(running) 상태에서 대기(waiting) 상태로 전환될 때 (예: I/O 요청 결과 또는 자식 프로세스 종료를 위한

    wait() 호출)12.

  2. 프로세스가 실행(running) 상태에서 준비(ready) 상태로 전환될 때 (예: 인터럽트 발생 시)13.

  3. 프로세스가 대기(waiting) 상태에서 준비(ready) 상태로 전환될 때 (예: I/O 완료 시)14.

  4. 프로세스가 종료될 때15.

상황 1과 4의 경우, 스케줄링 측면에서 선택의 여지가 없습니다. 새로운 프로세스(준비 큐에 있는 경우)가 실행을 위해 선택되어야 합니다16. 그러나 상황 2와 3에서는 선택의 여지가 있습니다17.

스케줄링이 상황 1과 4에서만 발생할 때, 이를

비선점형(nonpreemptive) 또는 협력적(cooperative) 스케줄링이라고 합니다18. 그렇지 않은 경우,

선점형(preemptive) 스케줄링입니다19. 비선점형 스케줄링에서는 CPU가 프로세스에 할당되면, 프로세스는 종료되거나 대기 상태로 전환될 때까지 CPU를 계속 점유합니다20. Windows, macOS, Linux, UNIX를 포함한 거의 모든 현대 운영체제는 선점형 스케줄링 알고리즘을 사용합니다21.

불행히도 선점형 스케줄링은 여러 프로세스 간에 데이터가 공유될 때 **경쟁 조건(race condition)**을 초래할 수 있습니다22. 예를 들어, 한 프로세스가 데이터를 업데이트하는 중에 선점되어 두 번째 프로세스가 실행되면, 두 번째 프로세스는 일관성 없는 상태의 데이터를 읽으려 할 수 있습니다23. 선점은 운영체제 커널의 설계에도 영향을 미칩니다24. 시스템 호출 처리 중 커널이 프로세스를 대신하여 활동(예: I/O 큐 변경)으로 바쁠 수 있습니다25. 이때 프로세스가 변경 도중에 선점되고 커널(또는 장치 드라이버)이 동일한 구조를 읽거나 수정해야 한다면 혼란이 발생합니다26. 대부분의 현대 운영체제는 이제 커널 모드에서 실행될 때 완전히 선점형입니다27.

인터럽트는 언제든지 발생할 수 있으며 커널에 의해 항상 무시될 수는 없으므로, 인터럽트의 영향을 받는 코드 섹션은 동시 사용으로부터 보호되어야 합니다28. 운영체제는 거의 모든 시간에 인터럽트를 받아들여야 합니다. 그렇지 않으면 입력이 손실되거나 출력이 덮어쓰여질 수 있습니다29. 이러한 코드 섹션이 여러 프로세스에 의해 동시에 접근되지 않도록, 인터럽트는 진입 시 비활성화되고 종료 시 다시 활성화됩니다30.

디스패처 (Dispatcher)

CPU 스케줄링 기능에 관련된 또 다른 구성 요소는 **디스패처(dispatcher)**입니다31. 디스패처는 CPU 스케줄러가 선택한 프로세스에 CPU 코어 제어권을 넘겨주는 모듈입니다32. 이 기능에는 다음이 포함됩니다33:

  • 한 프로세스에서 다른 프로세스로의

    컨텍스트 전환(context switching)34.

  • 사용자 모드로 전환35.

  • 해당 프로그램을 재개하기 위해 사용자 프로그램의 적절한 위치로 점프36.

디스패처는 모든 컨텍스트 전환 중에 호출되므로 가능한 한 빨라야 합니다37. 디스패처가 한 프로세스를 중지하고 다른 프로세스를 실행하는 데 걸리는 시간을 **디스패치 지연 시간(dispatch latency)**이라고 합니다38.

Linux 시스템에서

vmstat 명령어를 사용하여 시스템 전체의 컨텍스트 전환 횟수를 확인할 수 있습니다

/proc 파일 시스템을 사용하면 주어진 프로세스의 컨텍스트 전환 횟수를 확인할 수도 있습니다40. 자발적(voluntary) 컨텍스트 전환은 프로세스가 현재 사용할 수 없는 리소스(예: I/O를 위해 블록)가 필요하여 CPU 제어권을 포기할 때 발생합니다41. 비자발적(nonvoluntary) 컨텍스트 전환은 시간 할당량이 만료되거나 더 높은 우선순위의 프로세스에 의해 선점될 때와 같이 프로세스로부터 CPU가 강제로 회수될 때 발생합니다42.

Last updated