1.簡(jiǎn)介
隨著內(nèi)核不斷更新演進(jìn),內(nèi)核對(duì)定時(shí)器的分辨率要求越來(lái)越高。硬件的高速發(fā)展也逐漸能夠滿足內(nèi)核的這一要求,因此內(nèi)核針對(duì)硬件提供的便利,開始設(shè)計(jì)了更高分辨率的定時(shí)器(hrtimer),可達(dá)到ns級(jí)別。本文主要講解如何使用高精度定時(shí)器。
更多介紹詳見(jiàn)內(nèi)核文檔目錄kernel/Documentation/timers/hrtimers.txt
2.數(shù)據(jù)結(jié)構(gòu)
/**
* 定時(shí)器調(diào)用標(biāo)志位
*/
enum hrtimer_restart {
HRTIMER_NORESTART, /* Timer is not restarted */
HRTIMER_RESTART, /* Timer must be restarted */
};
/**
* struct hrtimer - 基本的hrtimer結(jié)構(gòu)
* @node: timerqueue節(jié)點(diǎn),
* @_softexpires:hrtimer的絕對(duì)最早到期時(shí)間。
* @function: 計(jì)時(shí)器到期回調(diào)函數(shù)
* @base: 指向計(jì)時(shí)器基礎(chǔ)的指針(每個(gè)cpu和每個(gè)時(shí)鐘)
* @state: 狀態(tài)信息(請(qǐng)參見(jiàn)上面的位值)
* @is_rel: 設(shè)置計(jì)時(shí)器
* @start_pid: 計(jì)時(shí)器統(tǒng)計(jì)信息字段,用于存儲(chǔ)任務(wù)的pid
* @start_site: 計(jì)時(shí)器統(tǒng)計(jì)信息字段,用于存儲(chǔ)計(jì)時(shí)器所在的站點(diǎn)
* @start_comm: 計(jì)時(shí)器統(tǒng)計(jì)信息字段,用于存儲(chǔ)其中的進(jìn)程名稱
*
* hrtimer結(jié)構(gòu)必須由hrtimer_init()初始化
*/
struct hrtimer {
struct timerqueue_node node;
ktime_t _softexpires;
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
u8 state;
u8 is_rel;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
};
3.使用流程
a.定義定時(shí)器結(jié)構(gòu)體變量
static struct hrtimer task1_timer;
b.初始化定時(shí)器任務(wù)
hrtimer_init(&task1_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
task1_timer.function = task1_timer_func;
c.實(shí)現(xiàn)定時(shí)器回調(diào)
static enum hrtimer_restart task1_timer_func(struct hrtimer *timer)
{
queue_work(test1_workqueue, &test1_item);
hrtimer_start(&task1_timer, ktime_set(2, 0), HRTIMER_MODE_REL); // 2s
return HRTIMER_NORESTART;
}
d.開啟定時(shí)器
hrtimer_cancel(&task1_timer);
/* ktime_set第一個(gè)參數(shù)為秒單位,第二個(gè)參數(shù)為納秒,定時(shí)時(shí)間0s + 900000000ns */
hrtimer_start(&task1_timer, ktime_set(0, 900000000), HRTIMER_MODE_REL);
4.注意事項(xiàng)
(1) 在需要調(diào)用開啟函數(shù)hrtimer_start,先調(diào)用hrtimer_cancel將定時(shí)器關(guān)閉。避免定時(shí)器被被開啟兩次,導(dǎo)致bug。
(2) 重復(fù)調(diào)用定時(shí)器可以在定時(shí)器回調(diào)函數(shù),返回值返回HRTIMER_RESTART。
也可以重新調(diào)用hrtimer_start,返回HRTIMER_NORESTART。
(3) 只需要重復(fù)執(zhí)行指定次數(shù),實(shí)現(xiàn)方法(舉其中一種):
int i = 0, num = 4;
static enum hrtimer_restart task1_timer_func(struct hrtimer *timer)
{
if(i < num) {
i++;
queue_work(test1_workqueue, &test1_item);
hrtimer_start(&task1_timer, ktime_set(0, 900000000), HRTIMER_MODE_REL); // 0.9s
} else {
i = 0;
}
return HRTIMER_NORESTART;
}
記錄歷經(jīng)的路,分享個(gè)人總結(jié)與感悟。關(guān)注“開源519”,聊天窗口發(fā)送 “hrtimer代碼” 獲取筆者本篇代碼實(shí)例,更多驅(qū)動(dòng)學(xué)習(xí)資料盡在“開源519”公眾號(hào)。
