Download presentation
Presentation is loading. Please wait.
1
리눅스 커널의 이해 중에서 5장. 타이밍 측정 김도형 네트워크 실험실
2
목차 Part I : 하드웨어 시계 Part II : 타이머 인터럽트 관리 Part III : PIT의 인터럽트 서비스 루틴
Part IV : TIMER_BH 하반부 함수 Part IV : 타이밍 측정과 관련한 시스템 콜
3
Part I : 하드웨어 시계
4
하드웨어 시계 실시간 시계 Real Time Clock(RTC) CPU및 다른 칩과 무관하게 동작
외부 전원(배터리, 축전지)를 통해 전원 공급 PC전원이 꺼진 후에도 계속 작동 2Hz~8.192Hz 사이 주파수로 IRQ8에 정기적으로 인터럽트 특정 값이 도달하면 IRQ8에 인터럽트 발생 – 알람시계로 사용 리눅스에서는 날짜와 시간을 알아내는 용도로 사용 /dev/rtc 장치파일을 통해 프로세스가 RTC를 프로그래밍 0x70, 0x71입출력 포트를 통해 RTC 접근 시스템 관리자는 /sbin/clock 시스템 프로그램을 통해 시각을 설정
5
하드웨어 시계 타임스탬프 카운터 80x86기반 마이크로 프로세서는 외부 발진기에서 클록(clock)시그널을 받는 CLK입력 핀이 있음. TSC(Time Stamp Counter)레지스터(64bit) Pentium이후 80x86프로세스에 있음 rdtsc(Read Time Stamp Counter) - 어셈블러 명령으로 읽을 수 있음 각 클록 시그널을 받을 때 마다 증가 Ex) 400MHz로 클록이 동작하면 TSC값은 2.5ns마다 증가 TSC를 이용하여 리눅스에서는 정확한 시간 측정 시스템을 초기화 할때 클록 시그널의 주파수를 알아내야 함 커널 컴파일 시점에서 선언하지 않으므로 리눅스에서 커널 이미지는 클록이 어떤 주파수 대역으로 움직이는 CPU에서도 동작할 수 있음 실제 클록을 알아내는 작업은 시스템을 부팅할 때 calibrate_tsc()함수 호출 하여 처리
6
하드웨어 시계 타임스탬프 카운터 Calibrate_tsc() 함수는 [ 232/f], f = CPU 주파수 ( MHz)
을 반환한다. f : 긴 시간간격( ms) 동안 발생한 시그널 수 프로그래밍 가능한 간격 타이머 채널중 하나를 설정 만듦 Calbrate_tsc()는 시스템 초기화 때만 호출하므로 긴 시간동안 실행가능
7
하드웨어 시계 프로그래밍 가능한 구간 타이머 PIT(Programmable Interval Timer): 타이밍 측정 장치
타이머 인터럽트(Timer Interrupt)발생 커널 시간간격이 하나 이상 지났다는 사실 알려줌 PIT가 커널이 지정한 고정된 주파수에 따라 계속 인터럽트를 발생 80x86기반 pc는 여려 개의 PIT를 갖고 있음 8254cmos 칩 사용, 0x40~0x43 IO포트 사용 틱(tick) 리눅스에서 첫번째 PIT를 100Hz 간격으로 IRQ0에 타이머 인터럽트가 발생하도록 프로그래밍 틱(tick)의 길이는 마이크로 초 단위로 tick변수에 저장 시스템과 관련된 모든 동작 시간 설정
8
하드웨어 시계 프로그래밍 가능한 구간 타이머 Hz는 초당 타이머 인터럽트 수 CLOCK_TICK_RATE는 1193180
타이머 인터럽트 주파수를 나타냄 CLOCK_TICK_RATE는 8254칩 내부 발진기 주파수 LATCH는 CLOCK_TICK_RATE와 Hz사이 비율 PIT를 프로그래밍할때 유용
9
하드웨어 시계 프로그래밍 가능한 구간 타이머 init_IRQ() : 첫째 PIT를 초기화
outb_p (0x34, 0x43); // PIT 새로운 주파수 인터럽트 발생 outb_p (LATCH & 0xff , 0x40);//장치에 새로운 인터럽트 주파수 지정 outb (LATCH >> 8, 0x40); //16비트 LATCH상수를 장치의 //8비트 0x40 입출력 포트에 연속 //적으로 2바이트를 보냄 (100Hz) //타이머 인터럽트 발생
10
Part II : 타이머 인터럽트 핸들러
11
타이머 인터럽트 핸들러 각 타이머 인터럽트는… 시스템 시작부터 경과한 시간 갱신 날짜와 시각을 갱신
긴급하다고 고려하여 타이머 인터럽트 핸들러 자체에서 처리 날짜와 시각을 갱신 현재 프로세스가 CPU에서 실행중인지 검사하고, 프로세스 할당 시간(quantum)이 넘었다면 프로세스를 선점 자원 사용 통계를 갱신한다. 각 소프트웨어 타이머와 연관된 시간 간격이 지났는지 검사하여,지난 경우 해당 함수를 호출한다. TIMER_BH, TQUEUE_BH 하반부에서 호출하는 함수에서 처리
12
타이머 인터럽트 핸들러 커널의 기본적인 시간관리 현재 시간을 최신으로 유지 현재 초에서 경과한 마이크로초 수 계산
CPU에 타임스탬프 카운터(TSC)의 유무에 따라 이용 TSC가 있는 경우가 더 정확 두 가지 조건(TSC 유무)을 수용하기 위해 두개 변수를 사용하는 함수 저장 TSC가 있으면 이를 사용하는 함수를 가르키도록 변수 지정 현재시간 계산후 에 변수에저장 do_get_fast_time 변수 do_gettimeofday() – TSC유, do_normal_gettime() – TSC무 do_gettimeoffset 변수 do_fast_gettimeoffset() – TSC유, do_slow_gettimeoffset – TSC무 커널을 시작할 때 호출하는 time_init() 한수는 위 두 변수(do_get_fast_time , do_gettimeoffset)이 올바른 함수를 가르키도록 설정 IRQ0에 해당하는 인터럽트 게이트(interrupt gate) 설정
13
Part III : PIT 인터럽트 서비스 루틴
14
PIT의 인터럽트 서비스 루틴 IRQ0 인터럽트 게이트 초기화후
irqaction 디스크립터의 handler 필드 : timer_interrupt() 함수의 주소를 포함 status 필드 : SA_INTERRUPT플래그 설정 인터럽트를 금지한 상태에서 함수 실행 CPU에 TSC레지스터가 있으면 실행 Rdtsc 어셈블러명령을 실행해여 TSC레지스터 값을 last_tsc_low 변수에 저장 8254칩 내부 발진기 상태를 읽어 타이머 인터럽트가 발생부터 인터럽트 서비스 루틴을 실행 까지 지연시간 계산 지연된 시간을 마이크로초(ms) 단위로 delay_at_last_interrupt 변수에 저장
15
PIT의 인터럽트 서비스 루틴 do_time_interrupt()함수 Do_timer()함수 do_timer() 함수 호출
adjtimex()시스템 콜 호출한 경우 660초(11분) 마다 한번씩 set_rtc_mmss()함수 호출하여 실시간 시계를 수정 - 네트워크에 존재하는 시스템 시계를 똑같이 맞출 수 있게 함 Do_timer()함수 인터럽트 금지한 상태에서 실행 : 가능한 빨리 실행 시스템 시작시간 부터 흘러간 시간을 나타내는 기본 값 하나만 갱신 나머지 작업은 두 하반부에 위임 타이밍 측정(uptime)과 관련한 세가지 주요 변수를 참조 함수를 실행하기 전 잃어버린 틱 을 저장하는데 필요 : xtime에 대한 변수의 상대값 Jiffies : 시스템이 시작할 때부터 지나간 틱 수, 타이머 인터럽트가 발생시 증가 기본적인 가동시간(uptime) : 절대값(계속 증가) lost_ticks xtime을 마지막으로 갱신 후 발생한 틱 lost_ticks_system xtime을 마지막으로 갱신 후 프로세스가 커널 모드에서 동작 동안 발생한 틱 수 모드 측정 – user_mode매크로 : 스택의 cs레지스터의 CPL필드를 검사 모드 측정
16
tq_timer 작업큐가 비어있지 않을때만 실행
PIT의 인터럽트 서비스 루틴 do_timer() 함수 void do_timer(struct pt_regs * regs) { jiffies ++; lost_ticks++; mark_bh (TIMER_BH); if (!user_moe(regs)) lost_ticks_system++; if (tq_timer) mark_bh(TQUEUE_BH); } tq_timer 작업큐가 비어있지 않을때만 실행
17
Part IV : TIMER_BH 하반부 함수
18
TIMER_BH 하반부 함수 날짜와 시간 갱신 timer_bh() 함수 xtime에서 현재 날짜, 시각을 알아냄
Update_times(), run_old_times(), run_timer_list()호출 날짜와 시간 갱신 xtime에서 현재 날짜, 시각을 알아냄 struct timeval 자료형 변수 xtime.tv_sec : 1970년 1월 1일 자정부터 현재까지 경과한 초단위 xtime.tv_usec : 마지막 초에서 경과한 시각을 마이크로초 단위로 저장
19
Update_wall_time_one_tick()
TIMER_BH 하반부 함수 xtime초기화 time_init() 호출 시스템 초기화 get_cmos_time() 호출 RTC 시간 읽음 초기화 xtime 갱신 TIMER_BH xtime.tv_usec 갱신 Update_times() xtime.tv_usec > Update_wall_times() lost_tick 횟수만큼 호출 Update_wall_time_one_tick() xtime.tv_usec
20
TIMER_BH 하반부 함수 자원 사용 통계 갱신 lost_ticks, lost_ticks_system 사용
시스템 시계를 갱신후, update_times() 인터럽트 후 Lost_ticks를 tick변수에 저장후 0으로 만듦 Lost_ticks_system을 system에 저장후 0으로 만듦 Calc_load(ticks)호출 TASK_RUNNING, TASK_UNINTERRUPTIBLE상태 프로세스 개수를 세서 CPU사용 통계 갱신 Update_process_times(ticks, system)호출 Kernel_start자료형의 kstat변수에 저장된 몇가지 커널 통계 갱신 Update_one_process()호출, times()시스템 콜을 통해 알 수 있는 통계 필드 갱신 사용자 모드, 커널모드 사용시간 구별
21
TIMER_BH 하반부 함수 자원 사용 통계 갱신 Update_process_times()함수
Current 프로세스 디스크립터에 있는 per_cpu_utime, per_cpu,stime필드 갱신 Per_cpu_utime : 사용자 모드일때 발생한 틱수 Per_cpu_stime : 시스템 모드일때 발생한 틱수 Do_processor_times() 호출하여 CPU시간 제한에 걸리는지 검사 제한에 걸리면 : current에 SIGXCPU, SIGKILL 시그널 보냄 Do_it_vert(), do_it_prof() 호출
22
TIMER_BH 하반부 함수 CPU시분할 타이머 인터럽트는 실행 할 수 있는 프로세스(TASK_RUNNING상태)가 CPU시간을 공유하는데 필수 각 프로세스는 quantum동안만 사용 Quantum내에서 프로세스가 종료되지 않는다면 Schedule()함수를 호출하여 새 프로세스 선택 프로세스 디스크립터 중 counter 필드 프로세스에 CPU시간 중 몇 틱이 남는지 나타냄 퀀텀은 항상 틱의 배수(10ms의 배수) PID0의 프로세스는 다른 프로세스가 없을 때 실행되므로, 시분할 되면 안됨,
23
TIMER_BH 하반부 함수 타이머 역할 타이머 커널, 프로세스에서 사용 특정 시간에 함수를 실행하도록 할때 사용
주어진 시간 간격이 지났을 때, 어떤 시점에서 함수를 호출하게 하는 소프트웨어적 기법 타임아웃 : 타이머에서 지정된 시간 간격이 지나갈 때 커널, 프로세스에서 사용 장치드라이버 : 예외적인 상황을 감지 할 때 활용 특정 시간에 함수를 실행하도록 할때 사용 현재 jiffies값에 원하는 틱 수를 더해 필드를 계산 커널은 타이머의 만료시간을 현재jiffies와 비교, 저장값이 같거나 클 때 타이머 중지 Time_after, time_before, time_after_eq, time_before_eq매크로 이용 Jiffies값이 오버플로우 주의
24
TIMER_BH 하반부 함수 타이머 역할 종류 주의점 정적 타이머 : 커널 모드 동적 타이머 : 커널 모드
간격 타이머 : 사용자 모드 주의점 커널은 타이머 함수를 만료 시간에 맞춰 정확시 실행 보장 못함 몇백 밀리초정도 지연후 실행을 보장하기때문에 실시간 어플리케이션에는 부적당
25
TIMER_BH 하반부 함수 정적 타이머 초기 리눅스 버전에 정의된 타이머 : 32개 정적으로 할당된 커널 자료 구조에 의지적
Old timer라고 부름 정적타이머 타임아웃 효과 BACKGR_TIMER BEEP_TIMER BLANK_TIMER COMTROL_TIMER COPRO_TIMER DIGI_TIMER FLOPPY_TIMER GDTH_TIMER GSCD_TIMER HD_TIMER MCD_TIMER QIC02_TAPE_TIMER RS_TIMER SWAP_TIMER 후위 입출력 동작요구 확성기 음색 화면끄기 컴트롤(comtrol) 직렬 카드 I80387 보조프로세서 디지보드(digiboard)카드 플로피디스크 GDTH SCSI 드라이버 LG(Goldstar) CD-ROM 하드디스크(옛날 IDE 드라이버) 미쯔미(mitsumi)cd-rom QIC-02 테이프 드라이버 RS-232직렬포트 Kswapd 커널 스레드 활성화
26
TIMER_BH 하반부 함수 동적 타이머 동적으로 생성, 소멸 가능 제한 없이 사용할 수 있음
Struct timer_list { // 새로운 객채를 만듦 struct timer_list *next; struct timer_list *prev; unsigned long expires; // 정적 타이머의 expires와 같음 unsigned long data; // 여러 장치 드라이버의 타임아웃을 처리할 수 있는 일반적인 함수 하나 정의 void (*function) (unsigned long); // 타이머가 만료될때까지 함수주소 포함 };
27
TIMER_BH 하반부 함수 동적타이머 생성/활성 Struct timer_list (t 로 가정)객체 생성
코드에 정적 전역변수지정 함수내 지역 변수 지정 커널 모드 스택에 객체를 저장 동적으로 할당된 디스크립터에 객체가 있다. Init_timer를 호출하여 객체 초기화 Next, prev필드를 null 동적 타이머가 리스트에 없으면, 해당 값을 expires필드에 지정 이미 리스트에 있으면, 해당값을 mod_timer()함수 호출 expires 갱신 타이머가 완료될 때, function필드 호출할 함수 주소로 설정 동적 타이머가 아직 리스트에 있으면, add_timer(&t)함수 호출하여 t 항목을 바른 리스트에 삽입
28
동적타이머 리스트 tvecs tv1 tv2 tv3 tv4 tv5 (<214-1) (<220-1)
(<226-1) (<232-1) (0-255) 동적타이머 리스트 [그림 5-1] 동적 타이머와 연관된 리스트의 그룹(p 236.)
29
Part V : 타이밍 측정과 관련한 시스템 콜
30
타이밍 측정과 관련한 시스템 콜 Time() ftime() gettimeofday()
1970년 1월 1일 자정부터 지나간 시간의 초단위 ftime() 1970년 1월 1일 자정부터 지나간 초 단위 시간 마지막 초부터 흘러간 밀리초 시간, 시간대(timezone) 일광 절약시간(daylightsaving)의 timeb자료로 변환 gettimeofday() Ftime()과 같은정보를 timeval, timezone 자료구조에 담아 반환
31
타이밍 측정과 관련한 시스템 콜 adjtimex() 여러 유닉스 변종에 존재
프로그램에서 호환성을 고려하여 사용을 하면 안된다. Timex 구조체에 대한 포인터를 매개 변수로 받아 timex필드에 있는 값으로 커널매개변수 넣어 반환 Update_wall_time_one_tick() 함수에서 각 틱마다 xtime.tv_usec에 더해 마이크로초 를 미세하게 조정
32
타이밍 측정과 관련한 시스템 콜 setitmer() alarm() 시스템 콜을 이용하여 간격 타이머를 활성화
ITEMER_REAL : 실제 흘러간 시간 ITIMER_VIRTUAL : 프로세스가 사용자 모드에서 보낸 시간 ITIMER_PROF : 사용자 모드, 커널모드에서 모두 보낸 시간 alarm() 지정 시간간격이 지나면 호출한 프로세스에 SIGALRM시그널 보냄 ITMER_REAL 정책을 사용하여 setitimer() 호출과 비슷 Real_timer동적 타임 사용 *alarm()과 ITIMER_REAL을 지정한 setitimer() 는 동시 사용 못함
33
Part VI : Q & A
Similar presentations