☆★☆2016.01.07 작성☆★☆
☆★☆참고책 _리눅스 커널 내부구조(저자_백승재, 최종무)☆★☆
7. 런 큐와 스케줄링
- 스케줄링을 위한 수행 가능 상태의 태스크를 자료구조를 통해 관리
* 런 큐(run queue) : 리눅스에서의 스케줄링을 위한 자료구조
운영체제에 따라 1개, 여러개(CPU별 1개의 런 큐 유지)
* 태스크 생성
- init_task 라는 헤더를 가진 이중 연결 리스트에 삽입
- 다중 CPU의 경우, 자식 태스크는 부모 태스크의 런 큐에 삽입(캐시 친화력↑)
- 대기 상태에서 깨어난 태스크는 대기 전의 런 큐에 삽입(캐시 친화력↑)
+ 캐시 친화력? 호출했던 것을 다시 호출할 확률 ↑(시간/공간 캐시)
* 스케줄링
① 실시간 태스크 스케줄링
- FIFO, RR
: 우선 순위 설정을 위해 rt_priority(realtime prioirty) 필드 사용(0~99까지의 우선순위)
태스크가 수행을 종료하거나, 스스로 중지하거나, 자신의 슬라이스를 다 사용할 때까지 CPU 사용
고정 우선순위
항상 우선순위가 높은 태스크가 먼저 수행되는 것 보장
- DAEDLINE
: deadline이 가까운 태스크를 우선순위로 두고 스케줄링 대상으로 선정(우선순위의 기준이 다름)
② 일반 태스크 스케줄링(CFS : Completely Fair Scheduler)
- 완벽하게 공평한 스케줄링 추구
- 정해진 시간 단위 내에 존재하는 태스크에 공평한 CPU 시간 할당
- vruntime(virtual runtime) : 각 태스크가 가진 값
CPU를 사용하는 경우 사용 시간과 우선순위를 고려하여 증가
부모의 우선순위와 동일
사용자 수준에서 -20~19 / 커널 수준에 (사용자 수준 우선순위 + 120) -> 100~139
실시간 태스크의 우선순위(0~99) 보다 항상 낮은 우선순위를 가짐(100~139)
runtime = runtime * ( weight(0) / weight(curr) )
- 우선순위가 0인 태스크의 weight 값을 현재 태스크의 weight 값으로 나누어 runtime에 곱함
- 우선순위가 높은 태스크의 경우 CPU를 좀더 오래 사용할 수 있도록 시간이 느리게 흐르는 것처럼 관리
우선순위가 낮은 태스크의 경우 CPU를 조금만 사용하도록 시간이 빠르게 흐르는 것처럼 관리
* 스케줄링 대상인 태스크 선택 문제
① 가장 작은 vruntime 값의 태스크를 스케줄링 대상으로 선정 :
- 새롭게 생성된 태스크의 빠른 수행 시도
- RBtree 자료구조 이용(가작 좌측에 있는 vruntime이 최소 값)
Red Black tree 예
② 타임슬라이스 지정
- 시간 단위를 태스크의 우선순위에 기반하여 태스크에 분배
* 스케줄러 호출
- 호출 방법 : schedule() 함수 호출, 태스크의 thread_info구조체 내부의 need_resched 필드 설정
- 호출하는 경우
: need_resched 필드를 보고 스케줄러의 필요가 있을 때
현재 수행 태스크의 타임 슬라이스를 모두 사용 or 이벤트 대기할 때
새로운 태스크 생성, 대기 상태의 태스크가 깨어날 때
현재 태스크가 스케줄링 관련 시스템 콜을 호출할 때
8. 문맥 교환
* 문맥 교환(Context switch) : 수행 중 태스크의 동작을 정지하고 다른 태스크로 전환하는 과정
* 문맥 저장(Context save) : 문맥 교환되는 시점에서 수행 정도라든지, 현재 CPU의 레지스터 값이 얼마인지 등의 정보를 저장
* 문맥(CPU register)는 task_structure의 thread에 struc_thread_struct 형태로 저장
9. 태스크와 시그널
* 시그널 : 태스크에게 비동기적인 사건의 발생을 알리는 매커니즘
* 태스크의 원할한 시그널 처리
- 다른 태스크에게 시그널 송신 : sys_kill() 함수
- 시그널 수신 : signal, pending 변수(task_structure)
- 시그널 처리 : sys_signal() 함수, sighand 변수(task_structure)
* 시그널 매커니즘 : 시그널 번호를 구조체로 정의, 큐에 등록하는 구조
- 특정 pid 태스크 종료시, pid(tgid의 개념)가 동일한 태스크들(쓰레드를 공유한)에 시그널을 공유(task_structure의 signal 필드)
- 특정 태스크에만 전달 : 공유하지 않는 시그널 pending 필드에 저장
* 시그널을 보내는 과정
① 해당 태스크의 task_structure 구조체를 찾기
② 보내려는 시그널 번호를 통해 siginfo 자료구조를 초기화
③ 시그널의 성격에 따라 task_structure의 signal, pending 필드를 선택하여 세팅
④ blocked 필드를 검사해서 받지 않도록 설정된 시그널인지 검색하여 시그널 송신
'나름컴공이라공 > Linux Kernel' 카테고리의 다른 글
Linux Kernal Internal > Ch5 파일시스템과 가상 파일시스템(3) (0) | 2019.07.19 |
---|---|
Linux Kernal Internal > Ch5 파일시스템과 가상 파일시스템(2) (0) | 2019.07.19 |
Linux Kernal Internal > Ch5 파일시스템과 가상 파일시스템(1) (0) | 2019.07.19 |
Linux Kernal Internal > Ch3 태스크 관리(2) (0) | 2019.07.19 |
Linux Kernal Internal > Ch3 태스크 관리(1) (0) | 2019.07.19 |