(Linux原理與結(jié)構(gòu))第五章時(shí)鐘管理_第1頁
(Linux原理與結(jié)構(gòu))第五章時(shí)鐘管理_第2頁
(Linux原理與結(jié)構(gòu))第五章時(shí)鐘管理_第3頁
(Linux原理與結(jié)構(gòu))第五章時(shí)鐘管理_第4頁
(Linux原理與結(jié)構(gòu))第五章時(shí)鐘管理_第5頁
已閱讀5頁,還剩154頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第五章 時(shí)

理第五章時(shí)鐘管理?5.1

時(shí)鐘管理系統(tǒng)組成結(jié)構(gòu)?5.2

時(shí)鐘設(shè)備管理?5.3

計(jì)時(shí)器管理?5.4

周期性時(shí)鐘中斷?5.5

單發(fā)式時(shí)鐘中斷?5.6

變頻式周期性時(shí)鐘中斷1第五章 時(shí)

理在所有的外部中斷中,時(shí)鐘中斷是最特別、最重要的一種。時(shí)鐘中斷驅(qū)動(dòng)著操作系統(tǒng)中的時(shí)間與定時(shí)器,是系統(tǒng)中與時(shí)間相關(guān)的所有操作的基礎(chǔ),是必須由操作系統(tǒng)內(nèi)核處理的最基本的外部中斷。時(shí)鐘中斷來源于計(jì)算機(jī)系統(tǒng)中的時(shí)鐘設(shè)備。時(shí)鐘設(shè)備是一種特殊的外部設(shè)備,其主要作用是產(chǎn)生時(shí)鐘中斷。傳統(tǒng)的時(shí)鐘設(shè)備常用于產(chǎn)生周期性的時(shí)鐘中斷,被看作是計(jì)算機(jī)系統(tǒng)的心跳與脈搏。老版本的Linux在時(shí)鐘中斷處理中完成所有與時(shí)間相關(guān)的管理工作,包括計(jì)時(shí)與定時(shí),未形成獨(dú)立的時(shí)鐘管理系統(tǒng)。1第五章 時(shí)

理這種嵌入在中斷處理中的時(shí)鐘管理方案雖然簡單,但卻存在一些問題,如與時(shí)鐘設(shè)備硬件綁定過緊,難以維護(hù);增加新的時(shí)鐘設(shè)備時(shí)需重寫管理程序,代碼重復(fù)量大;難以提供高精度定時(shí)、周期性時(shí)鐘中斷暫停等新型服務(wù)等,因而有必要對系統(tǒng)中的時(shí)鐘管理部分進(jìn)行重新設(shè)計(jì)。2005年以后,隨著高精度時(shí)鐘設(shè)備的引入,出現(xiàn)了多種時(shí)鐘管理改進(jìn)方案,這些方案被逐漸集成到了新的Linux版本中,逐步形成了獨(dú)立的時(shí)鐘管理系統(tǒng)。以時(shí)鐘管理系統(tǒng)為基礎(chǔ),當(dāng)前的Linux已可提供多種優(yōu)質(zhì)的計(jì)時(shí)與定時(shí)服務(wù)。1第五章 時(shí)

理時(shí)鐘管理系統(tǒng)負(fù)責(zé)管理時(shí)鐘設(shè)備和計(jì)時(shí)器,處理系統(tǒng)中與時(shí)間相5關(guān).的1

工時(shí)作。鐘Li管nux理中的系時(shí)統(tǒng)鐘管組理成系統(tǒng)結(jié)由構(gòu)兩大部分組成,其基礎(chǔ)是時(shí)鐘設(shè)備管理和計(jì)時(shí)器管理,建立在該基礎(chǔ)上的是基于時(shí)間的服務(wù),其組織結(jié)構(gòu)如圖5.1所示。1第五章 時(shí)

理圖5.1時(shí)鐘管理系統(tǒng)的組織結(jié)構(gòu)1第五章 時(shí)

理時(shí)鐘設(shè)備管理子系統(tǒng)負(fù)責(zé)管理系統(tǒng)中的時(shí)鐘設(shè)備,其中包含一個(gè)管理框架和一組通用操作,支持時(shí)鐘設(shè)備的注冊、選用、模式設(shè)置及時(shí)鐘中斷的處理。每一個(gè)時(shí)鐘設(shè)備都需要向該子系統(tǒng)注冊一個(gè)管理結(jié)構(gòu)。時(shí)鐘設(shè)備可工作在周期中斷模式、高精度單發(fā)中斷模式或低精度單發(fā)中斷模式。但在一個(gè)特定的時(shí)間點(diǎn)上,一個(gè)時(shí)鐘設(shè)備只能工作一種中斷模式。計(jì)時(shí)器管理子系統(tǒng)負(fù)責(zé)管理系統(tǒng)中的計(jì)時(shí)器設(shè)備。系統(tǒng)中可能同時(shí)存在多種計(jì)時(shí)器設(shè)備,每一種計(jì)時(shí)器都需要注冊一個(gè)管理結(jié)構(gòu)。以高精度計(jì)時(shí)器和時(shí)鐘設(shè)備為基礎(chǔ),可為用戶提供更加精確、平滑的時(shí)間服務(wù)。1第五章 時(shí)

理時(shí)鐘管理系統(tǒng)提供的服務(wù)包括時(shí)間管理(更新墻上時(shí)間并為用戶提供時(shí)間服務(wù))、定時(shí)管理(管理各類定時(shí)器并為用戶提供定時(shí)服務(wù))、進(jìn)程賬務(wù)管理(統(tǒng)計(jì)進(jìn)程的時(shí)間消耗信息并在需要時(shí)啟動(dòng)進(jìn)程調(diào)度)、負(fù)載管理(統(tǒng)計(jì)系統(tǒng)負(fù)載并進(jìn)行必要的平衡)等。老版本的Linux僅提供了兩種定時(shí)器,即核心定時(shí)器和時(shí)間間隔定時(shí)器。新版本的Linux增加了一個(gè)管理框架,專門用于管理系統(tǒng)中的高精度定時(shí)器。核心定時(shí)器和時(shí)間間隔定時(shí)器可建立在周期性時(shí)鐘中斷之上,但高精度定時(shí)器只能建立在高精度單發(fā)式時(shí)鐘中斷之上。1第五章 時(shí)

理單發(fā)式時(shí)鐘中斷僅在需要時(shí)產(chǎn)生,不需要時(shí)可以暫停。通過暫??臻e處理器上的周期性時(shí)鐘中斷,可極大地減少時(shí)鐘中斷的次數(shù),改善系統(tǒng)的節(jié)能效果。1第五章 時(shí)

理PIT(Programmable

Interval

Timer)。目前的系統(tǒng)中通常配置有多種時(shí)鐘設(shè)備,如Local

APIC

Timer、HPET(HighPrecision

Event

Timer)、ACPI的電源管理定時(shí)器(PowerManagement

Timer)等。1早期的系統(tǒng)中5.只2有一時(shí)個(gè)鐘時(shí)鐘設(shè)設(shè)備備,管即理第五章 時(shí)

理其中的PIT和HPET屬于全局時(shí)鐘設(shè)備,Local

APIC

Timer屬于局部時(shí)鐘設(shè)備。每類全局時(shí)鐘設(shè)備的配置量一般不會超過1個(gè),但每個(gè)處理器都可能配置有自己的局部時(shí)鐘設(shè)備。全局時(shí)鐘設(shè)備所產(chǎn)生的時(shí)鐘中斷可以被遞交給系統(tǒng)中任意一個(gè)處理器,局部時(shí)鐘設(shè)備所產(chǎn)生的時(shí)鐘中斷僅會遞交給與之相連的處理器。時(shí)鐘設(shè)備通常支持兩種中斷模式。工作在周期(Period)模式的時(shí)鐘設(shè)備會產(chǎn)生周期性的時(shí)鐘中斷,工作在單發(fā)(One

shot)模式的時(shí)鐘設(shè)備每啟動(dòng)一次僅會產(chǎn)生一個(gè)時(shí)鐘中斷。1第五章 時(shí)

理5.2.1

時(shí)鐘設(shè)備管理結(jié)構(gòu)1顯然,不同的時(shí)鐘設(shè)備具有不同的特性、不同的狀態(tài)和不同的操作方法。為了統(tǒng)一管理,Linux定義了結(jié)構(gòu)clock_event_device用來描述時(shí)鐘設(shè)備,每種時(shí)鐘設(shè)備一個(gè)。結(jié)構(gòu)clock_event_device中包含以下一些屬性域:時(shí)鐘設(shè)備特性features,如是否支持周期中斷模式、是否支持單發(fā)中斷模式、是否會在處理器睡眠(C3狀態(tài))時(shí)停止產(chǎn)生中斷、是否為啞設(shè)備等。設(shè)備當(dāng)前中斷模式mode,如未用、已關(guān)閉、周期模式、單發(fā)模式等。第五章 時(shí)

理下一次時(shí)鐘中斷發(fā)生時(shí)間next_event,僅用于單發(fā)中斷模式。next_event的取值范圍在min_delta_ns和max_delta_ns之間,單位為納秒。轉(zhuǎn)換關(guān)系mult和shift,用于時(shí)鐘中斷周期(納秒)和輸入脈沖數(shù)之間的相互轉(zhuǎn)換。通常情況下,時(shí)鐘設(shè)備在收

到多個(gè)輸入脈沖后會產(chǎn)生1個(gè)時(shí)鐘中斷。時(shí)鐘設(shè)備優(yōu)先級rating,值越大表示時(shí)鐘設(shè)備的優(yōu)先級越高。中斷請求號irq,是時(shí)鐘設(shè)備所產(chǎn)生的IRQ號。1第五章 時(shí)

理(7)處理器位圖cpumask,描述該時(shí)鐘設(shè)備所服務(wù)的處理器集合。結(jié)構(gòu)clock_event_device中還包含四個(gè)操作函數(shù),用于實(shí)現(xiàn)時(shí)鐘設(shè)備的管理操作,其中set_mode用于設(shè)置時(shí)鐘設(shè)備的中斷模式,set_next_event用于設(shè)置時(shí)鐘設(shè)備的下一次中斷時(shí)間,broadcast用于將設(shè)備產(chǎn)生的時(shí)鐘中斷廣播給其它處理器,event_handler用于處理時(shí)鐘中斷。1第五章 時(shí)

理Linux提供了兩個(gè)全局隊(duì)列用于管理時(shí)鐘設(shè)備,其中隊(duì)列clockevent_devices中包含所有已注冊且已被選用的時(shí)鐘設(shè)備,隊(duì)列clockevents_released中包含已注冊但未被選用的時(shí)鐘設(shè)備。指針global_clock_event指向當(dāng)前使用的全局時(shí)鐘設(shè)備。傳統(tǒng)的時(shí)鐘設(shè)備通常工作在周期中斷模式,用以產(chǎn)生周期性的時(shí)鐘中斷。周期性時(shí)鐘中斷的頻率是操作系統(tǒng)中的一個(gè)重要參數(shù),稱為HZ。1第五章 時(shí)

理兩次時(shí)鐘中斷之間的時(shí)間間隔稱為1個(gè)滴答(tick)。在早期的版本中,HZ被設(shè)為100,即1秒鐘產(chǎn)生100次時(shí)鐘中斷,滴答值是10

ms。在新版本中,HZ被設(shè)為1000,即1秒鐘產(chǎn)生1000次時(shí)鐘中斷,滴答值是1

ms。新式的時(shí)鐘設(shè)備通常工作在單發(fā)中斷模式,不再依賴于周期性時(shí)鐘中斷,因而可以將HZ取消掉。1第五章 時(shí)

理5.2.2

PIT設(shè)備1傳統(tǒng)的PIT由三個(gè)計(jì)數(shù)器組成,各計(jì)數(shù)器的初值由操作系統(tǒng)設(shè)定,并隨PIT的輸入脈沖而遞減,如圖5.2所示。PIT的三個(gè)計(jì)數(shù)器可獨(dú)立配置、獨(dú)立工作,支持周期和單發(fā)兩種中斷模式。若計(jì)數(shù)器工作在周期中斷模式,那么每當(dāng)它的計(jì)數(shù)值減到0時(shí),就會輸出一個(gè)脈沖,而后計(jì)數(shù)器會恢復(fù)初值,重新開始計(jì)數(shù),因而會產(chǎn)生周期性的輸出脈沖。缺省情況下,第0號計(jì)數(shù)器工作在周期中斷模式,它的輸出脈沖會周期性地中斷處理器,因而常被稱為周期性時(shí)鐘中斷。第五章 時(shí)

理圖5.2基于PIT的時(shí)鐘中斷1第五章 時(shí)

理在計(jì)算機(jī)系統(tǒng)中,PIT設(shè)備的輸入頻率是1

193

182

Hz,即每秒1

193

182個(gè)輸入脈沖。當(dāng)PIT工作在周期中斷模式時(shí),它產(chǎn)生周期性時(shí)鐘中斷的頻率略大于Hz。當(dāng)PIT工作在單發(fā)中斷模式時(shí),可為它設(shè)定的下一次中斷時(shí)間應(yīng)在12

571

ns(0xF個(gè)輸入脈沖)到27

461

862

ns(0x7FFF個(gè)輸入脈沖)之間。PIT是最基本的時(shí)鐘設(shè)備,其clock_event_device結(jié)構(gòu)已被注冊到

clockevent_devices隊(duì)列中。1第五章 時(shí)

理PIT內(nèi)部有4個(gè)寄存器,分別是計(jì)數(shù)器0、計(jì)數(shù)器1、計(jì)

數(shù)器2和控制寄存器,其I/O端口號分別是0x40、0x41、0x42、0x43。通過操作PIT的I/O端口可以改變其中斷模式,如將PIT設(shè)為周期中斷模式并將第0號計(jì)數(shù)器的初值設(shè)為(1193

182+Hz/2)/Hz、將PIT設(shè)為未用或關(guān)閉模式以禁止它繼續(xù)產(chǎn)生時(shí)鐘中斷等。若PIT工作在單發(fā)中斷模式,通過設(shè)置它的第0號計(jì)數(shù)器的計(jì)數(shù)值可以設(shè)定它的下一次中斷時(shí)間。PIT的輸入頻率較低,且不夠規(guī)整,滴答值難以算得十分精確(略小)。在目前的計(jì)算機(jī)系統(tǒng)中,只有當(dāng)HPET不可用時(shí)才會選用PIT。1第五章 時(shí)

理5.2.3

HPET設(shè)備1HPET是一種高精度時(shí)鐘設(shè)備,其輸入時(shí)鐘的頻率不低于10

MHz。一個(gè)HPET由一個(gè)主計(jì)數(shù)器和最多32個(gè)Timer組

成,每個(gè)Timer中又包含一個(gè)比較器和一個(gè)匹配寄存器,如圖5.3所示。HPET的主計(jì)數(shù)器單調(diào)增長,每個(gè)輸入時(shí)鐘周期加1。比較器隨時(shí)比較主計(jì)數(shù)器的當(dāng)前值與自己匹配寄存器的預(yù)定值,當(dāng)發(fā)現(xiàn)兩者匹配時(shí)即請求產(chǎn)生中斷。如果Timer工作在周期中斷模式,那么每次中斷之后其匹配寄存器的值都會自動(dòng)累加一個(gè)周期數(shù)(記錄在周期寄存器中),因而可產(chǎn)生周期性的時(shí)鐘中斷。第五章 時(shí)

理如果Timer工作在單發(fā)中斷模式,在產(chǎn)生中斷之后其匹配器的值不會自動(dòng)調(diào)整,因而僅能產(chǎn)生一次性的時(shí)鐘中斷。HPET的每個(gè)Timer都可以獨(dú)立地產(chǎn)生中斷,其中的第0號Timer可用于替代PIT(連接到PIC的第0號管腳或I/O

APIC的第2號管腳),第1號Timer可用于替代RTC的定時(shí)器(連接到PIC或I/O

APIC的第8號管腳)。1第五章 時(shí)

理圖5.3

HPET組成結(jié)構(gòu)1第五章 時(shí)

理如果系統(tǒng)支持HPET,那么在ACPI的描述表中一定包含著有關(guān)HPET的描述信息,如其寄存器的物理基地址等。Linux在初始化時(shí)已經(jīng)對HPET做了如下設(shè)置工作:(1)已將HPET的寄存器映射到了內(nèi)核的線性地址空間。與PIT相比,HPET內(nèi)部有更多的寄存器,如用于整體管理

的能力與ID寄存器、配置寄存器、中斷狀態(tài)寄存器、主計(jì)數(shù)寄存器等,用于各Timer自身管理的配置寄存器、匹配寄存器和中斷路由寄存器等。Linux用內(nèi)存映射方式訪問

HPET的寄存器。1第五章 時(shí)

理已對HPET的配置信息進(jìn)行了合法性檢查。讀HPET的寄存器可獲得它的配置信息,如其中的計(jì)數(shù)器個(gè)數(shù)、主計(jì)數(shù)器的計(jì)數(shù)周期(以10-15s為單位)等。Linux假定HPET的主計(jì)數(shù)周期(輸入時(shí)鐘周期)應(yīng)在0.1

ns~100

ns之間。已注冊了HPET的clock_event_device結(jié)構(gòu)。當(dāng)HPET工作在單發(fā)中斷模式時(shí),可為它設(shè)定的下一次中斷時(shí)間應(yīng)不小于5000

ns且不大于0x7FFFFFFF個(gè)主計(jì)數(shù)周期。1第五章 時(shí)

理(4)已在數(shù)組hpet_devs中記錄了HPET中所有Timer的配置信息。除第0和第1號Timer之外,HPET的其它Timer可動(dòng)態(tài)分配,用做其它目的。通過讀寫HPET的寄存器,可以對其進(jìn)行以下操作:(1)啟/停HPET。整體配置寄存器的第0位是啟/停位,將其清0,可使整個(gè)HPET停止工作,將其置1,可使整個(gè)

HPET重新工作。(2)讀/寫主計(jì)數(shù)器。讀主計(jì)數(shù)器可獲得它的當(dāng)前值,寫主計(jì)數(shù)器可以設(shè)置它的計(jì)數(shù)初值,如0。1第五章 時(shí)

理(3)改變各Timer的中斷模式。如將某個(gè)Timer設(shè)為周期中斷模式并設(shè)置它的計(jì)數(shù)周期(頻率也是Hz)、將某Timer設(shè)為單發(fā)中斷模式并通過匹配寄存器設(shè)定它的下次中斷時(shí)間、將某個(gè)Timer設(shè)為未用或關(guān)閉模式以禁止它繼續(xù)產(chǎn)生中斷等。1第五章 時(shí)

理5.2.4 Local

APIC設(shè)備1LocalAPIC

Timer位于LocalAPIC內(nèi)部,是一種局部時(shí)鐘設(shè)備。與PIT和HPET不同,LocalAPICTimer沒有自己獨(dú)立的時(shí)鐘源,它的定時(shí)依據(jù)是處理器的總線時(shí)鐘。每個(gè)LocalAPICTimer內(nèi)部至少包含三個(gè)寄存器,其中分頻寄存器用于設(shè)置Timer的計(jì)數(shù)頻率,實(shí)際是對處理器總線頻率的分頻。Local

APIC

Timer的實(shí)際計(jì)數(shù)頻率為總線頻率的1/2i(i=0~7),i由分頻寄存器指定。初始計(jì)數(shù)器用于設(shè)置計(jì)數(shù)初值。第五章 時(shí)

理當(dāng)前計(jì)數(shù)器的初值來源于初始計(jì)數(shù)器,并按計(jì)數(shù)頻率遞減。當(dāng)當(dāng)前計(jì)數(shù)器的值遞減到0時(shí),LocalAPIC

Timer產(chǎn)生中斷,并被遞交給與之相連的處理器,其中斷向量號為0xef。Local

APIC

Timer可工作在單發(fā)中斷模式和周期中斷模式中。當(dāng)工作在單發(fā)模式時(shí),當(dāng)前計(jì)數(shù)器從初始計(jì)數(shù)器中獲得初值并開始遞減,當(dāng)遞減到0時(shí)產(chǎn)生中斷,而后停止,等待下一次設(shè)置。當(dāng)工作在周期模式時(shí),當(dāng)前計(jì)數(shù)器會自動(dòng)從初始計(jì)數(shù)器重裝初值,反復(fù)計(jì)數(shù),從而產(chǎn)生周期性的中斷。1第五章 時(shí)

理Local

APIC

Timer可以被關(guān)閉,此時(shí)處理器僅能使用全局時(shí)鐘設(shè)備。Local

APIC

Timer也可以被啟用,此時(shí)處理器通常使用自己的局部時(shí)鐘設(shè)備。每個(gè)Local

APIC

Timer都要注冊自己的clock_event_device結(jié)構(gòu),注冊工作由處理器自己完成。Linux按16分頻設(shè)置Local

APICTimer,即每過16個(gè)總線時(shí)鐘周期Local

APICTimer的當(dāng)前計(jì)數(shù)值才會減1。由于處理器的總線時(shí)鐘不是固定的,因而必須預(yù)先估算總線時(shí)鐘頻率或Local

APIC

Timer的計(jì)數(shù)頻率。1第五章 時(shí)

理估算的依據(jù)是全局時(shí)鐘中斷,方法是讓系統(tǒng)延時(shí)100個(gè)滴答(100

ms),記下其間當(dāng)前計(jì)數(shù)器的計(jì)數(shù)差,從而估算出Local

APIC計(jì)數(shù)器的計(jì)數(shù)頻率和處理器的總線時(shí)鐘頻率。當(dāng)LocalAPICTimer工作在單發(fā)中斷模式時(shí),可為它設(shè)定的下一次中斷時(shí)間,即LocalAPIC的計(jì)數(shù)初值,應(yīng)在0xF到0x7FFFFF之間。1第五章 時(shí)

理改變Local

APIC

Timer的中斷模式需要設(shè)置Local

APIC局部中斷向量表中的LVTT和Timer的初始計(jì)數(shù)器,LVTT控制Timer的中斷模式(周期模式、單發(fā)模式)、中斷向量和中斷屏蔽等,初始計(jì)數(shù)器控制Timer的中斷頻率(周期模式)或下一次中斷時(shí)間(單發(fā)模式)。關(guān)閉Local

APIC

Timer的方法十分簡單,屏蔽它的中斷即可。特殊情況下,可以廣播一個(gè)Local

APIC

Timer的時(shí)鐘中斷,從而將其轉(zhuǎn)化成全局時(shí)鐘設(shè)備。方法是在局部時(shí)鐘中斷處理中,讓當(dāng)前處理器通過IPI機(jī)制向其它處理器發(fā)送處理器間中斷,中斷向量號也是0xef。1第五章 時(shí)

理15.2.5

當(dāng)前時(shí)鐘設(shè)備由于系統(tǒng)中同時(shí)存在多種時(shí)鐘設(shè)備,因而不同的處理器可能選用不同的時(shí)鐘設(shè)備。Linux在PERCPU數(shù)據(jù)區(qū)中為每個(gè)處理器定義了一個(gè)結(jié)構(gòu)變量tick_cpu_device(類型為tick_device),用于記錄處理器當(dāng)前使用的時(shí)鐘設(shè)備。每個(gè)處理器都需要選用一個(gè)時(shí)鐘設(shè)備,一個(gè)時(shí)鐘設(shè)備只能被一個(gè)處理器選用。struct

tick_device

{*evtdev;//mode;//中斷模struct

clock_event_device時(shí)鐘設(shè)備enum

tick_device_mode式};第五章 時(shí)

理DEFINE_PER_CPU(struct

tick_device,tick_cpu_device);每當(dāng)有新的時(shí)鐘設(shè)備注冊時(shí),當(dāng)前處理器都會進(jìn)行檢查比對,決定是否需要更新自己的時(shí)鐘設(shè)備。檢查的范圍包括新注冊的時(shí)鐘設(shè)備和clockevents_released隊(duì)列中的所有空閑的時(shí)鐘設(shè)備。在下列條件下,處理器將更換時(shí)鐘設(shè)備:新設(shè)備能為本處理器提供時(shí)鐘中斷。處理器還未選用時(shí)鐘設(shè)備,或新時(shí)鐘設(shè)備的優(yōu)先級比已選用設(shè)備的優(yōu)先級高。如果處理器已經(jīng)選用了時(shí)鐘設(shè)備,那么在下列情況下不用再進(jìn)行更換:1第五章 時(shí)

理新設(shè)備不能為本處理器提供時(shí)鐘中斷。處理器已選用了自己的局部時(shí)鐘設(shè)備。處理器已選用的時(shí)鐘設(shè)備支持單發(fā)中斷模式,但新時(shí)鐘設(shè)備不支持。處理器已選時(shí)鐘設(shè)備的優(yōu)先級比新設(shè)備的優(yōu)先級高。如果處理器決定選用或更換時(shí)鐘設(shè)備,它要進(jìn)行如下處理:1第五章 時(shí)

理如果處理器還未選用時(shí)鐘設(shè)備,則將新注冊的設(shè)備選為自己的周期性時(shí)鐘設(shè)備,即讓tick_cpu_device中的

evtdev指向新設(shè)備;如果處理器已選用過時(shí)鐘設(shè)備,則將老的時(shí)鐘設(shè)備設(shè)為未用模式,將其轉(zhuǎn)到clockevents_released隊(duì)列中,而后將新設(shè)備設(shè)為自己的時(shí)鐘設(shè)備,中斷模式與處理函數(shù)保持不變。如果選用的新設(shè)備不是當(dāng)前處理器的局部時(shí)鐘設(shè)備

(全局時(shí)鐘設(shè)備),則需要設(shè)置中斷控制器,讓其將新時(shí)鐘設(shè)備的中斷遞交給當(dāng)前處理器。事實(shí)上,每個(gè)時(shí)鐘設(shè)備的中斷僅會遞交給一個(gè)處理器。1第五章 時(shí)

理如果還未為時(shí)鐘中斷全局部分的處理工作指定處理器,則指定當(dāng)前處理器。時(shí)鐘中斷的處理工作分成兩部分:全局部分負(fù)責(zé)處理影響系統(tǒng)全局的工作(如更新系統(tǒng)時(shí)間),本地部分負(fù)責(zé)處理單個(gè)處理器內(nèi)部的工作(如更新當(dāng)前進(jìn)程的時(shí)間片)。系統(tǒng)中只能有一個(gè)處理器負(fù)責(zé)全局部分的處理工作。設(shè)置時(shí)鐘設(shè)備的中斷處理函數(shù)。初始情況下,時(shí)鐘設(shè)備工作在周期中斷模式,其處理函數(shù)是

tick_handle_periodic。1第五章 時(shí)

理如果該時(shí)鐘設(shè)備同時(shí)還是時(shí)鐘中斷的廣播設(shè)備,它的處理函數(shù)應(yīng)是tick_handle_periodic_broadcast。(5)啟用新選用的時(shí)鐘設(shè)備。如果新選用的時(shí)鐘設(shè)備工作在周期中斷模式,還要設(shè)置它的中斷頻率,否則要設(shè)置它的下一次中斷時(shí)間。在系統(tǒng)初始化時(shí),BSP負(fù)責(zé)注冊全局時(shí)鐘設(shè)備PIT和HPET,同時(shí)也會注冊自己的Local

APIC

Timer。由于LocalAPIC

Timer的優(yōu)先級比全局設(shè)備的優(yōu)先級高,因而只要BSP未禁用Local

APIC,它肯定會選用自己的局部時(shí)鐘設(shè)備。1第五章 時(shí)

理在AP啟動(dòng)過程中,它們也會注冊自己的Local

APIC

Timer,且會選用自己的局部時(shí)鐘設(shè)備。所以,正常情況下,處理器都會選用自己的局部時(shí)鐘設(shè)備,除非它的Local

APIC被禁用。如果處理器選用的是啞時(shí)鐘設(shè)備(不會產(chǎn)生時(shí)鐘中斷),則要啟用廣播設(shè)備(HPET或PIT)。指針tick_broadcast_device指向廣播設(shè)備,位圖tick_broadcast_mask記錄需要接收時(shí)鐘中斷廣播的處理器。初始情況下,廣播設(shè)備也工作在周期中斷模式,其處理函數(shù)是tick_handle_periodic_broadcast。當(dāng)廣播設(shè)備產(chǎn)生中斷時(shí),其處理函數(shù)會將該中斷轉(zhuǎn)發(fā)給選用啞設(shè)備的處理器,所轉(zhuǎn)發(fā)的中斷號就是啞設(shè)備注冊的中斷向量號,如0xef。1第五章 時(shí)

理傳統(tǒng)的計(jì)算機(jī)系統(tǒng)中僅有一個(gè)RTC和一個(gè)PIT,因而只1能以滴答為基礎(chǔ)5建.立3其計(jì)時(shí)間時(shí)管理器系統(tǒng)管。在理新的計(jì)算機(jī)系統(tǒng)中,除PIT之外,還配置有其它的計(jì)時(shí)設(shè)備,如HPET、TSC等,它們可以提供更小的計(jì)時(shí)單位、更高的計(jì)時(shí)精度和更新的計(jì)時(shí)方法。然而,多種共存的計(jì)時(shí)設(shè)備也增加了管理的復(fù)雜性。第五章 時(shí)

理為了統(tǒng)一起見,Linux將可以用來計(jì)時(shí)的設(shè)備抽象成計(jì)時(shí)器,并專門定義了結(jié)構(gòu)clocksource(也叫timesource)來描述計(jì)時(shí)器。每個(gè)計(jì)時(shí)器都有定義自己的clocksource結(jié)構(gòu),其中包含如下一些屬性域:優(yōu)先級rating,值越大表示計(jì)時(shí)器的優(yōu)先級越高。轉(zhuǎn)換關(guān)系mult和shift,用于計(jì)時(shí)單位數(shù)與納秒數(shù)之間的互換,兩者之間的關(guān)系是mult=1個(gè)計(jì)時(shí)單位的長度(納秒)*2shift。對jiffies計(jì)時(shí)器,1個(gè)計(jì)時(shí)單位就是1個(gè)滴答。對HPET計(jì)時(shí)器,1個(gè)計(jì)時(shí)單位就是一個(gè)輸入脈沖周期。1第五章 時(shí)

理(3)操作函數(shù),其中read和vread用于獲得計(jì)時(shí)器的當(dāng)前

值,resume用于恢復(fù)計(jì)時(shí)器的運(yùn)行,enable和disable用于開、關(guān)計(jì)時(shí)器等。計(jì)時(shí)器可動(dòng)態(tài)地注冊、注銷,并可暫停、恢復(fù)。系統(tǒng)中所有已注冊的clocksource結(jié)構(gòu)都被組織在鏈表clocksource_list中,高優(yōu)先級的在前,低優(yōu)先級的在后。指針curr_clocksource指向當(dāng)前使用的計(jì)時(shí)器,通常是已注冊且優(yōu)先級最高的計(jì)時(shí)器。在系統(tǒng)運(yùn)行過程中,當(dāng)前計(jì)時(shí)器可以被改變。1第五章 時(shí)

理在目前的Linux版本中,可用的計(jì)時(shí)器已有多種,包括基于jiffies的計(jì)時(shí)器、基于TSC的計(jì)時(shí)器、基于HPET的計(jì)時(shí)器等?;趈iffies的計(jì)時(shí)器是最傳統(tǒng)的計(jì)時(shí)器,它所計(jì)的是相對時(shí)間。Jiffies計(jì)時(shí)器建立在變量jiffies之上,或者說就是jiffies變量,其計(jì)時(shí)單位是滴答。如果系統(tǒng)使用的時(shí)鐘設(shè)備是PIT,時(shí)鐘中斷的頻率Hz是1000,那么一個(gè)滴答的長度約為999

847

ns,略小于106ns(1毫秒的納秒數(shù))。Jiffies計(jì)時(shí)器的read操作所讀出的是jiffies變量的當(dāng)前值。1第五章 時(shí)

理基于jiffies的計(jì)時(shí)器誤差較大,精度較低,而且會受時(shí)鐘中斷丟失的影響,因而其優(yōu)先級最低(為1),通常僅用做備用計(jì)時(shí)器。如果系統(tǒng)中配置有HPET,系統(tǒng)會在使能它時(shí)注冊基于HPET的計(jì)時(shí)器。HPET的計(jì)時(shí)頻率是其主計(jì)數(shù)器的增長頻率,計(jì)時(shí)單位即是其輸入時(shí)鐘的周期(可以從HPET的寄存器中讀出),不大于100

ns。因而HPET計(jì)時(shí)器的精度遠(yuǎn)高于jiffies計(jì)時(shí)器,優(yōu)先級為250,也遠(yuǎn)高于jiffies計(jì)時(shí)器。1第五章 時(shí)

理HPET計(jì)時(shí)器建立在其主計(jì)數(shù)器之上,或者說就是HPET的主計(jì)數(shù)器。在啟用HPET時(shí),其主計(jì)數(shù)器被清0,所以HPET計(jì)時(shí)器所計(jì)的也是相對時(shí)間。HPET計(jì)時(shí)器的read操作所讀出的是主計(jì)數(shù)器的當(dāng)前值。TSC(Time

Stamp

Counter)是Intel處理器提供的一個(gè)時(shí)間戳計(jì)數(shù)器,該計(jì)數(shù)器在開機(jī)或RESET時(shí)清0,在處理器運(yùn)行過程中單調(diào)增長。在較老的處理器上,每個(gè)內(nèi)部處理器時(shí)鐘周期都會使TSC遞增;在新的處理器上,TSC可按固

定速率遞增。Intel提供了專門的指令RDTSC用于讀取TSC的當(dāng)前值。1第五章 時(shí)

理TSC的計(jì)時(shí)單位取決于處理器的時(shí)鐘周期,需要估算。Linux初始化時(shí)已利用PIT的第2個(gè)計(jì)數(shù)器(用于揚(yáng)聲器)估算出了TSC的計(jì)數(shù)頻率,估算的方法很直觀,如下:讀出TSC的當(dāng)前計(jì)數(shù)值tsc1。等待PIT第2個(gè)計(jì)數(shù)器的值減少i個(gè),即延時(shí)(i×1000/1

193

182)ms。再讀出TSC的當(dāng)前計(jì)數(shù)值tsc2。TSC的計(jì)數(shù)頻率tsc_khz=((tsc2-tsc1)×1

193182)/(i×1000)kHz。當(dāng)然,當(dāng)處理器調(diào)整時(shí)鐘頻率時(shí),其TSC的計(jì)數(shù)頻率還需要重新估算。1第五章 時(shí)

理TSC計(jì)時(shí)器的read操作所讀出的是TSC計(jì)數(shù)器的當(dāng)前值。

由于目前處理器的時(shí)鐘頻率都比較高(1

GHz以上),因而TSC的計(jì)時(shí)精度很高。TSC計(jì)時(shí)器的優(yōu)先級為300,是最佳的計(jì)時(shí)器。1第五章 時(shí)

理初始情況下,時(shí)鐘設(shè)備也被設(shè)定在周期中斷模式,用于產(chǎn)生周期性時(shí)鐘中斷。操作系統(tǒng)在周期性時(shí)鐘中斷處理中完成與時(shí)間相關(guān)的所有管理工作,如時(shí)間管理(更新當(dāng)前時(shí)間)、定時(shí)管理(處理各類到期的定時(shí)器)、進(jìn)程時(shí)間片管理、系統(tǒng)負(fù)載統(tǒng)計(jì)等。1時(shí)鐘設(shè)備的5.原4始設(shè)周計(jì)期目標(biāo)性是時(shí)產(chǎn)生鐘周中期性斷的時(shí)鐘中斷。第五章 時(shí)

理5.4.1

周期性時(shí)鐘中斷處理1在早期的版本中,Linux將周期性時(shí)鐘中斷的處理過程分成上下兩部分。上部處理在關(guān)中斷狀態(tài)下執(zhí)行,僅僅累計(jì)變量jiffies。底半處理在開中斷狀態(tài)下執(zhí)行,完成與時(shí)間相關(guān)的管理工作。由于時(shí)鐘中斷可能丟失、底半處理可能被推遲,因而上述處理過程可能導(dǎo)致較大的時(shí)間誤差。在新的Linux版本中,時(shí)鐘中斷的大部分處理工作被移到了硬處理部分,其處理流程依賴于處理器當(dāng)前選用的時(shí)鐘設(shè)備。第五章 時(shí)

理處理器可能選用全局時(shí)鐘設(shè)備。全局時(shí)鐘設(shè)備產(chǎn)生的中斷屬于設(shè)備中斷,使用的IRQ號是0,中斷控制器為它遞交的中斷向量號是0x30。在系統(tǒng)初始化時(shí),已在IRQ0對應(yīng)的irq_desc結(jié)構(gòu)中注冊了處理程序timer_interrupt。每當(dāng)全局時(shí)鐘設(shè)備產(chǎn)生中斷時(shí),按照正常的設(shè)備中斷處理流程,函數(shù)timer_interrupt都會被執(zhí)行一次,該函數(shù)直接調(diào)用全局時(shí)鐘設(shè)備的處理函數(shù)global_clock_event->event_handler完成中斷處理。初始情況下,全局時(shí)鐘設(shè)備的處理函數(shù)是tick_handle_periodic。1第五章 時(shí)

理然而在目前的計(jì)算機(jī)系統(tǒng)中,處理器通常都會選用自己的LocalAPIC

Timer作為時(shí)鐘設(shè)備。LocalAPIC

Timer產(chǎn)生的時(shí)鐘中斷屬于局部中斷,中斷向量號是0xef,中斷處理函數(shù)是apic_timer_interrupt。局部時(shí)鐘中斷的處理流程如下:向Local

APIC的EOI寄存器寫0,應(yīng)答此次時(shí)鐘中斷。增加preempt_count中的硬處理計(jì)數(shù),表示進(jìn)入硬中斷處理程序。累計(jì)當(dāng)前處理器的統(tǒng)計(jì)信息,表示新收到一次局部時(shí)鐘中斷。1第五章 時(shí)

理執(zhí)行本地clock_event_device結(jié)構(gòu)中的event_handler操作,處理中斷。減少preempt_count中的硬處理計(jì)數(shù),表示已退出硬中斷處理程序。由此可見,局部時(shí)鐘中斷實(shí)際是由局部時(shí)鐘設(shè)備的event_handler操作處理的。處理器在選用局部時(shí)鐘設(shè)備時(shí)為它指定的event_handler操作也是tick_handle_periodic。因此,不管處理器選用的是全局時(shí)鐘設(shè)備還是局部時(shí)鐘設(shè)備,最終完成周期性時(shí)鐘中斷處理的都是函數(shù)tick_handle_periodic,該函數(shù)完成的主要處理工作如下:1第五章 時(shí)

理如果當(dāng)前處理器負(fù)責(zé)全局部分的處理工作,則更新系統(tǒng)時(shí)間、統(tǒng)計(jì)系統(tǒng)負(fù)載。統(tǒng)計(jì)當(dāng)前進(jìn)程的賬務(wù)信息,如累計(jì)進(jìn)程消耗的時(shí)間等。處理高精度定時(shí)器隊(duì)列,執(zhí)行其中已到期的各高精度定時(shí)器上的處理函數(shù)。激活軟中斷TIMER_SOFTIRQ,請求處理核心定時(shí)器,并試圖將時(shí)鐘設(shè)備切換到單發(fā)中斷模式。如果當(dāng)前處理器上有待處理器的RCU工作,則激活軟中斷RCU_SOFTIRQ。1第五章 時(shí)

理如果有待處理的日志寫操作,則處理它們。更新當(dāng)前進(jìn)程的調(diào)度信息(參見7.3.5),如更新當(dāng)前進(jìn)程的虛擬計(jì)時(shí)器或時(shí)間片,觸發(fā)處理器間的負(fù)載平衡等。處理符合POSIX標(biāo)準(zhǔn)的時(shí)間間隔定時(shí)器。統(tǒng)計(jì)系統(tǒng)的Profile數(shù)據(jù),以便進(jìn)行性能分析。注意:在切換到單發(fā)中斷模式之后,時(shí)鐘設(shè)備即不再產(chǎn)生周期性的時(shí)鐘中斷,其處理程序也就不會再被執(zhí)行,周期性時(shí)鐘中斷的處理工作將被設(shè)法仿真。1第五章 時(shí)

理5.4.2

時(shí)間管理1時(shí)間管理子系統(tǒng)的主要工作是向用戶提供單調(diào)且平滑增長的、符合人類閱讀習(xí)慣的墻上時(shí)間(Wall

Time

or

Timeof

Day),并能自動(dòng)對時(shí)鐘的漂移進(jìn)行微調(diào)。傳統(tǒng)的時(shí)間管理機(jī)制建立在周期性時(shí)鐘中斷之上,簡單但不準(zhǔn)確,且可能違犯單調(diào)增長的原則。新的時(shí)間管理機(jī)制建立在高精度計(jì)時(shí)器之上,能夠提供單調(diào)、平滑、精確的時(shí)間服務(wù)。在早期的版本中,Linux定義了兩個(gè)時(shí)間變量,其中jiffies的單位為滴答,內(nèi)容是從開機(jī)到當(dāng)前時(shí)刻所過去的滴答總數(shù),稱為相對時(shí)間;第五章 時(shí)

理xtime的單位是微秒,內(nèi)容是從1970-01-01

00:00:00到當(dāng)前時(shí)刻所過去的微秒數(shù),稱為墻上時(shí)間。變量jiffies的類型是32位的無符號整數(shù),變量xtime的類型是一個(gè)結(jié)構(gòu),其中包含兩個(gè)32位的整數(shù),分別表示秒和微秒數(shù),兩者之和為真正的墻上時(shí)間。在隨后的發(fā)展中,時(shí)鐘中斷的頻率(Hz)提高了(jiffies更易溢出),對時(shí)間精度的要求也提高了(納秒),因而Linux調(diào)整了上述兩個(gè)變量的定義,如下:1第五章 時(shí)

理u641jiffies_64_

_/view6/M05/3B/04/wKh2Cl1DyB第五章 時(shí)

理_

_attribute_

_((aligned

(16)));struct

timespec

wall_to_monotonic

__attribute_

_

((aligned

(16)));static

struct

timespec

xtime_/view6/M05/3B/04/wKh2C1第五章 時(shí)

理在系統(tǒng)初始化時(shí),已經(jīng)從RTC中取出了當(dāng)前時(shí)間(分別為year、mon、day、hour、min、sec),并已將它們轉(zhuǎn)化成了相當(dāng)于1970-01-01

00:00:00的秒數(shù)。轉(zhuǎn)化算法如下:將mon提前2月。將mon減2,如果mon<=0,則將

year減1,mon加12。轉(zhuǎn)換后的秒數(shù)=

((((year/4

-

year/100

+

year/400

+367

×

mon

/12

+

day)+year

×

365

-

719499

)×24+hour)×60+min)×60+sec。1第五章 時(shí)

理在變量xtime中,域tv_sec的初值就是這一轉(zhuǎn)化后的秒數(shù),域tv_nsec的初值是0。傳統(tǒng)的計(jì)時(shí)方法是:每收到一個(gè)時(shí)鐘中斷就在jiffies上加1,同時(shí)在xtime上累加1個(gè)滴答的時(shí)間量(如1

ms)。變量wall_to_monotonic用于計(jì)算開機(jī)以來新流逝的時(shí)間量(相對時(shí)間),其初值與xtime相反,且在時(shí)鐘中斷處理中保持不變。因而wall_to_monotonic與xtime的和就是開機(jī)后新流逝是時(shí)間量。這種計(jì)算方法比jiffies更準(zhǔn)確。1第五章 時(shí)

理在系統(tǒng)初始化時(shí),Linux還定義了一個(gè)timekeeper結(jié)構(gòu),用于記錄系統(tǒng)當(dāng)前選用的計(jì)時(shí)器和一些計(jì)時(shí)參數(shù),如

cycle_last是上一次更新墻上時(shí)間的時(shí)刻,xtime_nsec是累計(jì)的計(jì)時(shí)誤差,cycle_interval是一個(gè)時(shí)間更新周期(1個(gè)滴答或1個(gè)NTP校驗(yàn)周期)所對應(yīng)的計(jì)時(shí)單位數(shù),xtime_interval和raw_interval都是一個(gè)時(shí)間更新周期的長度(納秒數(shù)),前者經(jīng)過了NTP(Network

Time

Protocol)校準(zhǔn),后者未經(jīng)過校準(zhǔn)。1第五章 時(shí)

理NTP是一種常用的時(shí)間校準(zhǔn)機(jī)制,用于校正墻上時(shí)間。負(fù)責(zé)全局工作的處理器會在自己的周期性時(shí)鐘中斷處理中更新系統(tǒng)時(shí)間,時(shí)間更新的依據(jù)是當(dāng)前使用的計(jì)時(shí)器。時(shí)間更新的處理流程如下:將jiffies_64加1,因而jiffies也被自動(dòng)加1。從timekeeper中取出上次進(jìn)行時(shí)間更新的時(shí)間cycle_last,從系統(tǒng)當(dāng)前選用的計(jì)時(shí)器中取出當(dāng)前時(shí)間,算出兩者之間的時(shí)間差offset。根據(jù)offset和時(shí)間更新周期(cycle_interval)算出自上次時(shí)間更新以來新流逝的滴答數(shù)。由于時(shí)鐘中斷可能丟失,因而新流逝的滴答數(shù)可能大于1。1第五章 時(shí)

理根據(jù)新流逝的滴答數(shù)調(diào)整xtime中的tv_sec和tv_nsec,同時(shí)調(diào)整timekeeper中的累計(jì)誤差,并將cycle_last更新成最近一個(gè)時(shí)鐘中斷產(chǎn)生的時(shí)刻。根據(jù)timekeeper中的累計(jì)計(jì)時(shí)誤差微調(diào)它的mult、xtime_interval、xtime_nsec等參數(shù),從而校準(zhǔn)計(jì)時(shí)器。減去已累加到xtime中的時(shí)間量之后,offset中可能還有部分剩余,剩余量肯定小于1個(gè)滴答。將剩余的時(shí)間量累計(jì)到變量xtime_/view6/M05/3B/04/wKh2Cl1DyBeAeBD0AAdzuj51第五章 時(shí)

理(6)將xtime中的時(shí)間值拷貝到vsyscall頁中。vsyscall頁已被映射到所有進(jìn)程的虛擬地址空間中,用戶進(jìn)程可以直接訪問其中的內(nèi)容,因而可直接獲得當(dāng)前時(shí)間,從而減少系統(tǒng)調(diào)用的次數(shù),加快進(jìn)程運(yùn)行速度。由此可見,xtime和xtime_/view6/M05/3B/04/wKh2Cl1DyBeA1第五章 時(shí)

理與傳統(tǒng)計(jì)時(shí)方法相比,上述計(jì)時(shí)方法已不再依賴于jiffies,因而更加精確。雖然時(shí)鐘中斷可能丟失,jiffies可能不準(zhǔn)確,但只要收到時(shí)鐘中斷,xtime就會被更新成準(zhǔn)確的當(dāng)前時(shí)間,因?yàn)閤time的更新依據(jù)是高精度計(jì)時(shí)器,如TSC、HPET等,而高精度計(jì)時(shí)器的更新是由硬件自動(dòng)實(shí)現(xiàn)的,不會受關(guān)中斷的影響,也不會丟失。即使出現(xiàn)xtime被延遲更新的現(xiàn)象,用戶通過gettimeofday獲得的當(dāng)前時(shí)間也是精確的,因?yàn)樗趚time上加入了新流逝的時(shí)間量,而新流逝的時(shí)間量也取自高精度計(jì)時(shí)器。1第五章 時(shí)

理在新的計(jì)時(shí)方法中,系統(tǒng)開機(jī)時(shí)間(相對時(shí)間)由

wall_to_monotonic和xtime計(jì)算得來,也不再依賴于jiffies,因而更加精確且保證會單調(diào)增長。事實(shí)上,新的時(shí)間管理子系統(tǒng)已擺脫了對jiffies的依賴,可以在單發(fā)式時(shí)鐘中斷驅(qū)動(dòng)下很好地工作。1第五章 時(shí)

理5.4.3

定時(shí)管理1以周期性時(shí)鐘中斷為基礎(chǔ),可以提供多種定時(shí)器。使用定時(shí)器的目的有兩種,一是超時(shí),目的是監(jiān)測某事件是否會在預(yù)定的時(shí)間內(nèi)發(fā)生,一旦事件發(fā)生,定時(shí)器將被關(guān)閉,定時(shí)器到期表示事件未發(fā)生;二是定時(shí),目的是預(yù)定某項(xiàng)工作的停止或開始時(shí)間,一旦到期,工作必須立刻停止或開始。用做超時(shí)的定時(shí)器幾乎都會在到期前被關(guān)閉,且不需要很高的精度。用做定時(shí)的定時(shí)器通常會運(yùn)行到預(yù)定的時(shí)間,且需要較高的精度。早期的Linux提供了兩類定時(shí)器,一類是內(nèi)核自己使用的,稱核心定時(shí)器或低精度定時(shí)器;第五章 時(shí)

理另一類是給用戶進(jìn)程使用的,稱時(shí)間間隔定時(shí)器。兩類定時(shí)器都建立在jiffies基礎(chǔ)之上,由周期性時(shí)鐘中斷驅(qū)動(dòng),定時(shí)精度較低。在新版本中,Linux又提供了第三類定時(shí)器,稱為高精度定時(shí)器。高精度定時(shí)器的基礎(chǔ)是高精度時(shí)鐘設(shè)備。1第五章 時(shí)

理1.核心定時(shí)器管理1核心定時(shí)器是最基本的一類定時(shí)器,它所定的是相對于jiffies的時(shí)間,單位為滴答。當(dāng)jiffies的值達(dá)到或超過某核心定時(shí)器的到期時(shí)間時(shí),該定時(shí)器到期,它的處理函數(shù)會被執(zhí)行一次。在高精度定時(shí)機(jī)制被啟用之前,核心定時(shí)器由周期性時(shí)鐘中斷驅(qū)動(dòng);在高精度定時(shí)機(jī)制被啟用之后,核心定時(shí)器由高精度定時(shí)器驅(qū)動(dòng)。一個(gè)核心定時(shí)器由一個(gè)結(jié)構(gòu)timer_list描述,其主要內(nèi)容如下:struct

timer_list

{struct

list_head

entry;第五章 時(shí)

理//預(yù)定的1unsigned

long

expires;到期時(shí)間//到期處void

(*function)(unsigned

long);理函數(shù)data;//給處理*base;//定時(shí)器unsigned

long函數(shù)的參數(shù)struct

tvec_base當(dāng)前所屬的隊(duì)列組集合};第五章 時(shí)

理Linux定義了512個(gè)隊(duì)列用于組織單個(gè)處理器中的核心定時(shí)器,這些隊(duì)列被分成5組,其中tv1組中有256個(gè)隊(duì)列,tv2、tv3、tv4、tv5組中各有64個(gè)隊(duì)列。struct

tvec

{1vec[TVN_SIZE];//vec[TVR_SIZE];//struct

list_headTVN_SIZE=64};struct

tvec_root

{struct

list_headTVR_SIZE=256};第五章 時(shí)

理lock;1//*running_timer;

//struct

tvec_base

{spinlock_t保護(hù)隊(duì)列組的自旋鎖struct

timer_list正在被處理的定時(shí)器unsigned

long

timer_jiffies;

//下一次處理時(shí)間struct

tvec_rootstruct

tvectv1;tv2;第五章時(shí)鐘管理struct

tvecstruct

tvecstruct

tvectv3;tv4;tv5;}

_/view6/M05/3B/04/wKh2Cl1DyBeAeBD0AAdzuj5sPdA17

141第五章 時(shí)

理早期的Linux僅定義了一個(gè)核心定時(shí)器隊(duì)列組集合。新版本的Linux為每個(gè)處理器都定義了一個(gè)核心定時(shí)器隊(duì)列組集合。一個(gè)定時(shí)器僅能加入到一個(gè)隊(duì)列中,因而僅能屬于一個(gè)處理器。指針tvec_bases指向各處理器自己的定時(shí)器隊(duì)列組集合,如圖5.4所示。1第五章 時(shí)

理圖5.4核心定時(shí)器的隊(duì)列組集合結(jié)構(gòu)1第五章 時(shí)

理在一個(gè)核心定時(shí)器的隊(duì)列組集合中,不同隊(duì)列組的定時(shí)范圍不同,相鄰隊(duì)列間的時(shí)間差(粒度)也不同。這一組織方式在保證管理效率的前提下有效地減少了定時(shí)器隊(duì)列的數(shù)量。表5.1列出了各隊(duì)列組的定時(shí)范圍及隊(duì)列組中相鄰隊(duì)列間的時(shí)間差。1第五章 時(shí)

理表5.1隊(duì)列組的定時(shí)范圍及相鄰隊(duì)列間的時(shí)間差1第五章 時(shí)

理在一個(gè)核心定時(shí)器定時(shí)期間,它所處的隊(duì)列組(tvi)會

逐漸變化。定時(shí)器當(dāng)前所處的隊(duì)列組取決于它的定時(shí)間隔,即與當(dāng)前時(shí)刻的距離,也就是預(yù)定的到期時(shí)間(expires)與隊(duì)列組集合中timer_jiffies的差值,該差值落在哪個(gè)隊(duì)列組的定時(shí)范圍,定時(shí)器就應(yīng)該進(jìn)入哪個(gè)隊(duì)列組。隨著時(shí)間的流逝,定時(shí)器的到期時(shí)間越來越近,它所處的隊(duì)列組也會越來越小。到期的定時(shí)器永遠(yuǎn)都在tv1中。核心定時(shí)器在一個(gè)隊(duì)列組中的位置(隊(duì)列)僅取決于它

的到期時(shí)間(expires)而與它的定時(shí)間隔無關(guān)。定時(shí)器的到期時(shí)間是一個(gè)32位的無符號整數(shù),被分成5段,分別對應(yīng)5個(gè)隊(duì)列組,如圖5.5所示。1第五章 時(shí)

理圖5.5定時(shí)器到期時(shí)間(expires)的劃分1第五章 時(shí)

理如一個(gè)核心定時(shí)器應(yīng)進(jìn)入第i

(i在1到5之間)個(gè)隊(duì)列組,其expires的tvi段的值是j,那么該定時(shí)器應(yīng)被插入在第i個(gè)隊(duì)列組的第j個(gè)隊(duì)列中。由于定時(shí)器的expires不會改變,它在隊(duì)列組內(nèi)部的位置就不會隨著時(shí)間的流逝而變動(dòng)。也就是1說,核心定時(shí)器僅會在隊(duì)列組間移動(dòng),不需要在隊(duì)列組內(nèi)移動(dòng)。最壞情況下,一個(gè)定時(shí)器會被移動(dòng)4次,從tv5到tv4、tv4到tv3、tv3到tv2、tv2到tv1,形成了一個(gè)逐級下降的瀑布,因而這種管理模型又稱為瀑布模型。瀑布模型極大地減少了核心定時(shí)器管理的工作量。第五章 時(shí)

理瀑布模型與人類的計(jì)時(shí)習(xí)慣完全吻合。定時(shí)距離越近,定時(shí)粒度應(yīng)該越小,對它的管理應(yīng)越細(xì)致;定時(shí)距離越遠(yuǎn),定時(shí)粒度應(yīng)該越大,對它的管理可以更粗放。啟動(dòng)一個(gè)核心定時(shí)器的工作包括設(shè)置好它的處理函數(shù)和到期時(shí)間,確定它所在的定時(shí)隊(duì)列,而后將它的timer_list結(jié)構(gòu)插入到隊(duì)列(隊(duì)頭或隊(duì)尾)中。停止一個(gè)核心定時(shí)器就是將其timer_list結(jié)構(gòu)從隊(duì)列中摘下。在隊(duì)列間移動(dòng)核心定時(shí)器的工作包括兩步,即先將其從老隊(duì)列中摘下(刪除),再根據(jù)它的expires將其插入到新隊(duì)列中。1第五章 時(shí)

理通過刪除和再插入,可以在同一個(gè)隊(duì)列組集合內(nèi)移動(dòng)定時(shí)器,也可以在不同隊(duì)列組集合間移動(dòng)定時(shí)器,即在不同的處理器間移動(dòng)定時(shí)器,從而實(shí)現(xiàn)定時(shí)器的負(fù)載平衡。當(dāng)然,移動(dòng)定時(shí)器的過程需要鎖(tvec_base中的lock)的保護(hù)。在核心定時(shí)器定時(shí)期間,可以改變它的到期時(shí)間。定時(shí)器的到期時(shí)間被改變之后,它所在的隊(duì)列也應(yīng)隨之改變。核心定時(shí)器由周期性時(shí)鐘中斷驅(qū)動(dòng)。處理器每收到一次時(shí)鐘中斷,不管它來自全局還是局部時(shí)鐘設(shè)備,都會在硬處理程序中激活一次軟中斷TIMER_SOFTIRQ。在系統(tǒng)初始化時(shí),為該軟中斷注冊的處理程序是run_timer_softirq。1第五章 時(shí)

理因而,只要處理器處理軟中斷TIMER_SOFTIRQ,函數(shù)run_timer_softirq就會被執(zhí)行。只要jiffies的當(dāng)前值達(dá)到或超過了隊(duì)列組集合中的timer_jiffies,其上的核心定時(shí)器就會被檢查并被處理。早期的Linux為核心定時(shí)器的每個(gè)隊(duì)列組都定義了一個(gè)index,用來指示該隊(duì)列組中下一個(gè)待處理的隊(duì)列。當(dāng)index所指隊(duì)列被處理完后,index加1,指向下一個(gè)隊(duì)列。新版本的Linux去掉了各隊(duì)列組中的index,改用隊(duì)列組集合中的timer_jiffies統(tǒng)一指示各隊(duì)列組中的下一個(gè)待處理隊(duì)列,如圖5.6所示。1第五章 時(shí)

理圖5.6

timer_jiffies與定時(shí)器隊(duì)列的關(guān)系1第五章 時(shí)

理與expires一樣,timer_jiffies也被劃分成了5個(gè)部分,分別用于指示5個(gè)的隊(duì)列組中的待處理隊(duì)列。域timer_jiffies的初值是隊(duì)列組集合初始化時(shí)的jiffies,在隨后的處理中,timer_jiffies的值會不斷遞增,與jiffies基本保持一致,從而使各組中的隊(duì)列被輪流處理,因此核心定時(shí)機(jī)制又被稱為時(shí)間輪(Timing-Wheel)。核心定時(shí)器的處理流程如下:取出timer_jiffies中的tv1部分,暫記在index中。如果index是0,說明tv1的所有隊(duì)列已被處理過一遍,時(shí)間又過去了256個(gè)滴答,tv2的待處理隊(duì)列上的定時(shí)器距離到期時(shí)間已不足256個(gè)滴答,應(yīng)該將它們下移到tv1中。1第五章 時(shí)

理如果timer_jiffies中的tv2部分是0,說明tv2的所有隊(duì)列已被處理過一遍,時(shí)間又過去了256×64個(gè)滴答,tv3的待處理隊(duì)列上的定時(shí)器距離到期時(shí)間已不足256×64個(gè)滴答,應(yīng)該將它們下移到tv2中。如果timer_jiffies中的tv3部分是0,說明tv3的所有隊(duì)列已被處理過一遍,時(shí)間又過去了256×64×64個(gè)滴答,tv4的待處理隊(duì)列上的定時(shí)器距離到期時(shí)間已不足256×

64×64個(gè)滴答,應(yīng)該將它們下移到tv3中。1第五章 時(shí)

理如果timer_jiffies中的tv4部分是0,說明tv4的所有隊(duì)列已被處理過一遍,時(shí)間又過去了256×64×64×64個(gè)滴答,tv5的待處理隊(duì)列上的定時(shí)器距離到期時(shí)間已不足256×64×64×64個(gè)滴答,應(yīng)該將它們下移到tv4中。將timer_jiffies加1。在tv1中,index所指的是已到期的定時(shí)器隊(duì)列。摘下該隊(duì)列中的所有定時(shí)器,將隊(duì)列清空,而后逐個(gè)執(zhí)行各到期定時(shí)器上的處理函數(shù)function。如果timer_jiffies仍然未超過jiffies的當(dāng)前值,說明還有到期的定時(shí)器,轉(zhuǎn)(1)進(jìn)行新一輪的處理。1第五章 時(shí)

理正常情況下,當(dāng)處理核心定時(shí)器時(shí),隊(duì)列組集合中的timer_jiffies應(yīng)等于jiffies。但由于軟中斷可能被延遲,jiff有可能超過timer_jiffies。這也說明核心定時(shí)器的定時(shí)不是十分精確。1綜上所述,核心定時(shí)器的插入、刪除操作都很快,與系統(tǒng)中的定時(shí)器數(shù)量無關(guān),算法的時(shí)間復(fù)雜度是O(1)。核心定時(shí)器下移的平均時(shí)間復(fù)雜度很好,但最壞時(shí)間復(fù)雜度較差,為O(n),可能會增加定時(shí)處理的延遲時(shí)間。因而,核心定時(shí)器比較適合較近的定時(shí)(小于256滴答)、在到期或被下移之前就被刪除的定時(shí),如網(wǎng)絡(luò)的超時(shí)定時(shí)等。第五章 時(shí)

理2.高精度定時(shí)器管理1建立在周期性時(shí)鐘中斷基礎(chǔ)上的核心定時(shí)器所實(shí)現(xiàn)的定時(shí)粒度為滴答(毫秒級),且最壞時(shí)間復(fù)雜性較差,無法提供更精確的定時(shí)服務(wù)。1998年以來,人們嘗試了多種方法,試圖在核心定時(shí)器的管理框架中集成高精度定時(shí)器,但都沒有達(dá)到理想的效果。直到2006年,在Linux

2.6.16中,以高精度時(shí)鐘設(shè)備為基礎(chǔ),新設(shè)計(jì)了一種高精度定時(shí)器的管理框架,才解決了高精度定時(shí)器的管理問題。與核心定時(shí)器相似,一個(gè)高精度定時(shí)器也需要一個(gè)描

述結(jié)構(gòu),用于記錄它的到期時(shí)間(_expires)、到期處理函數(shù)(function)、定時(shí)器狀態(tài)等,該結(jié)構(gòu)為hrtimer,定義如下:第五章 時(shí)

理node;1struct

hrtimer

{struct

rb_nodektime_t_expires;ktime_t

_softexpires;enum

hrtimer_restart

(*function)(struct

hrtimer

*);*base;state;struct

hrtimer_clock_baseunsigned

long};第五章 時(shí)

理可以為高精度定時(shí)器預(yù)定一個(gè)到期時(shí)間范圍,從1_softexpires到_expires,但定時(shí)仍以_expires為準(zhǔn)。定時(shí)器的狀態(tài)包括未啟動(dòng)、已入隊(duì)、正在處理、正在遷移等。由于系統(tǒng)中可能同時(shí)啟動(dòng)多個(gè)高精度定時(shí)器,因而需要另外一種結(jié)構(gòu)來組織、管理它們的hrtimer結(jié)構(gòu)。根據(jù)高精度定時(shí)器的管理要求,所有的hrtimer結(jié)構(gòu)應(yīng)該組成一個(gè)有序隊(duì)列,隊(duì)頭的定時(shí)器最早到期,隊(duì)尾的定時(shí)器最遲到期。雖然可以用鏈表實(shí)現(xiàn)有序隊(duì)列,但有序鏈表的插入時(shí)間較長,最壞時(shí)間復(fù)雜度為O(n)。第五章 時(shí)

理為改善有序隊(duì)列的管理性能,Linux引入了紅黑樹,將已啟動(dòng)的高精度定時(shí)器組織在紅黑樹中,從而使插入、刪除和查找的時(shí)間復(fù)雜度都縮減到了O(log(n))。結(jié)構(gòu)hrtimer中的

node用于將高精度定時(shí)器鏈接到紅黑樹中。一棵紅黑樹由一個(gè)hrtimer_clock_base結(jié)構(gòu)描述,其定義如下:1struct

hrtimer_clock_base

{struct

hrtimer_cpu_baseclockid_t*cpu_base;index;struct

rb_root

active;第五章 時(shí)

理struct

rb_nodektime_t1*first;resolution;ktime_t

(*get_time)(void);softirq_time;offset;ktime_tktime_t};第五章 時(shí)

理其中的active是紅黑樹的根,first是紅黑樹中最左邊的節(jié)點(diǎn),也就是最早到期的高精度定時(shí)器,resolution是定時(shí)精度(未啟用高精度定時(shí)機(jī)制時(shí)的精度是1個(gè)滴答、啟用后的精度為1ns),offset是定時(shí)的基準(zhǔn)時(shí)間,softirq_time是系統(tǒng)當(dāng)前時(shí)間,get_time是從計(jì)時(shí)器中讀取當(dāng)前時(shí)間的操作函數(shù)。1第五章 時(shí)

理高精度定時(shí)器對到期時(shí)間的表示方法有兩種,一種是絕對時(shí)間(指定一個(gè)絕對的到期時(shí)刻),即定時(shí)到某年某月某日的某時(shí)某分某秒某納秒為止;另一種是相對時(shí)間(指定一個(gè)定時(shí)間隔),即從當(dāng)前時(shí)間開始定時(shí),在某納秒之后到期。采用絕對時(shí)間的定時(shí)器稱為絕對時(shí)間定時(shí)器,采用相對時(shí)間的定時(shí)器稱為相對時(shí)間定時(shí)器。雖然可以用統(tǒng)一的方式表示它們,但Linux提供了兩棵紅黑樹,分別用于組織兩類不同的高精度定時(shí)器。結(jié)構(gòu)hrtimer_cpu_base用于描述這兩棵紅黑樹,其定義如下:1第五章 時(shí)

理struct

hrtimer_cpu_base

{1lock;clock_base[2];//spinlock_tstruct

hrtimer_clock_base兩棵紅黑樹ktime_texpires_next;//時(shí)鐘設(shè)備下次產(chǎn)生中斷的時(shí)間intunsignednr_events;hres_active;

//是//累計(jì)到期次long};第五章 時(shí)

理在實(shí)現(xiàn)時(shí),時(shí)鐘設(shè)備下次產(chǎn)生中斷的時(shí)間expires_next被統(tǒng)一成了相對于開機(jī)時(shí)刻的偏移量,單位為ns。與核心定時(shí)器不同,高精度定時(shí)機(jī)制必須顯式地啟用。域hres_active記錄一個(gè)處理器上的高精度定時(shí)機(jī)制是否已被啟用。與核心定時(shí)器相似,為了避免沖突,Linux在PERCPU

數(shù)據(jù)區(qū)中為每個(gè)處理器定義了一個(gè)紅黑樹管理結(jié)構(gòu),稱為hrtimer_bases,其中的第0棵樹為絕對時(shí)間紅黑樹,讀取當(dāng)前時(shí)間的操作函數(shù)為ktime_get_real;第1棵樹為相對時(shí)間紅黑樹,讀取當(dāng)前時(shí)間的操作函數(shù)為ktime_get。兩棵樹中的初始定時(shí)精度resolution都是1個(gè)滴答。管理結(jié)構(gòu)如圖5.7所示。1第五章 時(shí)

理圖5.7高精度定時(shí)器的管理結(jié)構(gòu)1第五章 時(shí)

理不管是否已啟用高精度定時(shí)機(jī)制,都可以啟動(dòng)高精度定時(shí)器。在啟動(dòng)一個(gè)高精度定時(shí)器之前,需要先初始化它的hrtimer結(jié)構(gòu),設(shè)置好它的到期時(shí)間(_expires)、到期處理函數(shù)、類型(絕對或相對)等,而后按到期時(shí)間的先后順序?qū)⑵洳迦氲脚c定時(shí)器類型匹配的紅黑樹中。如果高精度定時(shí)機(jī)制已被啟用,且新啟動(dòng)定時(shí)器的相對到期時(shí)間(_expires與offset的差)比預(yù)定的下一次中斷時(shí)間expires_next更早,則要對時(shí)鐘設(shè)備進(jìn)行重新編程,以調(diào)整它的下一次中斷時(shí)間。1第五章 時(shí)

理如果高精度定時(shí)機(jī)制未被啟用,則不需要對時(shí)鐘設(shè)備進(jìn)行重新編程。如果在此期間新啟動(dòng)的定時(shí)器已經(jīng)到期,則要激活軟中斷HRTIMER_SOFTIRQ,檢查并處理已到期的高精度定時(shí)器。在高精度定時(shí)器到期之前可以將其停止。停止一個(gè)高精度定時(shí)器的主要工作是將其從紅黑樹中摘除。如果高精度定時(shí)機(jī)制已被啟用,且被停止的定時(shí)器位于紅黑樹的最左邊,則要對時(shí)鐘設(shè)備進(jìn)行重新編程,以調(diào)整它的下一次中斷時(shí)間。最左邊的定時(shí)器被摘除后,它的下一個(gè)定時(shí)器會變成最左邊的定時(shí)器。1第五章 時(shí)

理在一個(gè)高精度定時(shí)器定時(shí)期間,可以改變它的到期時(shí)間。定時(shí)器的到期時(shí)間被改變之后,它在紅黑樹中的位置也要隨之調(diào)整(先摘下、再插入)。在一個(gè)高精度定時(shí)器定時(shí)期間,可以將其從一個(gè)處理器遷移到另一個(gè)處理器(平衡負(fù)載)。遷移一個(gè)定時(shí)器的工作包括將其從老紅黑樹中摘下,再插入到新的紅黑樹中。在初始情況下,高精度定時(shí)機(jī)制都未被啟用(hres_active是0),各時(shí)鐘設(shè)備都工作在周期中斷模式中。在周期性時(shí)鐘中斷驅(qū)動(dòng)下,高精度定時(shí)器的處理流程如下:1第五章 時(shí)

理(1)更新兩棵紅黑樹中的當(dāng)前時(shí)間softirq_time。在絕對

定時(shí)器樹中,softirq_time被更新為xtime_/view6/M05/3B/04/w1第五章 時(shí)

理由此可見,雖然高精度定時(shí)器可以提供更高精度的定時(shí)服務(wù),但在真正啟用高精度定時(shí)機(jī)制之前,其優(yōu)勢并未發(fā)揮出來。在處理之時(shí),有的高精度定時(shí)器可能已經(jīng)過期了較長時(shí)間。此時(shí)的高精度定時(shí)器基本等價(jià)于核心定時(shí)器,有著較大的定時(shí)誤差。1第五章 時(shí)

理3.時(shí)間間隔定時(shí)器管理1用戶進(jìn)程的運(yùn)行也需要定時(shí)器,內(nèi)核應(yīng)該為用戶進(jìn)程提供這類定時(shí)服務(wù)。與核心定時(shí)器和高精度定時(shí)器不同,時(shí)間間隔定時(shí)器是由用戶進(jìn)程在用戶空間啟動(dòng)的(當(dāng)然需要通過系統(tǒng)調(diào)用),它們運(yùn)行在內(nèi)核空間,但需要將到期信息及時(shí)地通知用戶進(jìn)程。通知的手段是信號(Signal)。傳統(tǒng)的Linux提供三類時(shí)間間隔定時(shí)器,分別是實(shí)時(shí)(Real)、虛擬(Virtual)和概略(Profile)定時(shí)器。三類定時(shí)器所定的都是相對時(shí)間。第五章 時(shí)

理實(shí)時(shí)定時(shí)器根據(jù)系統(tǒng)實(shí)際時(shí)間定時(shí),定的是流逝的時(shí)間量,定時(shí)到期時(shí)進(jìn)程會收到SIGALRM信號。虛擬定時(shí)器根據(jù)進(jìn)程消耗的用戶態(tài)時(shí)間定時(shí),定的是進(jìn)程在用戶態(tài)消耗的時(shí)間量,定時(shí)到期時(shí)進(jìn)程會收到SIGVTALRM信號。概略定時(shí)器根據(jù)進(jìn)程消耗的時(shí)間(不管是用戶態(tài)時(shí)間還是核心態(tài)時(shí)間)定時(shí),定的是進(jìn)程消耗的時(shí)間量,定時(shí)到期時(shí)進(jìn)程會收到SIGPROF信號。虛擬與概略定時(shí)器的定時(shí)單位是滴答。Linux統(tǒng)一管理三類時(shí)間間隔定時(shí)器。1第五章 時(shí)

理用戶進(jìn)程不會啟動(dòng)太多的時(shí)間間隔定時(shí)器。事實(shí)上,一個(gè)用戶進(jìn)程最多能夠啟動(dòng)三個(gè)時(shí)間間隔定時(shí)器,每類定時(shí)器一個(gè)。由于這一限制,時(shí)間間隔定時(shí)器的管理結(jié)構(gòu)就不需要特別復(fù)雜,僅需要在進(jìn)程管理結(jié)構(gòu)中為時(shí)間間隔定時(shí)器增加幾個(gè)域變量即可。時(shí)間間隔定時(shí)器可以工作在單發(fā)模式,也可以工作在周期模式。既然間隔定時(shí)器可工作在周期模式,就需要為它們分別準(zhǔn)備一個(gè)變量來記錄周期長度或時(shí)間間隔;既然實(shí)時(shí)定時(shí)器按系統(tǒng)時(shí)間定時(shí),就需要為它準(zhǔn)備一個(gè)高精度定時(shí)器或核心定時(shí)器;1第五章 時(shí)

理既然虛擬和概略定時(shí)器按進(jìn)程消耗的時(shí)間定時(shí),就需要為它們分別準(zhǔn)備變量來記錄進(jìn)程消耗的時(shí)間量和到期的時(shí)間量。早期的Linux將上述信息直接記錄在task_struct結(jié)構(gòu)中,新版本的Linux將這些信息記錄在信號管理結(jié)構(gòu)signal_struct中。結(jié)構(gòu)signal_struct中包含很多內(nèi)容,與時(shí)間間隔定時(shí)器相關(guān)的有如下幾個(gè):real_timer是為實(shí)時(shí)定時(shí)器準(zhǔn)備的高精度定時(shí)器。it_real_incr、it_virt_incr、it_prof_incr是實(shí)時(shí)、擬、概略定時(shí)器的定時(shí)間隔。1第五章 時(shí)

理it_virt_expires和it_prof_expires是虛擬和概略定時(shí)器的當(dāng)前值。utime是進(jìn)程消耗的用戶態(tài)時(shí)間,stime是進(jìn)程消耗的核心態(tài)時(shí)間,utime+stime是進(jìn)程消耗的時(shí)間。定時(shí)器的當(dāng)前值與定時(shí)間隔可以取不同的值,其組合意義如表5.2所示。1第五章 時(shí)

理表5.2時(shí)間間隔定時(shí)器各參數(shù)的組合意義1第五章 時(shí)

理三類時(shí)間間隔定時(shí)器的啟動(dòng)與處理方式如下:(1)實(shí)時(shí)定時(shí)器。在進(jìn)程創(chuàng)建時(shí),已設(shè)置了它的高精度

定時(shí)器real_timer,該定時(shí)器將采用相對時(shí)間定時(shí),其到期

處理函數(shù)是it_real_fn。在用戶進(jìn)程請求啟動(dòng)實(shí)時(shí)定時(shí)器時(shí),請求的時(shí)間間隔被記錄在進(jìn)程的it_real_incr中,定時(shí)器

real_timer被同時(shí)設(shè)置并啟動(dòng)。當(dāng)定時(shí)器到期時(shí),向進(jìn)程發(fā)

送信號SIGALRM。如果it_real_incr非0,則real_timer的到

期時(shí)間會被加上it_real_incr,該定時(shí)器也會被重新啟動(dòng)。1第五章 時(shí)

理(2)虛擬定時(shí)器。在進(jìn)程創(chuàng)建時(shí),虛擬定時(shí)器的當(dāng)前值與定時(shí)間隔都是0。在用戶進(jìn)程請求啟動(dòng)虛擬定時(shí)器時(shí),

it_virt_expires被設(shè)為初始定時(shí)間隔與進(jìn)程已消耗的用戶態(tài)時(shí)間之和,it_virt_incr被設(shè)為定時(shí)間隔。在時(shí)鐘中斷處理中,當(dāng)前進(jìn)程消耗的用戶態(tài)時(shí)間量被累計(jì)在utime中。如果utime大于或等于it_virt_expires,則向進(jìn)程發(fā)送信號SIGVTALRM。如果it_virt_incr為0,則將it_virt_expires清0,停止定時(shí),否則將it_virt_expires設(shè)為utime+it_virt_incr,重新啟動(dòng)定時(shí)器,如圖5.8所示。1第五章 時(shí)

理圖5.8周期性虛擬定時(shí)器1第五章 時(shí)

理(3)概略定時(shí)器。在進(jìn)程創(chuàng)建時(shí),概略定時(shí)器

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論