歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

Linux操作系統內核的時鐘中斷機制

  摘要:

  本文主要從內核實現的角度分析了Linux 2.4.0內核的時鐘中斷、內核對時間的表示等。本文是為那些想要了解Linux I/O子系統的讀者和Linux驅動程序開發人員而寫的。


  關鍵詞:Linux、時鐘、定時器
  申明:這份文檔是按照自由軟件開放源代碼的精神發布的,任何人可以免費獲得、使用和重新發布,但是你沒有限制別人重新發布你發布內容的權利。發布本文的目的是希望它能對讀者有用,但沒有任何擔保,甚至沒有適合特定目的的隱含的擔保。更詳細的情況請參閱GNU通用公共許可證(GPL),以及GNU自由文檔協議(GFDL)。

  你應該已經和文檔一起收到一份GNU通用公共許可證(GPL)的副本。如果還沒有,寫信給:The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,MA02139, USA 歡迎各位指出文檔中的錯誤與疑問。

  前言

  時間在一個操作系統內核中占據著重要的地位,它是驅動一個OS內核運行的“起博器”。一般說來,內核主要需要兩種類型的時間:

  1. 在內核運行期間持續記錄當前的時間與日期,以便內核對某些對象和事件作時間標記(timestamp,也稱為“時間戳”),或供用戶通過時間syscall進行檢索。

  2. 維持一個固定周期的定時器,以提醒內核或用戶一段時間已經過去了。

  PC機中的時間是有三種時鐘硬件提供的,而這些時鐘硬件又都基於固定頻率的晶體振蕩器來提供時鐘方波信號輸入。這三種時鐘硬件是:(1)實時時鐘(Real Time Clock,RTC);(2)可編程間隔定時器(Programmable Interval Timer,PIT);(3)時間戳計數器(Time Stamp Counter,TSC)。

  時鐘硬件

  1、實時時鐘RTC

  自從IBM PC AT起,所有的PC機就都包含了一個叫做實時時鐘(RTC)的時鐘芯片,以便在PC機斷電後仍然能夠繼續保持時間。顯然,RTC是通過主板上的電池來供電的,而不是通過PC機電源來供電的,因此當PC機關掉電源後,RTC仍然會繼續工作。通常,CMOS RAM和RTC被集成到一塊芯片上,因此RTC也稱作“CMOS Timer”。最常見的RTC芯片是MC146818(Motorola)和DS12887(maxim),DS12887完全兼容於MC146818,並有一定的擴展。本節內容主要基於MC146818這一標准的RTC芯片。具體內容可以參考MC146818的Datasheet。

  1.1 RTC寄存器

  MC146818 RTC芯片一共有64個寄存器。它們的芯片內部地址編號為0x00~0x3F(不是I/O端口地址),這些寄存器一共可以分為三組:

  (1)時鐘與日歷寄存器組:共有10個(0x00~0x09),表示時間、日歷的具體信息。在PC機中,這些寄存器中的值都是以BCD格式來存儲的(比如23dec=0x23BCD)。

  (2)狀態和控制寄存器組:共有4個(0x0A~0x0D),控制RTC芯片的工作方式,並表示當前的狀態。

  (3)CMOS配置數據:通用的CMOS RAM,它們與時間無關,因此我們不關心它。

  時鐘與日歷寄存器組的詳細解釋如下:


Address Function 
00 Current second for RTC 
01 Alarm second 
02 Current minute 
03 Alarm minute 
04 Current hour 
05 Alarm hour 
06 Current day of week(01=Sunday) 
07 Current date of month 
08 Current month 
09 Current year(final two digits,eg:93)

  狀態寄存器A(地址0x0A)的格式如下:
  其中:

  (1)bit[7]——UIP標志(Update in Progress),為1表示RTC正在更新日歷寄存器組中的值,此時日歷寄存器組是不可訪問的(此時訪問它們將得到一個無意義的漸變值)。

  (2)bit[6:4]——這三位是“除法器控制位”(divider-control bits),用來定義RTC的操作頻率。各種可能的值如下:





Divider bits Time-base frequency Divider Reset Operation Mode 
DV2 DV1 DV0 
0 0 0 4.194304 MHZ NO YES 
0 0 1 1.048576 MHZ NO YES 
0 1 0 32.769 KHZ NO YES 
1 1 0/1 任何 YES NO

  PC機通常將Divider bits設置成“010”。

  (3)bit[3:0]——速率選擇位(Rate Selection bits),用於周期性或方波信號輸出。

  RS bits 4.194304或1.048578 MHZ 32.768 KHZ

  RS3 RS2 RS1 RS0 周期性中斷 方波 周期性中斷 方波


0 0 0 0 None None None None 
0 0 0 1 30.517μs 32.768 KHZ 3.90625ms 256 HZ 
0 0 1 0 61.035μs 16.384 KHZ 
0 0 1 1 122.070μs 8.192KHZ 
0 1 0 0 244.141μs 4.096KHZ 
0 1 0 1 488.281μs 2.048KHZ 
0 1 1 0 976.562μs 1.024KHZ 
0 1 1 1 1.953125ms 512HZ 
1 0 0 0 3.90625ms 256HZ 
1 0 0 1 7.8125ms 128HZ 
1 0 1 0 15.625ms 64HZ 
1 0 1 1 31.25ms 32HZ 
1 1 0 0 62.5ms 16HZ 
1 1 0 1 125ms 8HZ 
1 1 1 0 250ms 4HZ 
1 1 1 1 500ms 2HZ

  PC機BIOS對其默認的設置值是“0110”。

  狀態寄存器B的格式如下所示:

  各位的含義如下:

  (1)bit[7]——SET標志。為1表示RTC的所有更新過程都將終止,用戶程序隨後馬上對日歷寄存器組中的值進行初始化設置。為0表示將允許更新過程繼續。

  (2)bit[6]——PIE標志,周期性中斷使能標志。

  (3)bit[5]——AIE標志,告警中斷使能標志。

  (4)bit[4]——UIE標志,更新結束中斷使能標志。

  (5)bit[3]——SQWE標志,方波信號使能標志。

  (6)bit[2]——DM標志,用來控制日歷寄存器組的數據模式,0=BCD,1=BINARY。BIOS總是將它設置為0。

  (7)bit[1]——24/12標志,用來控制hour寄存器,0表示12小時制,1表示24小時制。PC機BIOS總是將它設置為1。

  (8)bit[0]——DSE標志。BIOS總是將它設置為0。

  狀態寄存器C的格式如下:

  (1)bit[7]——IRQF標志,中斷請求標志,當該位為1時,說明寄存器B中斷請求發生。

  (2)bit[6]——PF標志,周期性中斷標志,為1表示發生周期性中斷請求。

  (3)bit[5]——AF標志,告警中斷標志,為1表示發生告警中斷請求。

  (4)bit[4]——UF標志,更新結束中斷標志,為1表示發生更新結束中斷請求。

  狀態寄存器D的格式如下:

  (1)bit[7]——VRT標志(Valid RAM and Time),為1表示OK,為0表示RTC已經掉電。

  (2)bit[6:0]——總是為0,未定義。

  1.2 通過I/O端口訪問RTC

  在PC機中可以通過I/O端口0x70和0x71來讀寫RTC芯片中的寄存器。其中,端口0x70是RTC的寄存器地址索引端口,0x71是數據端口。

  讀RTC芯片寄存器的步驟是:


mov al, addr 
out 70h, al ; Select reg_addr in RTC chip 
jmp $+2 ; a slight delay to settle thing 
in al, 71h ;

  寫RTC寄存器的步驟如下:


mov al, addr 
out 70h, al ; Select reg_addr in RTC chip 
jmp $+2 ; a slight delay to settle thing 
mov al, value 
out 71h, al

  1.3 可編程間隔定時器PIT
  每個PC機中都有一個PIT,以通過IRQ0產生周期性的時鐘中斷信號。當前使用最普遍的是Intel 8254 PIT芯片,它的I/O端口地址是0x40~0x43。

  Intel 8254 PIT有3個計時通道,每個通道都有其不同的用途:

  (1) 通道0用來負責更新系統時鐘。每當一個時鐘滴答過去時,它就會通過IRQ0向系統產生一次時鐘中斷。

  (2) 通道1通常用於控制DMAC對RAM的刷新。

  (3) 通道2被連接到PC機的揚聲器,以產生方波信號。

  每個通道都有一個向下減小的計數器,8254 PIT的輸入時鐘信號的頻率是1193181HZ,也即一秒鐘輸入1193181個clock-cycle。每輸入一個clock-cycle其時間通道的計數器就向下減1,一直減到0值。因此對於通道0而言,當他的計數器減到0時,PIT就向系統產生一次時鐘中斷,表示一個時鐘滴答已經過去了。當各通道的計數器減到0時,我們就說該通道處於“Terminal count”狀態。

  通道計數器的最大值是10000h,所對應的時鐘中斷頻率是1193181/(65536)=18.2HZ,也就是說,此時一秒鐘之內將產生18.2次時鐘中斷。

  2、 PIT的I/O端口

  在i386平台上,8254芯片的各寄存器的I/O端口地址如下:




Port Description 
40h Channel 0 counter(read/write) 
41h Channel 1 counter(read/write) 
42h Channel 2 counter(read/write) 
43h PIT control Word(write only)

  其中,由於通道0、1、2的計數器是一個16位寄存器,而相應的端口卻都是8位的,因此讀寫通道計數器必須進行進行兩次I/O端口讀寫操作,分別對應於計數器的高字節和低字節,至於是先讀寫高字節再讀寫低字節,還是先讀寫低字節再讀寫高字節,則由PIT的控制寄存器來決定。8254 PIT的控制寄存器的格式如下:

  (1)bit[7:6]——Select Counter,選擇對那個計數器進行操作。“00”表示選擇Counter 0,“01”表示選擇Counter 1,“10”表示選擇Counter 2,“11”表示Read-Back Command(僅對於8254,對於8253無效)。

  (2)bit[5:4]——Read/Write/Latch格式位。“00”表示鎖存(Latch)當前計數器的值;“01”只讀寫計數器的高字節(MSB);“10”只讀寫計數器的低字節(LSB);“11”表示先讀寫計數器的LSB,再讀寫MSB。

  (3)bit[3:1]——Mode bits,控制各通道的工作模式。“000”對應Mode 0;“001”對應Mode 1;“010”對應Mode 2;“011”對應Mode 3;“100”對應Mode 4;“101”對應Mode 5。

  (4)bit[0]——控制計數器的存儲模式。0表示以二進制格式存儲,1表示計數器中的值以BCD格式存儲。

  2.1 PIT通道的工作模式

  PIT各通道可以工作在下列6種模式下:

  1. Mode 0:當通道處於“Terminal count”狀態時產生中斷信號。

  2. Mode 1:Hardware retriggerable one-shot。

  3. Mode 2:Rate Generator。這種模式典型地被用來產生實時時鐘中斷。此時通道的信號輸出管腳OUT初始時被設置為高電平,並以此持續到計數器的值減到1。然後在接下來的這個clock-cycle期間,OUT管腳將變為低電平,直到計數器的值減到0。當計數器的值被自動地重新加載後,OUT管腳又變成高電平,然後重復上述過程。通道0通常工作在這個模式下。

  4. Mode 3:方波信號發生器。

  5. Mode 4:Software triggered strobe。

  6. Mode 5:Hardware triggered strobe。

  2.2 鎖存計數器(Latch Counter)

  當控制寄存器中的bit[5:4]設置成0時,將把當前通道的計數器值鎖存。此時通過I/O端口可以讀到一個穩定的計數器值,因為計數器表面上已經停止向下計數(PIT芯片內部並沒有停止向下計數)。NOTE!一旦發出了鎖存命令,就要馬上讀計數器的值。

  2.3 時間戳記數器TSC

  從Pentium開始,所有的Intel 80x86 CPU就都又包含一個64位的時間戳記數器(TSC)的寄存器。該寄存器實際上是一個不斷增加的計數器,它在CPU的每個時鐘信號到來時加1(也即每一個clock-cycle輸入CPU時,該計數器的值就加1)。

  匯編指令rdtsc可以用於讀取TSC的值。利用CPU的TSC,操作系統通常可以得到更為精准的時間度量。假如clock-cycle的頻率是400MHZ,那麼TSC就將每2.5納秒增加一次。



  匯編指令rdtsc可以用於讀取TSC的值。利用CPU的TSC,操作系統通常可以得到更為精准的時間度量。假如clock-cycle的頻率是400MHZ,那麼TSC就將每2.5納秒增加一次。



Copyright © Linux教程網 All Rights Reserved