萬盛學電腦網

 萬盛學電腦網 >> Linux教程 >> Linux操作系統內核的時鐘中斷機制

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

class="21448">

  摘要:

  本文主要從內核實現的角度分析了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,控

copyright © 萬盛學電腦網 all rights reserved