linux從內(nèi)核2.6.16開始引入了高精度定時(shí)器,達(dá)到ns級(jí)別。自此,內(nèi)核擁有兩套并行計(jì)時(shí)器,低精度和高精度。如果高精度沒有開啟,即使使用高精度函數(shù),默認(rèn)使用的仍舊是低精度。
高精度:?
雖然內(nèi)核已經(jīng)支持高精度,但是對(duì)于不少產(chǎn)品而言,由于內(nèi)核是裁剪的,配置的時(shí)候并沒有加入編譯進(jìn)去,雖然對(duì)應(yīng)的內(nèi)核源碼中有相關(guān)代碼。如果想支持,那么可以進(jìn)入內(nèi)核源碼,執(zhí)行make menuconfig。去查看當(dāng)前系統(tǒng)是否支持高精度,(備注:因?yàn)槔锩孢x項(xiàng)比較多,還可以直接去查看編譯好的.config文件,看里面是否有CONFIG_HIGH_RES_TIMERS,如果有,就通過make menuconfig開啟,沒有的話,就是不支持),是否真正啟用,可以在內(nèi)核中對(duì)相應(yīng)宏進(jìn)行打印。
低精度:?
(定時(shí)精度和頻率HZ相關(guān),精度為(1000/HZ ) ms)
#include ?
void do_gettimeofday(struct timeval *tv);//獲取精確時(shí)間函數(shù)?
//內(nèi)核相關(guān)定義
struct timeval {?
time_t tv_sec;? ? ? ?/* seconds */
suseconds_t tv_usec; /* microseconds */?
};
#define TIMER_TOTAL_NUM? 2? ?//定義定時(shí)器總數(shù)
struct? timeval? ?tv;
struct? timer_list? funTimer[TIMER_TOTAL_NUM ]; //定義定時(shí)器相關(guān)結(jié)構(gòu)體數(shù)組
short int siTimeInitFlag[TIMER_TOTAL_NUM? ]; //定時(shí)器初始化標(biāo)志
short int siTimeoutFlag[TIMER_TOTAL_NUM? ];//定時(shí)器啟動(dòng)標(biāo)志
typedef void (*pfTimerFunction)(unsigned long ulData);? //定義定時(shí)器處理函數(shù)指針,方便處理多個(gè)定時(shí)器
//定時(shí)器初始化
void timer_init(int iIndex, int iMs, pfTimerFunction pTimerFunction)?
{
init_timer(&funTimer[iIndex]);//初始化
funTimer[iIndex].function = pTimerFunction;//處理函數(shù)
funTimer[iIndex].data = (unsigned long)iMs;//參數(shù)傳遞,在處理函數(shù)中可以不使用
funTimer[iIndex].expires = jiffies + HZ; //定時(shí)時(shí)長(zhǎng)設(shè)置為1s
add_timer(&funTimer[iIndex]);//開啟定時(shí)器
siTimeInitFlag[iIndex] = 1;//初始標(biāo)志置為1
siTimeoutFlag[iIndex] = 1;//定時(shí)器啟動(dòng)標(biāo)志
}
//定時(shí)器處理函數(shù)
static void timer_function(unsigned long ulData)
{
/*
這里寫自己需要執(zhí)行的功能.........
.................
//定時(shí)是否準(zhǔn)確測(cè)試
do_gettimeofday(&tv);//獲取時(shí)間
printk("time------%d:%d\n", tv.tv_sec, tv.tv_usec);//查看間隔,看定時(shí)時(shí)間是否精準(zhǔn)
*/
//循環(huán)定時(shí)器實(shí)現(xiàn),如果不實(shí)現(xiàn)循環(huán),可執(zhí)行自己要實(shí)現(xiàn)的,再進(jìn)行定時(shí)器刪除,也可以不刪除,到時(shí)后自動(dòng)刪除
if(1 == siTimeoutFlag[0])
{
del_timer_sync(&funTimer[0]);//用del_timer_sync代替了del_timer
}
funTimer[0].function = timer_function;
funTimer[0].expires = jiffies + HZ;//重新設(shè)置定時(shí)時(shí)間
add_timer(&funTimer[0]);//啟動(dòng)定時(shí)器
siTimeoutFlag[0] = 1;
}
//簡(jiǎn)單例子調(diào)用
int main(void)
{
timer_init(0, 3, timer_function);
return 0;
}
使用注意:?
1、加入初始化標(biāo)志siTimeInitFlag[iIndex] 是防止定時(shí)器在運(yùn)行時(shí),再次初始化,這樣會(huì)導(dǎo)致內(nèi)核崩潰;?
2、使用循環(huán)定時(shí)器時(shí), funTimer[0].expires = jiffies + HZ; funTimer的成員expires 必須重新賦值,且要執(zhí)行 ,?
add_timer(&funTimer[0]);?
3、定時(shí)時(shí)長(zhǎng)funTimer[iIndex].expires = jiffies + HZ; //宏定義HZ可以查看源碼,或者打印出來,jiffies 為節(jié)拍數(shù),系統(tǒng)最高?
精度為(1000/HZ)ms。?
jiffies + HZ————-設(shè)置定時(shí)時(shí)長(zhǎng)為1s;?
jiffies + 1—————設(shè)置定時(shí)時(shí)長(zhǎng)為(1000/HZ)ms,是系統(tǒng)最高精度?
4、內(nèi)核添加printk后,由于打印函數(shù)耗時(shí),會(huì)導(dǎo)致執(zhí)行時(shí)間延長(zhǎng),一個(gè)打印延長(zhǎng)一般為ms級(jí)別
?
評(píng)論
查看更多