當前位置:首頁 » 操作系統 » 定時器linux

定時器linux

發布時間: 2024-01-04 08:19:46

1. linux下的幾種時鍾和定時器機制

1. RTC(Real Time Clock)

所有PC都有RTC. 它和CPU和其他晶元獨立。它在電腦關機之後還可以正常運行。RTC可以在IRQ8上產生周期性中斷. 頻率在2Hz--8192HZ.

Linux只是把RTC用來獲取時間和日期. 當然它允許進程通過對/dev/rtc設備來對它進行編程。Kernel通過0x70和0x71 I/O埠來訪問RTC。

 

2. TSC(Time Stamp Counter)

80x86上的微處理器都有CLK輸入針腳. 從奔騰系列開始. 微處理器支持一個計數器. 每當一個時鍾信號來的時候. 計數器加1. 可以通過匯編指令rdtsc來得到計數器的值。通過calibrate_tsc可以獲得CPU的頻率. 它是通過計算大約5毫秒里tsc寄存器裡面的增加值來確認的。或者可以通過cat /proc/cpuinfo來獲取cpu頻率。tsc可以提供比PIT更精確的時間度量。

 

3. PIT(Programmable internval timer)

除了RTC和TSC. IBM兼容機提供了PIT。PIT類似微波爐的鬧鍾機制. 當時間到的時候. 提供鈴聲. PIT不是產生鈴聲. 而是產生一種特殊中斷. 叫定時器中斷或者時鍾中斷。它用來告訴內核一個間隔過去了。這個時間間隔也叫做一個滴答數。可以通過編譯內核是選擇內核頻率來確定。如內核頻率設為1000HZ,則時間間隔或滴答為1/1000=1微秒。滴答月短. 定時精度更高. 但是用戶模式的時間更短. 也就是說用戶模式下程序執行會越慢。滴答的長度以納秒形式存在tick_nsec變數裡面。PIT通過8254的0x40--0x43埠來訪問。它產生中斷號為IRQ 0.

下面是關於pIT裡面的一些宏定義:

HZ:每秒中斷數。

CLOCK_TICK_RATE:值是1,193,182. 它是8254晶元內部振盪器頻率。

LATCH:代表CLOCK_TICK_RATE和HZ的比率. 被用來編程PIT。

setup_pit_timer()如下:

spin_lock_irqsave(&i8253_lock, flags);

outb_p(0x34,0x43);

udelay(10);

outb_p(LATCH & 0xff, 0x40);

udelay(10);

outb (LATCH >> 8, 0x40);

spin_unlock_irqrestore(&i8253_lock, flags);

 

 

4. CPU Local Timer

最近的80x86架構的微處理器上的local apic提供了cpu local timer.他和pit區別在於它提供了one-shot和periodic中斷。它可以使中斷發送到特定cpu。one-shot中斷常用在實時系統裡面。

2. 有沒有辦法可以獲取linux開發板的硬體定時器頻率

1、默認情況下系統節拍率選擇100Hz。
2、設置好後在Linux內核源碼根目錄下的config文件中可見系統節拍率被設置為100Hz。
3、Linux內核會使用CONFIGHZ來設置自己的系統時鍾,文件includeasmgenericparamh。
4、Linux內核使用全局變數jiffies來記錄系統從啟動以來的系統節拍數,系統啟動的時候會將jiffies初始化為0,即可獲取,linux開發板的硬體定時器頻率。

3. linux 時鍾中斷 哪個定時器

一. Linux的硬體時間
PC機中的時間有三種硬體時鍾實現,這三種都是基於晶振產生的方波信號輸入。這三種時鍾為:(1)實時時鍾RTC ( Real Time Clock) (2)可編程間隔器PIT(Programmable Interval Timer )(3)時間戳計數器TSC(Time Stamp Clock)
1. 實時時鍾 RTC
用於長時間存放系統時間的設備,即時關機後也可依靠主板CMOS電池繼續保持系統的計時,原理圖如下:

Note: Linux與RTC的關系是,當Linux啟動時從RTC讀取時間和日期的基準值,然後在Kernel運行期間便拋開RTC,以軟體的形式維護系統的時間日期,並在適當時機由Kernel將時間寫回RTC Register.
1.1 RTC Register
(1). 時鍾與日歷Register
共10個,地址:0x00-0x09,分別用於保存時間日歷的具體信息,詳情如下:
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(1=Sunday)
07 Current Date of Month
08 Current Month
09 Current Year
(2).狀態和控制Register
共四個,地址:0x0a-0x0d,控制RTC晶元的工作方式,並表示當前狀態。
l 狀態RegisterA , 0x0A 格式如下:
bit[7]——UIP標志(Update in Progress),為1表示RTC正在更新日歷寄存器組中的值,此時日歷寄存器組是不可訪問的(此時訪問它們將得到一個無意義的漸變值)。
bit[6:4]——這三位是用來定義RTC的操作頻率。各種可能的值如下:

DV2 DV1 DV0
0 0 0 4.194304 MHZ
0 0 1 1.048576 MHZ
0 1 0 32.769 KHZ
1 1 0/1 任何
PC機通常設置成「010」。
bit[3:0]——速率選擇位(Rate Selection bits),用於周期性或方波信號輸出。
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」
l 狀態Register B , 0x0B 格式如下:
bit[7]——SET標志。為1表示RTC的所有更新過程都將終止,用戶程序隨後馬上對日歷寄存器組中的值進行初始化設置。為0表示將允許更新過程繼續。
bit[6]——PIE標志,周期性中斷enable標志。
bit[5]——AIE標志,告警中斷enable標志。
bit[4]——UIE標志,更新結束中斷enable標志。
bit[3]——SQWE標志,方波信號enable標志。
bit[2]——DM標志,用來控制日歷寄存器組的數據模式,0=BCD,1=BINARY。BIOS總是將它設置為0。
bit[1]——24/12標志,用來控制hour寄存器,0表示12小時制,1表示24小時制。PC機BIOS總是將它設置為1。
bit[0]——DSE標志。BIOS總是將它設置為0。
l 狀態Register C,0x0C 格式如下:
bit[7]——IRQF標志,中斷請求標志,當該位為1時,說明寄存器B中斷請求 發生。
bit[6]——PF標志,周期性中斷標志,為1表示發生周期性中斷請求。
bit[5]——AF標志,告警中斷標志,為1表示發生告警中斷請求。
bit[4]——UF標志,更新結束中斷標志,為1表示發生更新結束中斷請求。
l 狀態Register D,0x0D 格式如下:
bit[7]——VRT標志(Valid RAM and Time),為1表示OK,為0表示RTC 已經掉電。
bit[6:0]——總是為0,未定義。
2.可編程間隔定時器 PIT
每個PC機中都有一個PIT,以通過IRQ0產生周期性的時鍾中斷信號,作為系統定時器 system timer。當前使用最普遍的是Intel 8254 PIT晶元,它的I/O埠地址是0x40~0x43。
Intel 8254 PIT有3個計時通道,每個通道都有其不同的用途:
(1) 通道0用來負責更新系統時鍾。每當一個時鍾滴答過去時,它就會通過IRQ0向 系統 產生一次時鍾中斷。
(2) 通道1通常用於控制DMAC對RAM的刷新。
(3) 通道2被連接到PC機的揚聲器,以產生方波信號。
每 個通道都有一個向下減小的計數器,8254 PIT的輸入時鍾信號的頻率是1.193181MHZ,也即一秒鍾輸入1193181個clock-cycle。每輸入一個clock-cycle其時間 通道的計數器就向下減1,一直減到0值。因此對於通道0而言,當他的計數器減到0時,PIT就向系統產生一次時鍾中斷,表示一個時鍾滴答已經過去了。計數 器為16bit,因此所能表示的最大值是65536,一秒內發生的滴答數是:1193181/65536=18.206482.
PIT的I/O埠:
0x40 通道0 計數器 Read/Write
0X41 通道1計數器 Read/Write
0X42 通道2計數器 Read/Write
0X43 控制字 Write Only
Note: 因PIT I/O埠是8位,而PIT相應計數器是16位,因此必須對PIT計數器進行兩次讀寫。
8254 PIT的控制寄存器(0X43)的格式如下:
bit[7:6] — 通道選擇位:00 ,通道0;01,通道1;10,通道2;11,read-back command,僅8254。
bit[5:4] – Read/Write/Latch鎖定位,00,鎖定當前計數器以便讀取計數值;01,只讀高位元組;10,只讀低位元組;11,先高後低。
bit[3:1] – 設定各通道的工作模式。
000 mode0 當通道處於count out 時產生中斷信號,可用於系統定時
001 mode1 Hardware retriggerable one-shot
010 mode2 Rate Generator。產生實時時鍾中斷,通道0通常工作在這個模式下
011 mode3 方波信號發生器
100 mode4 Software triggered strobe
101 mode5 Hardware triggered strobe
3. 時間戳計數器 TSC
從Pentium開始,所有的Intel 80x86 CPU就都包含一個64位的時間戳記數器(TSC)的寄存器。該寄存器實際上是一個不斷增加的計數器,它在CPU的每個時鍾信號到來時加1(也即每一個clock-cycle輸入CPU時,該計數器的值就加1)。
匯編指令rdtsc可以用於讀取TSC的值。利用CPU的TSC,操作系統通常可以得到更為精準的時間度量。假如clock-cycle的頻率是400MHZ,那麼TSC就將每2.5納秒增加一次。
二. Linux時鍾中斷處理程序
1. 幾個概念
(1)時鍾周期(clock cycle)的頻率:8253/8254 PIT的本質就是對由晶體振盪器產生的時鍾周期進行計數,晶體振盪器在1秒時間內產生的時鍾脈沖個數就是時鍾周期的頻率。Linux用宏 CLOCK_TICK_RATE來表示8254 PIT的輸入時鍾脈沖的頻率(在PC機中這個值通常是1193180HZ),該宏定義在include/asm-i386/timex.h頭文件中
#define CLOCK_TICK_RATE 1193180 kernel=2.4 &2.6

(2)時鍾滴答(clock tick):當PIT通道0的計數器減到0值時,它就在IRQ0上產生一次時鍾中斷,也即一次時鍾滴答。PIT通道0的計數器的初始值決定了要過多少時鍾周期才產生一次時鍾中斷,因此也就決定了一次時鍾滴答的時間間隔長度。
(3)時鍾滴答的頻率(HZ):1秒時間內PIT所產生的時鍾滴答次數。 這個值也由PIT通道0的計數器初值決定的.Linux內核用宏HZ來表示時鍾滴答的頻率,而且在不同的平台上HZ有不同的定義值。對於ALPHA和 IA62平台HZ的值是1024,對於SPARC、MIPS、ARM和i386等平台HZ的值都是100。該宏在i386平台上的定義如下 (include/asm-i386/param.h):
#define HZ 100 kernel=2.4
#define HZ CONFIG_HZ kernel=2.6

(4)宏LATCH:定義要寫到PIT通道0的計數器中的值,它表示PIT將隔多少個時鍾周期產生一次時鍾中斷。公式計算:
LATCH=(1秒之內的時鍾周期個數)÷(1秒之內的時鍾中斷次數)=(CLOCK_TICK_RATE)÷(HZ)
定義在<include/linux/timex.h>
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)
(5)全局變數jiffies:用於記錄系統自啟動以來產生的滴答總數。啟動時,kernel將該變數初始為0,每次時鍾中斷處理程序timer_interrupt()將該變數加1。因為一秒鍾內增加的時鍾中斷次數等於Hz,所以jiffies一秒內增加的值也是Hz。由此可得系統運行時間是jiffies/Hz 秒。
jiffies定義於<linux/jiffies.h>中:
extern unsigned long volatile jiffies;
Note:在kernel 2.4,jiffies是32位無符號數;kernel 2.6,jiffies是64位無符號數。
(6)全局變數xtime: 結構類型變數,用於表示當前時間距UNIX基準時間1970-01-01 00:00:00的相對秒數值。當系統啟動時,Kernel通過讀取RTC Register中的數據來初始化系統時間(wall_time),該時間存放在xtime中。
void __init time_init (void) {
... ...
xtime.tv_sec = get_cmos_time ();
xtime.tv_usec = 0;
... ... }
Note:實時時鍾RTC的最主要作用便是在系統啟動時用來初始化xtime變數。
2.Linux的時鍾中斷處理程序
Linux下時鍾中斷處理由time_interrupt() 函數實現,主要完成以下任務:
l 獲得xtime_lock鎖,以便對訪問的jiffies_64 (kernel2.6)和 xtime進行保護
l 需要時應答或重新設置系統時鍾。
l 周期性的使用系統時間(wall_time)更新實時時鍾RTC
l 調用體系結構無關的時鍾常式:do_timer()。
do_timer()主要完成以下任務:
l 更新jiffies;
l 更新系統時間(wall_time),該時間存放在xtime變數中
l 執行已經到期的動態定時器
l 計算平均負載值
void do_timer(unsigned long ticks)
{
jiffies_64 += ticks;
update_process_times(user_mode(regs));
update_times (ticks);
}
static inline void update_times(unsigned long ticks)
{
update_wall_time ();
calc_load (ticks);
}
time_interrupt ():

static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
int count;
write_lock (&xtime_lock); //獲得xtime_lock鎖

if(use_cyclone)
mark_timeoffset_cyclone();
else if (use_tsc) {
rdtscl(last_tsc_low); //讀TSC register到last_tsc_low
spin_lock (&i8253_lock); //對自旋鎖i8253_lock加鎖,對8254PIT訪問
outb_p (0x00, 0x43);

count = inb_p(0x40);
count |= inb(0x40) << 8;
if (count > LATCH) {
printk (KERN_WARNING "i8253 count too high! resetting../n");
outb_p (0x34, 0x43);
outb_p (LATCH & 0xff, 0x40);
outb(LATCH >> 8, 0x40);
count = LATCH - 1;
}
spin_unlock (&i8253_lock);

if (count = = LATCH) {
count- -;
}

count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
} //end use_tsc
do_timer_interrupt (irq, NULL, regs);
write_unlock(&xtime_lock);
}//end time_interrupt

do_timer_interrupt():
static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
……
do_timer(regs);
if((time_status & STA_UNSYNC)= =0&&xtime.tv_sec> last_rtc_update + 660 && xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600;
……
}
do_timer_interrupt()主要完成:調用do_timer()和判斷是否需要更新CMOS時鍾。更新CMOS時鍾的條件如下:三個須同時成立
1.系統全局時間狀態變數time_status中沒有設置STA_UNSYNC標志,即Linux沒有設置外部同步時鍾(如NTP)
2.自從上次CMOS時鍾更新已經過去11分鍾。全局變數last_rtc_update保存上次更新CMOS時鍾的時間.
3.由於RTC存在Update Cycle,因此應在一秒鍾間隔的中間500ms左右調用set_rtc_mmss()函數,將當前時間xtime.tv_sec寫回RTC中。
Note. Linux kernel 中定義了一個類似jiffies的變數wall_jiffies,用於記錄kernel上一次更新xtime時,jiffies的值。

Summary: Linux kernel在啟動時,通過讀取RTC里的時間日期初始化xtime,此後由kernel通過初始PIT來提供軟時鍾。
時鍾中斷處理過程可歸納為:系統時鍾system timer在IRQ0上產生中斷;kernel調用time_interrupt();time_interrupt()判斷系統是否使用TSC,若使用 則讀取TSC register;然後讀取PIT 通道0的計數值;調用do_time_interrupt(),實現系統時間更新.

4. linux定時器周期設置多少

linux定時器周期設置60分鍾。根據查詢相關資料信息:linux鍵入crontab-e編沒高輯crontab服消察叢務文件即可設置定時器拿櫻周期。

熱點內容
安卓手機如何打開xp文件 發布:2024-11-29 08:27:46 瀏覽:949
戰歌腳本第二集 發布:2024-11-29 08:22:42 瀏覽:890
緩存清理是什麼意思 發布:2024-11-29 08:14:39 瀏覽:675
cvm伺服器搭建博客 發布:2024-11-29 08:03:42 瀏覽:889
魅族手機軟體怎麼加密 發布:2024-11-29 07:50:04 瀏覽:215
阿里雲伺服器託管合同 發布:2024-11-29 07:46:37 瀏覽:297
linux用戶許可權設置 發布:2024-11-29 07:43:39 瀏覽:271
c語言if函數嵌套 發布:2024-11-29 07:43:35 瀏覽:758
學編程L2 發布:2024-11-29 07:39:58 瀏覽:430
微信如何設置收與付密碼 發布:2024-11-29 07:39:15 瀏覽:542