[TIL/크래프톤 정글9기] 66일차 (Pintos MLFQS)

1. BSD 4.4 스케줄러와 'nice' 값 개념
- BSD 4.4 스케줄러는 우선순위 기반 스케줄러로, 사용자와 상호작용이 많은(인터랙티브한) 프로세스에 높은 우선순위를 줌
- nice 값은 프로세스가 CPU 시간을 얼마나 양보할 의향이 있는지를 나타내는 정수
- 값 범위: -20(우선순위 상승) ~ 20(우선순위 하락)
- 기본값 0은 우선순위에 영향 없음
- 예를 들어, nice 값이 높으면 "나는 CPU 좀 양보할게"라는 뜻이고, 낮으면 "나는 CPU를 더 많이 써야 해"라는 의미
2. 프로세스 우선순위 계산 공식과 원리
- 우선순위 공식:
priority = PRI_MAX - (recent_cpu / 4) - (nice * 2)
- 여기서,
PRI_MAX는 최대 우선순위 (예: 63)
recent_cpu는 최근 CPU 사용량
nice는 위에서 설명한 값
- 공식의 원리:
- nice 값이 높으면 우선순위가 낮아짐
- 최근 CPU를 많이 사용한 프로세스는 우선순위가 낮아짐
- 우선순위는 4번째 클럭 틱마다 재계산됨
- 계산 결과는 소수점 아래를 버리고 정수로 변환
3. recent cpu란? CPU 사용량 측정법
- recent cpu는 프로세스가 최근에 얼마나 CPU를 사용했는지를 나타내는 값
- 매 클럭 틱마다 현재 실행 중인 프로세스의 recent cpu가 1씩 증가
- 오래전에 CPU를 많이 썼어도, 시간이 지나면 recent cpu 값이 줄어드는 메커니즘
4. dk(감쇠) 계수와 load average 개념
- dk(감쇠) 계수는 recent cpu 값을 줄이는 역할
- 시스템 부하(load average)에 따라 dk 값이 달라짐:
- 부하가 높으면 dk ≈ 1 (recent cpu 값 거의 유지)
- 부하가 낮으면 dk ≈ 0 (recent cpu 값 빠르게 감소)
- load average는 시스템이 얼마나 바쁜지를 나타내는 지표로, 실행 대기 중인 프로세스 수와 실행 중인 프로세스 수를 가중 평균하여 계산
5. 우선순위 재계산과 recent cpu 업데이트 규칙
- 4번째 클럭 틱마다 모든 프로세스의 우선순위를 재계산
- 매 클럭 틱마다 실행 중인 프로세스의 recent cpu를 1씩 증가
- 매 1초마다 모든 프로세스의 recent cpu 값을 dk * recent_cpu + nice 공식으로 업데이트
- load average도 1초마다 갱신
6. 예시: 3개 프로세스 우선순위 변화 과정
- 프로세스 P1, P2, P3가 있고, 모두 nice=0, load average=0에서 시작
- 첫 클럭 틱에서 모든 프로세스 우선순위는 63 (최대)
- P1이 CPU를 사용하면서 recent cpu가 증가 → 우선순위가 62로 떨어짐
- P2, P3는 우선순위 63 유지 → P2가 CPU를 차지
- 이런 식으로 우선순위가 계속 재계산되면서 CPU가 공평하게 분배됨
7. 고정소수점 연산(Fixed Point Arithmetic) 필요성
- 커널 내에서는 부동소수점 연산이 불가능하므로, 고정소수점 연산을 사용
- 17.14 포맷을 사용: 32비트 중 17비트는 정수 부분, 14비트는 소수 부분, 1비트는 부호
- 이를 위해 변환 함수(정수→고정소수점, 고정소수점→정수)와 사칙연산 함수들을 직접 구현
8. 구현 시 필요한 함수와 구조체 수정
- thread 구조체에
nice와 recent_cpu 필드 추가
- 우선순위 계산 함수 구현
- recent_cpu, load average 계산 함수 구현
- recent_cpu 증가 함수 구현
- 4번째 틱과 1초마다 우선순위와 recent_cpu, load average 재계산 함수 구현
9. 스케줄러 구현 시 주의사항 및 테스트 통과 조건
- 우선순위 기부(priority donation) 기능은 고급 스케줄러 사용 시 비활성화 필요
- lock acquire/release 함수 수정 필요
thread_set_nice, thread_get_nice, thread_get_load_avg, thread_get_recent_cpu 함수 구현

