采用混合時鐘模式提高Linux時鐘精度的方法
數(shù)控技術(shù)(CNC)已經(jīng)成為現(xiàn)代制造業(yè)的核心技術(shù)之一,開放式數(shù)控系統(tǒng)相對于傳統(tǒng)數(shù)控系統(tǒng)在功能、靈活性、成本等方面的優(yōu)勢,使得開放式數(shù)控成為數(shù)控系統(tǒng)未來發(fā)展的主要趨勢。目前,開放式數(shù)控系統(tǒng)主要有三種結(jié)構(gòu),即專用CNC+PC、通用PC+運動控制器和軟數(shù)控系統(tǒng)。其中軟數(shù)控系統(tǒng)采用多任務(wù)實時操作系統(tǒng),將運動控制部分與管理部分集成到一個硬件平臺上,滿足數(shù)控系統(tǒng)在功能方面和非功能方面(主要表現(xiàn)在實時性)的要求[1]。開放式數(shù)控系統(tǒng)的理想軟件平臺是實時多任務(wù)操作系統(tǒng),目前,商業(yè)實時多任務(wù)操作系統(tǒng)有很多,比較著名的有VxWORKS、iRMX、QNX等,但這些操作系統(tǒng)產(chǎn)品大多成本高、開放性差。Linux是一種發(fā)展十分迅速的類UNIX系統(tǒng),已被廣泛地運用到服務(wù)器、桌面系統(tǒng)以及嵌入式應(yīng)用領(lǐng)域。Linux由于其開放源代碼的特點,可以在此基礎(chǔ)上開發(fā)具有自主知識產(chǎn)權(quán)的數(shù)控系統(tǒng)。但是Linux最初的設(shè)計目標(biāo)是一個分時操作系統(tǒng),追求系統(tǒng)效率和公平性,在對實時性要求高的領(lǐng)域應(yīng)用受到限制。雖然2.6內(nèi)核的Linux時鐘粒度提高到了1 ms,但仍遠(yuǎn)不能滿足數(shù)控系統(tǒng)對定時精度的要求。
近年來的研究以細(xì)化時鐘粒度來提高Linux的實時應(yīng)用能力提出了一些方案和設(shè)想,主要有KURT-Linux系統(tǒng)、RT-Linux系統(tǒng)。本文對KURT_Linux、RT-Linux提高時鐘精度的方法進行分析,考慮在強周期性應(yīng)用或者在某個時段內(nèi)有大量高精度定時器將超時的情況下,采用一種動態(tài)的多模式時鐘機制來提高Linux的時鐘精度,并通過分析測試證明該方案確實可行。
1 Linux時鐘機制與改進
1.1 Linux時鐘機制
時鐘和定時器對Linux系統(tǒng)來說是至關(guān)重要的。首先,內(nèi)核要管理系統(tǒng)的運行時間以及墻上時間;其次,內(nèi)核中大量的任務(wù)是基于時間驅(qū)動,其中有些任務(wù)是周期執(zhí)行,如對調(diào)度程序中運行隊列進行平衡調(diào)整或?qū)ζ聊贿M行刷新,而有些任務(wù)需要推后執(zhí)行的I/O操作則需要等待一個相對時間后才運行。
系統(tǒng)時鐘是定時器硬件和系統(tǒng)軟件的結(jié)合,在X86體系結(jié)構(gòu)中,使用最普遍的定時器硬件是Intel8254可編程定時器芯片(PIT),它產(chǎn)生的中斷就是時鐘中斷(tick)。時鐘中斷是特定的周期性中斷,對應(yīng)中斷服務(wù)程序,完成更新系統(tǒng)時間以及任務(wù)的管理、調(diào)度等工作;系統(tǒng)在每次時鐘中斷處理中更新jiffies,維護系統(tǒng)定時器鏈表timer_list,對超時的定時器進行處理。
與系統(tǒng)定時器相對的是動態(tài)定時器,是用來調(diào)度事件在將來某個時刻發(fā)生的機制。它依賴于系統(tǒng)時鐘中斷,在時鐘中斷服務(wù)程序的下半部,系統(tǒng)檢查是否有超時的動態(tài)定時器并進行處理。linux2.6內(nèi)核的系統(tǒng)時鐘頻率為1 000 Hz,即時鐘中斷的觸發(fā)周期為1 ms,中斷服務(wù)程序最快每1 ms執(zhí)行一次。動態(tài)定時器隨時都可能超時,但只有在中斷服務(wù)處理程序執(zhí)行時才會檢查、執(zhí)行超時的動態(tài)定時器,所以動態(tài)定時器的平均誤差大約為半個系統(tǒng)時鐘周期。
CNC數(shù)控系統(tǒng)的工作過程通常是首先內(nèi)建一個定時器(由操作系統(tǒng)完成),然后周期性地執(zhí)行控制程序,周期通常為幾十微秒到十幾毫秒。在每個周期內(nèi)要完成狀態(tài)監(jiān)測、譯碼、刀具補償計算、插補計算、PLC管理、位置控制等工作??梢?,在加工工件過程中,CNC要求的實時性非常高,必須在很短、很精確的周期內(nèi)完成一系列的計算和輸入輸出,否則加工精度無法得到保障。標(biāo)準(zhǔn)2.6內(nèi)核Linux定時器精度遠(yuǎn)遠(yuǎn)達不到數(shù)控系統(tǒng)周期實時任務(wù)要求的微秒級定時精度。
1.2 提高時鐘精度的辦法
近年來人們對Linux進行實時化改造提出了一些方案和設(shè)想,主要有KURT-Linux、RT-Linux等[2]。下面分別進行介紹。
KURT_Linux[3]由kansas大學(xué)開發(fā),通過對Linux內(nèi)核內(nèi)部進行改造來滿足實時應(yīng)用需求。在時鐘精度方面,KURT-Linux將Linux的時鐘中斷固定模式改為單次觸發(fā)模式(one-shot mode),即每次給時鐘芯片設(shè)置一個超時時間,然后等到該超時事件發(fā)生,在時鐘中斷處理過程中再次根據(jù)需要設(shè)置一個超時時間。通過這種變長時鐘模式,將Linux時鐘精度提高到μs級。既保證了特定實時任務(wù)的精度要求,又避免了不必要的調(diào)度負(fù)擔(dān)。
RT-Linux是新墨西哥工學(xué)院研制的一個基于Linux的硬實時系統(tǒng)。它采用雙內(nèi)核方法,在原有Linux基礎(chǔ)上設(shè)計一個專門處理實時進程的內(nèi)核,然后把整個Linux作為實時內(nèi)核上運行的一個低優(yōu)先級進程。在時鐘精度方面類似KURT_Linux,將系統(tǒng)實時時鐘設(shè)置為單次觸發(fā)狀態(tài),然后利用TSC提供高達CPU時鐘頻率的定時精度。
Monta Vista Linux是由James Ready領(lǐng)導(dǎo)開發(fā)的嵌入式Linux,通過對Linux內(nèi)核進行內(nèi)部改造,直接修改原有Linux內(nèi)核的數(shù)據(jù)結(jié)構(gòu)等來滿足實時需要。在高精度時鐘方面,拋開傳統(tǒng)的周期中斷CPU的方法,使定時器在需要的任何一個μs產(chǎn)生中斷,但不在每個μs產(chǎn)生中斷,將系統(tǒng)的定時精度提高到μs級。
Linux-SRT是劍橋大學(xué)David Ingram的博士論文項目,它簡單地修改了Linux中Hz的定義,將Linux時鐘頻率由100 Hz提高到1 024 Hz。這種方式實現(xiàn)起來很簡單,但是由此帶來頻繁的定時中斷使得系統(tǒng)開銷很大。借鑒KURT-Linux的one-shot思想來提高時鐘精度,并利用高級可編程中斷控制器(APIC)[4]或通過附加的硬件資源實現(xiàn)一個與系統(tǒng)時鐘并行的高精度實時時鐘,在系統(tǒng)中維護一個高精度實時時鐘和一個低精度系統(tǒng)時鐘[5-7],是一種普遍采用的提高時鐘精度的方法。但是在缺乏附加硬件支持或APIC使用受限的應(yīng)用環(huán)境下,只能利用PIT芯片作為高精度時鐘源,在每次中斷處理時要重新計算下一次中斷時間和對PIT進行編程。由于PC的兼容性,PIT芯片位于低速的ISA總線上,頻繁設(shè)置定時器硬件也需要耗費大量的時鐘周期。因此one-shot模式時鐘中斷處理時間可能達到標(biāo)準(zhǔn)Linux時鐘中斷處理時間的7~15倍[8-9]。在強周期應(yīng)用或有大量定時器集中在某個時段內(nèi)時超時,需要采取一種不同于one-shot的時鐘模式。
如果系統(tǒng)中沒有任何實時定時器,則系統(tǒng)每隔1 ms會有一次周期性jiffies時鐘中斷,采用one-shot模式使得系統(tǒng)性能下降大約1.5%。如果系統(tǒng)中沒有任何實時定時器,則需要重新將時鐘設(shè)置為RTL CLOCK MODE PERIODIC工作模式,并且時鐘周期和標(biāo)準(zhǔn)Linux下時鐘周期一致,使Linux能在系統(tǒng)中不存在實時任務(wù)的情況下高效地工作。
2 動態(tài)高精度時鐘設(shè)計和實現(xiàn)
動態(tài)高精度時鐘設(shè)計方案借鑒了KURT-Linux思想,但與其不同的是提供一個與標(biāo)準(zhǔn)Linux核心時鐘并行的具有精密刻度的實時時鐘,并與原核心時鐘區(qū)別開。采用X86體系CPU提供的TSC作為高精度的時間標(biāo)度,權(quán)衡一定時間段(如一個jiffies)內(nèi)高精度定時器的數(shù)量,設(shè)置Linux時鐘中斷模式為標(biāo)準(zhǔn)模式、one-shot模式或高頻周期時鐘模式。實現(xiàn)了μs級定時精度的同時,降低了頻繁計算和設(shè)置時鐘芯片的時間代價。
下面給出關(guān)鍵的全局變量:
(1)time_mode:表示當(dāng)前時鐘工作模式。其中-1代表高頻周期時鐘模式,該模式下,根據(jù)需要達到的定時精度,設(shè)置時鐘芯片以較高的頻率產(chǎn)生周期性中斷;0代表標(biāo)準(zhǔn)模式,時鐘芯片以標(biāo)準(zhǔn)Linux默認(rèn)的頻率產(chǎn)生周期中斷;1代表one-shot模式,時鐘芯片被設(shè)置為單次觸發(fā)狀態(tài),即每次給時鐘芯片設(shè)置一個超時時間,超時事件發(fā)生時,在時鐘中斷處理程序中根據(jù)需要再次給時鐘芯片設(shè)置一個超時時間。系統(tǒng)啟動時設(shè)置為默認(rèn)值0。
(2)SCALE:時鐘精度提高比。設(shè)置高頻周期模式需要的參數(shù),用來表示所需要達到的時鐘精度相對普通Linux時鐘精度的提高倍數(shù)。
(3)Threshold:閾值。如果即將在某一時間段內(nèi)超時的實時定時器數(shù)量大于預(yù)設(shè)值,系統(tǒng)設(shè)置硬件定時器工作在高頻周期時鐘模式。
2.1 時鐘中斷處理
為了加強Linux的實時功能,同時又要保持Linux的完整性,本方案的動態(tài)多模式時鐘機制以模塊化的方式實現(xiàn)有關(guān)實時部分的功能,并利用接口函數(shù)實現(xiàn)實時模塊與Linux核心的聯(lián)系。
(1)標(biāo)準(zhǔn)模式。標(biāo)準(zhǔn)模式下的中斷處理首先查詢實時定時器隊列中是否有實時定時器在下一個系統(tǒng)時鐘中斷(jiffies+1)之前超時,即在(jiffies,jiffies+1)內(nèi)是否有實時定時器要處理,根據(jù)實時定時器數(shù)量設(shè)置時鐘芯片的工作模式,執(zhí)行do_timer_interrupt()等函數(shù)維護系統(tǒng)相關(guān)時間,標(biāo)記下半部。
(2)one_shot模式。one-shot模式下的中斷處理先判斷jiffies時鐘是否到期,如果到期:
①查詢實時定時器隊列中是否有實時定時器在下一個系統(tǒng)時鐘中斷(tick+1)之前超時,即在(jiffies,jiffies+1)內(nèi)有實時定時器要處理(其超時時間用sub_jiffies表示),然后根據(jù)實時定時器數(shù)量設(shè)置時鐘芯片工作模式。
②執(zhí)行do_timer_interrupt()函數(shù)等維護與系統(tǒng)有關(guān)的時間,并標(biāo)記下半部。
如果jiffies時鐘未到期,則查詢實時定時器鏈表,根據(jù)其最早超時實時定時器的超時時間與當(dāng)前時間的差值設(shè)置時鐘芯片產(chǎn)生下一次中斷的時間。
(3)高頻周期時鐘模式。高頻周期模式下中斷處理先判斷jiffies時鐘是否到期,如果系統(tǒng)時鐘節(jié)拍到期,執(zhí)行上述①、②模式。否則,如果有實時定時器超時,標(biāo)記中斷下半部;如果沒有實時定時器超時則直接返回。
對超時定時器的處理都留到時鐘中斷下半部(softirq)處理,超時的實時定時器優(yōu)先得到處理,以盡可能保證實時定時器的及時處理,隨后處理普通Linux的定時器,時鐘中斷處理過程如圖1所示。
2.2 定時器組織
普通Linux系統(tǒng)原有的粗粒度定時器對于內(nèi)核的穩(wěn)定和不要求高精度定時的非實時應(yīng)用仍是合適的,只是針對有高精度定時要求的實時應(yīng)用組織一個高精度定時器隊列HRT_list,隊列中的定時器按超時時間非降序排列,隊列中第一個定時器的超時時間就是隊列的最早超時時間。
原Linux內(nèi)核中的定時器是通過稱為CTW(Cascading Timer Wheel)的結(jié)構(gòu)管理和維護,并因此使得對定時器的插入、刪除等操作的時間為0(1)。本文把HRT_list隊列和CTW結(jié)合起來以降低定時器處理時間、提高效率。把需要較長時間才超時的實時定時器仍舊插入到原定時器隊列中,借助該隊列維護。在每次系統(tǒng)時鐘中斷處理的下半部處理完超時的實時定時器后,把在下一次系統(tǒng)時鐘中斷前超時的高精度定時器從原隊列移除,并插入到HRT_list隊列中。因此,HRT_list隊列中所需要維護的高精度實時定時器也是有限的,避免了維護一個大規(guī)模定時器隊列的開銷,近似實現(xiàn)了0(1)的系統(tǒng)開銷。
3 性能分析與測試
3.1 性能分析
當(dāng)系統(tǒng)中沒有高精度定時器時,PIT仍以Linux系統(tǒng)默認(rèn)的頻率觸發(fā)時鐘中斷,在每一次系統(tǒng)時鐘中斷處理過程中,只需要判斷工作模式以及下一次jiffies中斷前有否實時定時器超時,經(jīng)測試由此而帶來的處理時間不超過1us,增加系統(tǒng)負(fù)擔(dān)0.1%,不會影響系統(tǒng)的性能。當(dāng)在某個時間段內(nèi)系統(tǒng)中實時定時器不多于閾值時,系統(tǒng)時鐘工作在類似KURT-Linux的one-shot模式,同時維持普通Linux系統(tǒng)時鐘的穩(wěn)定。而由此而帶來的系統(tǒng)負(fù)擔(dān)是可以接受的[3]。
當(dāng)系統(tǒng)中存在大量實時定時器或在某個時間段內(nèi)即將超時的實時定時器數(shù)量超過一定值(閾值)時,相對于one-shot模式需要頻繁地計算下次中斷時間,并重新編程在低速的ISA總線上的PIT的時間代價是可取的,證明如下:
用Thw表示中斷的硬件處理時間,Tisr表示中斷程序上半部執(zhí)行時間,n代表某個時段內(nèi)(一個jiffies內(nèi))超時的定時器數(shù)量。得到兩種模式下總的時鐘中斷處理時間關(guān)系式:
顯然,當(dāng)某個時段內(nèi)超時的定時器數(shù)量大于Threshold時,采用高頻周期模式的時間開銷就會小于one-shot模式。
3.2 模擬測試
測試環(huán)境為Pentium4 3.0 GHz CPU,1GDDR內(nèi)存的硬件平臺和2.6.15.6版本內(nèi)核的Fedora core linux操作系統(tǒng)平臺。
根據(jù)數(shù)控實時任務(wù)的要求設(shè)定了周期為0.1 ms、1 ms和100 ms的進程模擬數(shù)控實時周期任務(wù)[10],統(tǒng)計運行1 000次的數(shù)據(jù),比較改進后的高精度定時器和原linux定時器的平均定時偏差,并令閾值為30,設(shè)置周期任務(wù)數(shù)量為4、20、40,使時鐘工作在不同模式下。測試結(jié)果如表1所示。
由測試數(shù)據(jù)對比,原linux系統(tǒng)的定時平均偏差為968 μs,改進后系統(tǒng)的定時平均偏差為34 ?滋s。顯而易見,改進后的定時器定時精度大大提高,達到10 μs級,能滿足數(shù)控系統(tǒng)應(yīng)用的要求。
在原Linux內(nèi)核和改進后的高精度定時器內(nèi)核上睡眠50 μs各1 000次,測試實際睡眠時間所得結(jié)果與表1類似,50 μs的實際睡眠時間從(2.001~2.116) ms級降到(57~91) μs級。
全軟件數(shù)控系統(tǒng)以應(yīng)用軟件的形式實現(xiàn)運動控制,是開放式數(shù)控系統(tǒng)的發(fā)展方向。開源的Linux是開發(fā)具有自主知識產(chǎn)權(quán)數(shù)控系統(tǒng)的理想平臺,但是其粗糙的時鐘粒度是普通Linux直接應(yīng)用于數(shù)控系統(tǒng)的最大障礙,因此需要細(xì)化Linux的時鐘粒度提高其實時性。
簡單地提高系統(tǒng)時鐘頻率將引起頻繁的中斷處理,導(dǎo)致系統(tǒng)性能的下降。KURT-Linux采用的one-shot方式將周期性的時鐘中斷改進為單次觸發(fā)狀態(tài),實現(xiàn)了μs級的定時精度。本文分析了普通Linux時鐘機制和幾種實時Linux操作系統(tǒng)細(xì)化時鐘精度的方式,提出了一種混合多種時鐘模式的動態(tài)時鐘機制,達到了CNC要求的時鐘精度。最后的性能分析和模擬測試證實了新時鐘機制的技術(shù)性能。
評論