11. Timers and Time Management
리눅스 커널에서 '시간'이라는 개념은 중요하다.
- 많은 수의 커널 루틴들이 event-driven이 아닌 time-drive으로 동작하고 있다.
- 스케줄러 runqueue의 밸런스를 맞출 때
- 스크린을 refresh할 때
- 절대적인 시간 뿐 아니라 상대적인 시간도 관리할 필요가 있다.
- 절대적인 시간: YY-MM-DD-HH-MM-SS로 이루어지는 시간 (예시: 2017년 7월 11일 오후 1시에 스터디)
- 상대적인 시간: 기준 시간으로부터 +-로 이루어지는 시간 (예시: 지금으로부터 5초 후에 Disk I/O 발생)
- 주기적으로 발생하는 일들을 구현하는 것과 미래의 특정한 시간의 일을 스케줄링하는 것을 구현하는 것은 조금 다르다.
- system timer가 발생시키는 timer interrupt에 의해 주기적으로 event들이 발생한다. 이 때 system time이 갱신된다.
- dynamic timer는 미래의 특정한 시각에 발생하는 일을 스케줄링할 때 작동한다.
- Tick Rate: HZ, 초당 몇번의 timer interrupt를 발생시킬 지를 정하는 값
- architecture dependent
- 현재 x86 architecture는 100HZ
- Controversial issue
- HZ가 높아지면 고해상도의 타이머가 된다. tick의 최소 단위에 의해 발생하는 에러율도 낮아짐
- 다만 handler를 많이 호출하게 되면서 불필요한 오버헤드 생성 + 전력소모가 커진다
- Jiffies
- 전역변수 Jiffies 부팅 때부터 누적 틱값을 저장하고 있다.
- 32bit 체계에서는 overflow가 생길 수 있으므로 64비트를 이용하는 테크닉을 사용한다.
하드웨어 시계
- RTC(Real-Time Clock)
- 비휘발성 저장매체에 시스템의 진짜 시간을 담고 있다.
- 꺼져도 작은 배터리를 이용하여 계속 시간을 잰다.
- RTC + BIOS settings
- 시스템을 부팅할 때 커널이 RTC를 읽어서 wall time을 초기화시키고 xtime에 저장한다.
System Timer
- 주기적으로 interrupt를 발생시켜서 tick 개념을 구현
- RTC(Real-Time Clock)
Timer interrupt handler
architecture dependent routine + independent routine
architecture dependent routine
jiffies_64 와 xtime을 보호하기위해 xtime_lock을 잡는다.
주기적으로 wall time을 real time clock에 저장하고 갱신한다
architecture independent routine으로 넘어감
architecture independent routine
jiffies_64 1증가
사용자나 커널에 의해 사용되는 시간 종속적인 정보들을 업데이트
dynamic timer를 체크하여 만료된 timer routine을 실행
scheduler_tick을 실행
xtime(wall time)을 갱신
load average를 계산
The Time of Day
struct timespec xtime
sys_gettimeofday
Timers (dynamic timer)
- 일정 시간이 지나면 timer에 달려있는 handler function을 call back
- timer_list 변수를 초기화한다.
- expires에 delay tick 값을 계산해서 넣어준다.
- timer handler function을 매핑한다.
- 타이머를 실행한다. (add_timer)
- 수정할 때는 mod_timer를 이용한다.
- 타이머가 만기되기 전 타이머의 작동을 해제하고 싶을 땐 del_timer를 이용한다.
- Timer race condition
- del_timer_sync를 사용하자. 타 프로세서에서 이미 수행 중일지도 모르니까
- bottom-half context의 softirqs 파트에서 실제로 수행되도록 구현되어 있음
- update_process_times
- run_local_timers
- 일정 시간이 지나면 timer에 달려있는 handler function을 call back
Delaying Execution
- Busy looping
- time_before를 이용하여 while loop에서 busy delay
- Small delays (smaller than a clock tick)
- udelay, ndelay, mdelay와 같은 함수들이 지원해준다.
- 길게 사용하지 말 것 (overflow 조심)
- schedule_timeout을 이용하여 task를 sleep 시키자.
- Busy looping