想著博客中還沒有翻譯過一篇文章,雖然英文水平有限,但是借助google翻譯慢慢地翻譯出一篇文章也是不錯的選擇。那就來學習下hrtimer的文檔吧。
hrtimers - 高精度內核timers子系統
----------------------------------------------------
這個補丁是介紹一個新的高精度內核timers子系統。
可能有人會問:我們已經有了一個timer子系統(kernel/timers.c),為什麼我們需要兩個timer子系統呢?在長期的來回試圖將高分辨率和高精度的功能集成到現有的timer框架,並在實踐中對高精度timers的實現經過各種測試後,我們最終得出了結論是timer的時間輪代碼基本上說不適合這樣的做法的。我們最初不相信這個(必須有一個解決方案),並發費了相當大的努力試圖整合到timer時間輪裡,但是我們失敗了。事後看來,這種整合很難/不可能是有很多原因的:
1、強制將低分辨率和高分辨率的timers以同樣的方式處理導致了很多妥協和很多#ifdef的宏。timers.c代碼是非常嚴格地關於jiffies和采取32位數的,並且已經被磨練和優化到相對狹窄的用例很多年了,因此即使是很小的擴展,也很容易毀掉時間輪的概念,從而導致更加糟糕的妥協。timer時間輪代碼是非常好的,緊湊的代碼,而且在目前的使用情況下沒有出現任何問題,但是它根本就不適合再擴展到高分辨率tmers了。
2、級聯的不可預知的O(n)的開銷會導致需要更復雜的處理高精度計時器的延遲,從而又降低了魯棒性。這樣的設計還是會引起相當大的時間不准確。級聯是timer時間輪概念的基本屬性,它不能被設計出在不可接受的方式中帶來不必然的降低timer.c部分代碼。
3、目前posix的timer子系統上timer時間輪的實現已經推出了相當復雜的處理CLOCK_REALTIME timers的settimeofday或者ntp time-我們的經驗,進一步的例子:timer時間輪數據結構對於高精度timers過於嚴格了。
4、timer時間輪代碼是可被確定的最優化的“timeout”用例。這樣的超時通常設置為覆蓋各種I/O路徑的錯誤,如網絡和塊的I/O。絕大多數的timers永不過期,很少級聯,因為預期正確的事件都及時到來,所以在需要處理它們之前就可以在timer時間輪裡面刪除了。因而這些超時的用戶可以接受timer時間輪的粒度和精度的權衡,並在很大程度上期待timer子系統的開銷接近於0。對它們來說准確不是核心目的-事實上大部分使用的超時值都是熱點。對它們來說,至多是一個必要以保證超時的完成,因此,這應該是最便宜和不顯眼的了。
精密timer的主要用戶是用戶空間的程序,它們使用nanosleep,posix的timers和itimer的接口。此外,在內核中,用戶喜歡驅動程序和子系統也用timer的事件(例如多媒體),可以從一個單獨的益高精度timer子系統中受益。
雖然該子系統目前還不提供高精度的時鐘源,但是該高精度子系統可以很容易地擴展高精度時鐘的功能,並且補丁已經存在並迅速成熟。為實時和多媒體應用的需求日益增加以及用於精確的計時器的其他潛在用戶提供了另一個理由分開超時和精准計時器的子系統。
另一個潛在的好處是,這樣的分離允許甚至更特殊用戶在現有計時器輪低分辨率和低精度的用例的優化-一旦精確敏感API從計時器輪分離,並且被遷移過來hrtimers。例如,我們可以減少在超時子系統的頻率從250HZ到100HZ(或者更小)。
hrtimer子系統的實現細節
----------------------------------------------------
基本的設計考慮是:
-簡單
-數據結構不綁定jiffies或者任何其他粒度。一切內核邏輯工作在64位納秒分辨率-不做任何妥協
-簡化現有的,時間相關的內核代碼
另一個基本的要求是直接入隊列然後排列激活timers。看完一些可能的解決方案,比如基數樹和哈希,我們選擇了紅黑樹作為基本的數據結構。紅黑樹可以作為內核庫,並且被用在了眾多像內存管理和文件系統等的性能要求很嚴格的領域。這裡紅黑樹僅用於時間排列順序,一個單獨的列表用於給出後可以讓代碼快速訪問排列定時器,而無需遍歷紅黑樹。
(這單獨的列表對之後我們要介紹的高精度的時鐘非常有用,此外我們需要分離申請中的和過期的隊列,同時保持時間順序完好)
timer排序的入隊列不是純碎用於高精度時鐘而言,雖然它也簡化了基於低分辨率CLOCK_REALTIME定時器的絕對的處理。現有的實現需要保持所有額外的列表絕對的CLOCK_REALTIME定時器以及復雜的鎖。萬一settimeofday和NTP,甚至所有的定時器不得不出隊列,timer變化的代碼不得不解決這些一個接著一個的問題,並且所有這些都必須再次入隊列。timer排序的入隊和到期時間,在絕對時間的單位存儲將產出posix定時器實現的一切復雜的和縮放不好的代碼-時鐘可以簡單地無需觸摸紅黑樹而設置。這也通常情況下使得處理posix定時器變得更加簡單。
鎖定和hrtiemers的每個CPu的行為大部分是取自現有的定時器輪的代碼,因為它十分成熟,非常適合。由於不同的數據結構,代碼共享還不能成功。此外,hrtimer函數現在也越來月清晰明了了-比如hrtimer_try_to_cancel()和hrtimer_cancel()[這大致相當於del_timer()和del_timer_sync()]-所以沒有將它們直接的1:1映射,因而沒有真正潛力來實現代碼的共享。
基本數據類型:每時刻time的值,絕對或者相對的,是在一個特殊的納秒級分辨率的類型:ktime_t。內核內部是通過宏和內聯函數來實現表示ktime_t的值和操作的,並且可以在混合聯合類型和64位納秒之間切換。混合聯合類型優化了在32位的CPU的一次轉換。這個構建時可選擇ktime_t存儲格式,實現避免在32位CPU上的64位乘法和除法對性能的影響。這樣的操作是經常需要由內核和用戶空間的接口和內部時刻格式提供的存儲格式之間進行轉換。(見/include/linux/ktime.h獲取更多詳細信息)。
hrtimers-四捨五入的計時器值
----------------------------------------------------
該hrtimer代碼將以較低分辨率的時鐘圍繞計時器事件,因為它必須如此,否則它不會做任何人工捨入的。
一個問題是什麼分辨率值應該通過返回給用戶所述clock_getres()接口。這將返回一個給定時鐘任何實際分辨率-無論是低分辨率,高分辨率,或者人工低分辨率。
hrtimers-測試和驗證
----------------------------------------------------
我們用在hrtimers頂部的高分辨率時鐘子系統驗證,在實踐中hrtimer實施細則,我們跑了posix計時器測試,以確保符合規范。我們也在低分辨率的時鐘下試驗。
該hrtimer補丁轉換了下面的內核函數使用hrtimers:
- nanosleep
- itimers
- posix-timers
對於nano sleep喝posix定時器的轉變啟動了統一的nanosleeo和clock_nanosleep
該代碼已經成功在以下平台編譯成功:
i386, x86_64, ARM, PPC, PPC64, IA64
hrtimers也集成到-rt樹,連同一個hrtimers型高分辨率時鐘的實現,所以hrtimers代碼也得到了海量的測試並在實踐中使用。