Linux 高精度定時器hrtimer 使用示例【轉】


本文轉載自:http://blog.csdn.net/dean_gdp/article/details/25481225

hrtimer的基本操作

 

Linux的傳統定時器通過時間輪算法實現(timer.c),但hrtimer通過紅黑樹算法實現。在struct hrtimer里面有一個node域,類型為struct rb_node,這個域代表了hrtimer在紅黑樹中的位置。

hrtimer_start

hrtimer_start函數將一個hrtimer加入到一個按照到期時間排序的紅黑樹中,其主要流程為:

int hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode);

// 根據time和mode參數的值計算hrtimer的超時時間,並設置到timer->expire域。

// expire設置的是絕對時間,所以如果參數mode的值為HRTIMER_MODE_REL(即參數tim的值為相對時間),那么需要將tim的值修正為絕對時間:

// expire = tim + timer->base->get_time()。(注意本文只研究單CPU的情況)

//調用enqueue_hrtimer,將hrtimer加入到紅黑樹中。

 

hrtimer的到期

hrtimer在hrtimer_run_queues函數中判斷是否到期執行。hrtimer_run_queues的調用鏈為:linux的系統時鍾函數->update_process_times->run_local_timers->hrtimer_run_queues。

void hrtimer_run_queues(void)

// 判斷是否是高精度模式,如果是高精度模式,立即返回。本文暫不考慮這種情況。

// 對每一個時鍾源(REAL和MONOTONIC)的紅黑樹,按到期先后順序檢查hrtimer,看它們是否到期(將定時器與時鍾源的softirq_time比較)。如果到期,就把這個到期的定時器取出,然后按照定時器的具體模式執行相應的操作:

如果定時器模式為HRTIMER_CB_SOFTIRQ,那么將定時器搬到hrtimer_cpu_base的cb_pending隊列

調用__run_hrtimer,在__run_hrtimer中執行定時器的回調函數。

 

在沒有配置高精度模式時,cb_pending隊列中的定時器會在T_SOFTIRQ軟中斷中執行。調用鏈為

run_timer_softirq-> hrtimer_run_pending-> run_hrtimer_pending-> run_hrtimer_pending

 

hrtimer_cancel

hrtimer_cancel函數的作用是刪除一個正在排隊的定時器。這里分三種情況,一種是定時器已到期,並且設置了軟中斷模式;第二種是沒有到期,還在紅黑樹中;第三種是定時器正在執行。

l 第一種情況,定時器被掛在hrtimer_cpu_base的cb_pending隊列中,所以需要把它從pending隊列中移出。

l 第二種情況,定時器還在紅黑樹中,那么把它從紅黑樹中移出。由於本文暫時只考慮高精度沒有打開的情況,所以先不研究定時器正好排在紅黑樹第一個時的情況(即代碼中調用hrtimer_force_reprogram函數的部分)。

l 第三種情況刪除失敗,hrtimer_cancel函數會循環重試,等到定時器執行完的時候再刪除。(這在多CPU系統中可能會發生)

 

 

#include <linux/module.h>

#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/jiffies.h>




static struct hrtimer timer;
ktime_t kt;


static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
{
//kt = ktime_set(1, 10);
printk(" ------ I am in hrtimer -----\n");
hrtimer_forward(timer, timer->base->get_time(), kt);
return HRTIMER_RESTART;
}


static int __init test_init(void)
{


pr_info("timer resolution: %lu\n", TICK_NSEC);
kt = ktime_set(1, 10); /* 1 sec, 10 nsec */
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
//hrtimer_set_expires(&timer, kt);
hrtimer_start(&timer, kt, HRTIMER_MODE_REL);
timer.function = hrtimer_handler;


printk("\n-------- test start ---------\n");
return 0;
}


static void __exit test_exit(void)
{
hrtimer_cancel(&timer);
printk("-------- test over ----------\n");
return;
}


MODULE_LICENSE("GPL");


module_init(test_init);

module_exit(test_exit);

 

轉載地址:http://blog.chinaunix.NET/uid-361890-id-257337.html

http://blog.csdn.net/walkingman321/article/details/6133171


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM