L13. hrtimer使用實(shí)例(高精度定時(shí)器)

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)。

開源519.jpg

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容