?
近年來的研究以細化時鐘粒度來提高Linux的實時應用能力提出了一些方案和設想,主要有KURT-Linux系統、RT-Linux系統。本文對KURT_Linux、RT-Linux提高時鐘精度的方法進行分析,考慮在強周期性應用或者在某個時段內有大量高精度定時器將超時的情況下,采用一種動態的多模式時鐘機制來提高Linux的時鐘精度,并通過分析測試證明該方案確實可行。
1 Linux時鐘機制與改進
1.1 Linux時鐘機制
時鐘和定時器對Linux系統來說是至關重要的。首先,內核要管理系統的運行時間以及墻上時間;其次,內核中大量的任務是基于時間驅動,其中有些任務是周期執行,如對調度程序中運行隊列進行平衡調整或對屏幕進行刷新,而有些任務需要推后執行的I/O操作則需要等待一個相對時間后才運行。
系統時鐘是定時器硬件和系統軟件的結合,在X86體系結構中,使用最普遍的定時器硬件是Intel8254可編程定時器芯片(PIT),它產生的中斷就是時鐘中斷(tick)。時鐘中斷是特定的周期性中斷,對應中斷服務程序,完成更新系統時間以及任務的管理、調度等工作;系統在每次時鐘中斷處理中更新jiffies,維護系統定時器鏈表timer_list,對超時的定時器進行處理。
與系統定時器相對的是動態定時器,是用來調度事件在將來某個時刻發生的機制。它依賴于系統時鐘中斷,在時鐘中斷服務程序的下半部,系統檢查是否有超時的動態定時器并進行處理。linux2.6內核的系統時鐘頻率為1 000 Hz,即時鐘中斷的觸發周期為1 ms,中斷服務程序最快每1 ms執行一次。動態定時器隨時都可能超時,但只有在中斷服務處理程序執行時才會檢查、執行超時的動態定時器,所以動態定時器的平均誤差大約為半個系統時鐘周期。
CNC數控系統的工作過程通常是首先內建一個定時器(由操作系統完成),然后周期性地執行控制程序,周期通常為幾十微秒到十幾毫秒。在每個周期內要完成狀態監測、譯碼、刀具補償計算、插補計算、PLC管理、位置控制等工作。可見,在加工工件過程中,CNC要求的實時性非常高,必須在很短、很精確的周期內完成一系列的計算和輸入輸出,否則加工精度無法得到保障。標準2.6內核Linux定時器精度遠遠達不到數控系統周期實時任務要求的微秒級定時精度。
1.2 提高時鐘精度的辦法
近年來人們對Linux進行實時化改造提出了一些方案和設想,主要有KURT-Linux、RT-Linux等[2]。下面分別進行介紹。
KURT_Linux[3]由kansas大學開發,通過對Linux內核內部進行改造來滿足實時應用需求。在時鐘精度方面,KURT-Linux將Linux的時鐘中斷固定模式改為單次觸發模式(one-shot mode),即每次給時鐘芯片設置一個超時時間,然后等到該超時事件發生,在時鐘中斷處理過程中再次根據需要設置一個超時時間。通過這種變長時鐘模式,將Linux時鐘精度提高到μs級。既保證了特定實時任務的精度要求,又避免了不必要的調度負擔。
RT-Linux是新墨西哥工學院研制的一個基于Linux的硬實時系統。它采用雙內核方法,在原有Linux基礎上設計一個專門處理實時進程的內核,然后把整個Linux作為實時內核上運行的一個低優先級進程。在時鐘精度方面類似KURT_Linux,將系統實時時鐘設置為單次觸發狀態,然后利用TSC提供高達CPU時鐘頻率的定時精度。
Monta Vista Linux是由James Ready領導開發的嵌入式Linux,通過對Linux內核進行內部改造,直接修改原有Linux內核的數據結構等來滿足實時需要。在高精度時鐘方面,拋開傳統的周期中斷CPU的方法,使定時器在需要的任何一個μs產生中斷,但不在每個μs產生中斷,將系統的定時精度提高到μs級。
Linux-SRT是劍橋大學David Ingram的博士論文項目,它簡單地修改了Linux中Hz的定義,將Linux時鐘頻率由100 Hz提高到1 024 Hz。這種方式實現起來很簡單,但是由此帶來頻繁的定時中斷使得系統開銷很大。
借鑒KURT-Linux的one-shot思想來提高時鐘精度,并利用高級可編程中斷控制器(APIC)[4]或通過附加的硬件資源實現一個與系統時鐘并行的高精度實時時鐘,在系統中維護一個高精度實時時鐘和一個低精度系統時鐘[5-7],是一種普遍采用的提高時鐘精度的方法。但是在缺乏附加硬件支持或APIC使用受限的應用環境下,只能利用PIT芯片作為高精度時鐘源,在每次中斷處理時要重新計算下一次中斷時間和對PIT進行編程。由于PC的兼容性,PIT芯片位于低速的ISA總線上,頻繁設置定時器硬件也需要耗費大量的時鐘周期。因此one-shot模式時鐘中斷處理時間可能達到標準Linux時鐘中斷處理時間的7~15倍[8-9]。在強周期應用或有大量定時器集中在某個時段內時超時,需要采取一種不同于one-shot的時鐘模式。
如果系統中沒有任何實時定時器,則系統每隔1 ms會有一次周期性jiffies時鐘中斷,采用one-shot模式使得系統性能下降大約1.5%。如果系統中沒有任何實時定時器,則需要重新將時鐘設置為RTL CLOCK MODE PERIODIC工作模式,并且時鐘周期和標準Linux下時鐘周期一致,使Linux能在系統中不存在實時任務的情況下高效地工作。
2 動態高精度時鐘設計和實現
動態高精度時鐘設計方案借鑒了KURT-Linux思想,但與其不同的是提供一個與標準Linux核心時鐘并行的具有精密刻度的實時時鐘,并與原核心時鐘區別開。采用X86體系CPU提供的TSC作為高精度的時間標度,權衡一定時間段(如一個jiffies)內高精度定時器的數量,設置Linux時鐘中斷模式為標準模式、one-shot模式或高頻周期時鐘模式。實現了μs級定時精度的同時,降低了頻繁計算和設置時鐘芯片的時間代價。
下面給出關鍵的全局變量:
(1)time_mode:表示當前時鐘工作模式。其中-1代表高頻周期時鐘模式,該模式下,根據需要達到的定時精度,設置時鐘芯片以較高的頻率產生周期性中斷;0代表標準模式,時鐘芯片以標準Linux默認的頻率產生周期中斷;1代表one-shot模式,時鐘芯片被設置為單次觸發狀態,即每次給時鐘芯片設置一個超時時間,超時事件發生時,在時鐘中斷處理程序中根據需要再次給時鐘芯片設置一個超時時間。系統啟動時設置為默認值0。
(2)SCALE:時鐘精度提高比。設置高頻周期模式需要的參數,用來表示所需要達到的時鐘精度相對普通Linux時鐘精度的提高倍數。
(3)Threshold:閾值。如果即將在某一時間段內超時的實時定時器數量大于預設值,系統設置硬件定時器工作在高頻周期時鐘模式。
2.1 時鐘中斷處理
為了加強Linux的實時功能,同時又要保持Linux的完整性,本方案的動態多模式時鐘機制以模塊化的方式實現有關實時部分的功能,并利用接口函數實現實時模塊與Linux核心的聯系。
(1)標準模式。標準模式下的中斷處理首先查詢實時定時器隊列中是否有實時定時器在下一個系統時鐘中斷(jiffies+1)之前超時,即在(jiffies,jiffies+1)內是否有實時定時器要處理,根據實時定時器數量設置時鐘芯片的工作模式,執行do_timer_interrupt()等函數維護系統相關時間,標記下半部。
(2)one_shot模式。one-shot模式下的中斷處理先判斷jiffies時鐘是否到期,如果到期:
①查詢實時定時器隊列中是否有實時定時器在下一個系統時鐘中斷(tick+1)之前超時,即在(jiffies,jiffies+1)內有實時定時器要處理(其超時時間用sub_jiffies表示),然后根據實時定時器數量設置時鐘芯片工作模式。
②執行do_timer_interrupt()函數等維護與系統有關的時間,并標記下半部。
如果jiffies時鐘未到期,則查詢實時定時器鏈表,根據其最早超時實時定時器的超時時間與當前時間的差值設置時鐘芯片產生下一次中斷的時間。
(3)高頻周期時鐘模式。高頻周期模式下中斷處理先判斷jiffies時鐘是否到期,如果系統時鐘節拍到期,執行上述①、②模式。否則,如果有實時定時器超時,標記中斷下半部;如果沒有實時定時器超時則直接返回。
對超時定時器的處理都留到時鐘中斷下半部(softirq)處理,超時的實時定時器優先得到處理,以盡可能保證實時定時器的及時處理,隨后處理普通Linux的定時器,時鐘中斷處理過程如圖1所示。

?
2.2 定時器組織
普通Linux系統原有的粗粒度定時器對于內核的穩定和不要求高精度定時的非實時應用仍是合適的,只是針對有高精度定時要求的實時應用組織一個高精度定時器隊列HRT_list,隊列中的定時器按超時時間非降序排列,隊列中第一個定時器的超時時間就是隊列的最早超時時間。
原Linux內核中的定時器是通過稱為CTW(Cascading Timer Wheel)的結構管理和維護,并因此使得對定時器的插入、刪除等操作的時間為0(1)。本文把HRT_list隊列和CTW結合起來以降低定時器處理時間、提高效率。把需要較長時間才超時的實時定時器仍舊插入到原定時器隊列中,借助該隊列維護。在每次系統時鐘中斷處理的下半部處理完超時的實時定時器后,把在下一次系統時鐘中斷前超時的高精度定時器從原隊列移除,并插入到HRT_list隊列中。因此,HRT_list隊列中所需要維護的高精度實時定時器也是有限的,避免了維護一個大規模定時器隊列的開銷,近似實現了0(1)的系統開銷。
3 性能分析與測試
3.1 性能分析
當系統中沒有高精度定時器時,PIT仍以Linux系統默認的頻率觸發時鐘中斷,在每一次系統時鐘中斷處理過程中,只需要判斷工作模式以及下一次jiffies中斷前有否實時定時器超時,經測試由此而帶來的處理時間不超過1us,增加系統負擔<0.1%,不會影響系統的性能。當在某個時間段內系統中實時定時器不多于閾值時,系統時鐘工作在類似KURT-Linux的one-shot模式,同時維持普通Linux系統時鐘的穩定。而由此而帶來的系統負擔是可以接受的[3]。
當系統中存在大量實時定時器或在某個時間段內即將超時的實時定時器數量超過一定值(閾值)時,相對于one-shot模式需要頻繁地計算下次中斷時間,并重新編程在低速的ISA總線上的PIT的時間代價是可取的,證明如下:
用Thw表示中斷的硬件處理時間,Tisr表示中斷程序上半部執行時間,n代表某個時段內(一個jiffies內)超時的定時器數量。得到兩種模式下總的時鐘中斷處理時間關系式:

?
顯然,當某個時段內超時的定時器數量大于Threshold時,采用高頻周期模式的時間開銷就會小于one-shot模式。
3.2 模擬測試
測試環境為Pentium4 3.0 GHz CPU,1GDDR內存的硬件平臺和2.6.15.6版本內核的Fedora core linux操作系統平臺。
根據數控實時任務的要求設定了周期為0.1 ms、1 ms和100 ms的進程模擬數控實時周期任務[10],統計運行1 000次的數據,比較改進后的高精度定時器和原linux定時器的平均定時偏差,并令閾值為30,設置周期任務數量為4、20、40,使時鐘工作在不同模式下。測試結果如表1所示。

?
由測試數據對比,原linux系統的定時平均偏差為968 μs,改進后系統的定時平均偏差為34 ?滋s。顯而易見,改進后的定時器定時精度大大提高,達到10 μs級,能滿足數控系統應用的要求。
在原Linux內核和改進后的高精度定時器內核上睡眠50 μs各1 000次,測試實際睡眠時間所得結果與表1類似,50 μs的實際睡眠時間從(2.001~2.116) ms級降到(57~91) μs級。
全軟件數控系統以應用軟件的形式實現運動控制,是開放式數控系統的發展方向。開源的Linux是開發具有自主知識產權數控系統的理想平臺,但是其粗糙的時鐘粒度是普通Linux直接應用于數控系統的最大障礙,因此需要細化Linux的時鐘粒度提高其實時性。
簡單地提高系統時鐘頻率將引起頻繁的中斷處理,導致系統性能的下降。KURT-Linux采用的one-shot方式將周期性的時鐘中斷改進為單次觸發狀態,實現了μs級的定時精度。本文分析了普通Linux時鐘機制和幾種實時Linux操作系統細化時鐘精度的方式,提出了一種混合多種時鐘模式的動態時鐘機制,達到了CNC要求的時鐘精度。最后的性能分析和模擬測試證實了新時鐘機制的技術性能。
評論