1. 定時器類型
經典定時器(低精度)
內核最初版本就是提供的此類定時器,實現於kernel/timer.c中,提供的典型分辨率爲4ms,從現在看來分辨率很低,此類定時器只產生週期性的信號
高精度定時器
隨着應用需求的提升,後來引入了高分辨率定時器,分辨率可以達到ns級別,這樣就可以不用只產生週期行的信號,而是設置一些需要的事件信號就可以,這樣就可以隨機發出信號,而原先的週期信號就可以通過模擬來產生
2. 源代碼
時間子系統的源代碼在目錄kernel/time下,代碼總量近2W行:
~/kernel/time$ wc -l ./*
1089 ./alarmtimer.c
763 ./clockevents.c--------------------clockevent
1019 ./clocksource.c--------------------clocksource
1830 ./hrtimer.c------------------------hrtimer
301 ./itimer.c
136 ./jiffies.c
197 ./Kconfig
14 ./Makefile
1017 ./ntp.c
13 ./ntp_internal.h
446 ./posix-clock.c
1523 ./posix-cpu-timers.c
1131 ./posix-timers.c
303 ./sched_clock.c
168 ./test_udelay.c
1005 ./tick-broadcast.c
110 ./tick-broadcast-hrtimer.c
535 ./tick-common.c
166 ./tick-internal.h
132 ./tick-oneshot.c
1183 ./tick-sched.c
84 ./tick-sched.h
764 ./time.c
109 ./timeconst.bc
127 ./timeconv.c
112 ./timecounter.c
2054 ./timekeeping.c
74 ./timekeeping_debug.c
26 ./timekeeping.h
29 ./timekeeping_internal.h
1718 ./timer.c
401 ./timer_list.c
425 ./timer_stats.c
19004 total
3. 子系統軟件框架
時間子系統的軟件框架如圖所示,從底層硬件到上層軟件的整個關係概略如下:
3.1 clockevent和clocksource(timekeeper)
一個硬件timer在內核中可以被表示成兩種形式:clockevent和clocksource
clocksource層主要是來表示硬件源,提供操作硬件設備的各種功能:讀取時間;timer設備的休眠與喚醒;使能和關閉設備等。clocksource最終會提供給timekeeper模塊使用,每註冊進一個timer設備,系統都會進行比較,讓timekeeper選取一個最合適的clocksource
clockevent層表示時鐘事件,當某個事件到時間時,就產生一箇中斷報告事件到來,clockevent被上層的tick_device層使用。
3.2 tick_device
tick_device表示能產生tick的設備,其實就是timer設備,或許是出於區分,所以用tick_device來表示。
tickdevice分兩種:oneshot和periodic。oneshot是單觸發的,在內核中又稱爲是動態的,它產生的時鐘信號都是動態信號,沒有固定的週期,不過也可以模擬固定週期,只要以一個固定時間產生時鐘信號即可。periodic是週期的,它以一個固定的時間來產生時鐘信號,而且支持這種模式的底層硬件timer一般是低精度的。
對於低精度timer,最合適的是表示成periodic tick_device,這樣就能產生週期性的事件,但是如果要支持動態(即高精度)事件,可以通過配置CONFIG_NO_HZ_COMMON開啓,這樣就能實現在低精度timer設備的支持下實現動態事件,但是動態事件的產生不能是高精度的。
對於高精度timer,最合適的就是表示成oneshot tick_device,這樣就能實現動態事件,如果要模擬週期性的事件,還需要開啓CONFIG_HIGH_RES_TIMERS,這樣就能實現。
3.3 hrtimer
時間子系統中動態事件的運轉需要hrtimer模塊支持,每一個事件用hrtimer表示,然後加入到紅黑樹中,然後在每個hrtimer的時間到期時,timer就會產生時鐘信號,然後調用此時的事件任務就可以了。
change log
date | content | linux |
---|---|---|
2017.1.2 | 初稿 | linux4.6.3 |