16. 라운드 로빈 스케줄러를 추가하자

들어가기

라운드 로빈 스케줄러를 구현하는 방법에 대해 알아보자.

본론

16.1 스케줄러와 리스트

16.1.1 스케줄러의 역할과 종류

  • 스케줄러는 태스크를 특정 기준에 따라 정렬하여 실행 순서를 결정.
  • 프로세서의 사용률을 높이고 성능을 향상시킬 수 있음.
  • 일정한 시간마다 돌아가면서 공평하게 실행하는 라운드 로빈 방식.
  • 태스크가 많아지면 프로세서를 할당 받을때 까지 시간이 오래 걸림.
  • 우선순위별로 라운드 로빈 방식을 적용할 필요.
    • 멀티레벨 큐.
    • 멀티 피드백 큐.

16.1.2 스케줄러와 자료구조

  • 스케줄러가 태스크를 선택하려면 실행할 태스크를 모아 놓을 자료구조가 필요.
  • 삽입, 제거 기능을 포함한 검색이나 임의의 위치에 데이터를 제거하는 기능이 필요, 리스트.

16.1.3 범용 리스트의 설계외 구현

// 데이터를 연결하는 구조체
typedef struct kListLinkStruct{
    void* pvNext;
    QWORD qwID;
} LISTLINK;

// 리스트를 관리하는 구조체
typedef struct kLiskManagerStruct{
    int iItemCount;

    void* pvHeader;
    void* pvTail;
} LIST;
  • 리스트를 구현하는데 있어 핵심적인 부분은 다음 데이터의 어드레스를 관리하는 것.
  • 다음 데이터의 어드레스를 구조체 내에서 정의하면 쉽게 관리.
  • 삽입할 때와 달리 리스트에 데이터를 제거할 때는 네 가지 경우를 고려.
    • Header와 Tail의 값이 아무것도 없을 때.
    • 가운데에 있는 데이터를 제거할 때.
    • 리스트에 데이터가 2개 이상 존재하고, 처음이나 맨 뒤를 제거할 때.
  • 18.3 코드 참조.

16.2 태스크 풀과 스케줄러

16.2.1 태스크 풀과 스택 풀 설계

typedef struct kTCBPoolManagerStruct {
    TCB* pstStartAddress;
    int iMaxCount;
    int iUseCount;

    int iAllocatedCount
}
  • 태스크 풀은 태스크 자료구조를 모아 놓은 자료 공간, 태스크를 생상하거나 삭제할 때 사용할 TCB가 모여 있는 특정 메모리 영역.
  • 태스크 풀을 IST 영역 이후에 별도 공간에 할당할 예정.

16.2.2 태스크 풀과 스택 풀 구현

  • 구현할 운영체제에서는 최대 1024개의 태스크를 생성할 수 있게 설정.
  • 태스크를 할당하기 위해서는 태스크 풀을 검색해 TCB가 할당된 상태인지, 해제된 상태인지를 확인.
  • iAllocatedCount와 TCB의 ID의 상위 32비트를 OR 연산하여 태스크를 구분.
  • 해제 상태를 나타내는 필드를 쓰지 않고, ID 필드에 통합하여 관리하는 이유는 TCB ID의 중복을 막고자 하는 것.
  • 18.3 코드 참조.

16.2.3 라운드 로빈 스케줄러 설계

typedef struct kSchedulerStruct {
    // 현재 수행 중인 태스크
    TCB* pstRunningTask;

    // 할당된 프로세서의 시간
    int iProcessorTime;

    // 실행할 태스크가 준비 중인 리스트
    List stReadyList;
}
  • 대기 중인 태스크의 목록과 현재 수행 중인 태스크 정보만 있으면 작동.

16.2.4 라운드 로빈 스케줄러 구현

  • 부팅 과정에서 새로운 TCB를 할당받아 현재 수행 중인 태스크에 설정, 태스크를 전환할 때 부팅 과정을 진행한 태스크의 콘텍스트를 저장.
  • 태스크를 전환하는 함수는 태스크 수행하는 중에 전환하는 코드와 인터럽트가 발생했을 때 전환하는 코드로 구분.
  • 태스크 수행 중에 전환하는 함수는 인터럽트가 발생하지 못하도록 막는 코드를 포함해야 함.
  • 인터럽트가 발생하면 IST에 이미 콘텍스트가 저장된 상태이므로, 콘텍스트를 따로 저장할 필요 없이 IST에서 TCB로 복사.

16.2.5 시분할 멀티태스킹 구현

  • 시분할 멀티태스킹 기법은 일정한 시간을 개별 태스크에 할당하고 해당 시간이 만료되면 태스크를 강제로 전환하는 방식.
  • PIT 컨트롤러가 발생시키는 IRQ 0 인터럽트를 활용.

16.3 라운드 로빈 스케줄러의 통합과 빌드

16.3.1 리스트 파일 추가

List.c 코드 보기
List.h 코드 보기

16.3.2 태스크 파일 수정

Task.c 코드 보기
Task.h 보드 보기

16.3.3 인터럽트 관련 파일과 유틸리티 파일 수정

ISR.asm 코드 보기
interruptHandler.c 코드 보기
interruptHandler.h 코드 보기
Utility.c 코드 보기
Utility.h 코드 보기

16.3.4 C 언어 커널 엔트리 포인트 파일과 콘솔 셸 파일 수정

Main.c 코드 보기
consoleShell.c 코드 보기

16.3.5 빌드와 실행


  • 라운드 로빈 방식으로 화면 출력 태스킹을 수행.

마치며

끝.. 코드를 이해하면 길이 보인다…..

Share