이 코드는 어떤 문제를 푸나요?
RT 스케줄러는 우선순위마다 대기열을 두고, 비어 있지 않은 우선순위를 비트맵으로 빠르게 찾습니다. 같은 우선순위 안에서는 큐의 순서가 중요합니다. 여기서는 pick_next_rt_entity 전체를 읽되 entity가 task 자체와 항상 같은 것은 아니라는 점도 함께 봅니다.
읽을 범위: v6.6 · kernel/sched/rt.c · pick_next_rt_entity 1769–1785행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.
먼저 알아둘 개념
우선순위 비트맵
대기열에 후보가 있는 우선순위를 비트로 요약합니다. 모든 큐를 순서대로 길게 탐색하지 않고 첫 유효 비트를 찾을 수 있습니다.
내부 우선순위 번호
이 배열에서는 작은 인덱스가 먼저 선택됩니다. 사용자가 보는 RT priority 숫자와 커널 내부 번호를 그대로 같은 방향으로 읽으면 혼동됩니다.
list_entry
연결 리스트 노드의 주소에서 그 노드를 멤버로 가진 구조체의 주소를 구하는 매크로입니다. 데이터를 복사해서 새 entity를 만드는 것이 아닙니다.
처음 읽을 때
우선순위 인덱스 3에 A·B, 인덱스 8에 C가 있다고 가정하세요. 비트맵에서 3을 고르고 그 큐의 첫 entity A를 찾는 두 단계를 그려 보세요.
더 깊이 살펴볼 때
FIFO와 RR의 차이는 이 선택 함수 한 곳에 다 들어 있지 않습니다. 같은 우선순위의 큐 순서를 언제 바꾸는지, RT 그룹에서는 entity를 따라 어떻게 내려가는지 함께 확인하셔야 합니다.
그림으로 보는 변화

1. 비어 있지 않은 우선순위 찾기
sched_find_first_bit(bitmap)
화살표는 선택 순서입니다. 예시에서 작은 내부 인덱스가 더 높은 우선순위입니다.
2. 해당 우선순위 큐 선택
queue = array->queue + idx
배열 인덱스로 대기열 하나를 찾습니다. 모든 task를 한꺼번에 정렬하지 않습니다.
3. 맨 앞 entity 반환
list_entry(queue->next, ..., run_list)
화살표는 리스트 노드에서 포함 구조체로의 참조 변환입니다. 아직 CPU 레지스터 전환은 하지 않습니다.
pick_next_rt_entity를 한 줄씩 읽기
줄 번호는 v6.6 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.
static struct sched_rt_entity *pick_next_rt_entity(struct rt_rq *rt_rq)
{
struct rt_prio_array *array = &rt_rq->active;
struct sched_rt_entity *next = NULL;
struct list_head *queue;
int idx;
idx = sched_find_first_bit(array->bitmap);
BUG_ON(idx >= MAX_RT_PRIO);
queue = array->queue + idx;
if (SCHED_WARN_ON(list_empty(queue)))
return NULL;
next = list_entry(queue->next, struct sched_rt_entity, run_list);
return next;
}static struct sched_rt_entity *pick_next_rt_entity(struct rt_rq *rt_rq)RT 실행 큐에서 다음 scheduling entity를 고릅니다. 반환형은 task_struct가 아니라 sched_rt_entity 포인터입니다.
struct rt_prio_array *array = &rt_rq->active;현재 활성 우선순위 배열을 가리킵니다. 비트맵과 우선순위별 연결 리스트가 여기에 있습니다.
struct sched_rt_entity *next = NULL;선택 결과를 담을 포인터를 NULL로 초기화합니다.
struct list_head *queue;선택한 우선순위의 리스트 머리를 담을 변수를 준비합니다.
int idx;비트맵에서 찾은 내부 우선순위 인덱스를 저장합니다.
idx = sched_find_first_bit(array->bitmap);비어 있지 않은 우선순위 중 첫 비트를 찾습니다. 내부 번호가 작은 후보를 먼저 고릅니다.
BUG_ON(idx >= MAX_RT_PRIO);유효 RT 우선순위를 찾았다는 전제가 깨지면 커널 버그로 처리합니다. 정상 경로의 일상적인 빈 큐 처리가 아닙니다.
queue = array->queue + idx;찾은 우선순위에 해당하는 리스트 머리 주소를 계산합니다.
if (SCHED_WARN_ON(list_empty(queue)))비트맵에서 찾은 큐가 실제로 비어 있는지 스케줄러 경고 매크로로 확인합니다. 요약 비트맵과 목록의 일관성이 깨진 상태에서 잘못된 entity를 읽지 않도록 합니다.
return NULL;불일치 상태에서 잘못된 entity를 따라가지 않고 NULL을 반환합니다.
next = list_entry(queue->next, struct sched_rt_entity, run_list);첫 리스트 노드의 주소에서 run_list를 포함한 sched_rt_entity 주소를 구합니다. 매크로는 멤버 위치 차이를 이용합니다.
return next;선택한 entity를 상위 선택 경로에 넘깁니다. 그룹 계층이나 최종 task 판단은 호출자가 이어서 합니다.
함께 생각해 볼 질문
먼저 들어온 task가 항상 먼저 실행되나요?
서로 다른 RT 우선순위에서는 우선순위가 먼저입니다. 같은 우선순위 안에서 정책과 큐 순서가 작용합니다.
next 변수는 새 task를 할당한 것인가요?
아닙니다. 기존 큐 노드가 속한 sched_rt_entity의 주소를 얻습니다.
비트맵에 비트가 있는데 큐가 비면 어떻게 하나요?
자료구조의 일관성이 깨진 상황이므로 경고하고 NULL을 반환하는 방어 코드가 있습니다.
출처와 읽은 범위
Linux stable v6.6 · kernel/sched/rt.c
해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고
