linux 內核筆記之時間管理(三) : 高精度timer

低精度定時器基於時間輪算法,與jiffies關係緊密,精度爲ms級,應用場景一般爲“超時”退出。
因此,對於精度要求較高的驅動或應用場景,內核重新設計了一套軟件架構,它可以提供納秒級的定時精度,基於紅黑樹實現。

hrtimer的結構

與普通timer類似,每一個CPU也維護一個hrtimer的結構hrtimer_cpu_base,

struct hrtimer_cpu_base {
    raw_spinlock_t          lock;
    seqcount_t          seq;
    struct hrtimer          *running;
    unsigned int            cpu;
    unsigned int            active_bases;
    unsigned int            clock_was_set_seq;
    bool                migration_enabled;
    bool                nohz_active;
#ifdef CONFIG_HIGH_RES_TIMERS   //高精度配置
    unsigned int            in_hrtirq   : 1,
                    hres_active : 1,
                    hang_detected   : 1;
    ktime_t             expires_next;  //定時器的到期時間
    struct hrtimer          *next_timer;
    unsigned int            nr_events;
    unsigned int            nr_retries;
    unsigned int            nr_hangs;
    unsigned int            max_hang_time;
#endif
    struct hrtimer_clock_base   clock_base[HRTIMER_MAX_CLOCK_BASES]; //時鐘源
} ____cacheline_aligned;

其中hrtimer的結構,

struct hrtimer {
    struct timerqueue_node      node;
    ktime_t             _softexpires; //到期時間
    enum hrtimer_restart        (*function)(struct hrtimer *);
    struct hrtimer_clock_base   *base;   //時鐘源
    u8              state;     //hrtimer當前狀態
    u8              is_rel;
#ifdef CONFIG_TIMER_STATS
    int             start_pid;
    void                *start_site;
    char                start_comm[16];
#endif
};

hrimer的有以下幾種狀態,

enum  hrtimer_base_type {  
    HRTIMER_BASE_MONOTONIC,  // 單調遞增的monotonic時間,不包含休眠時間  
    HRTIMER_BASE_REALTIME,   // 平常使用的牆上真實時間  
    HRTIMER_BASE_BOOTTIME,   // 單調遞增的boottime,包含休眠時間  
    HRTIMER_MAX_CLOCK_BASES, // 用於後續數組的定義  
}; 

hrtimer的使用

初始化hrtimer:

void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,  
             enum hrtimer_mode mode);  

激活hrtimer:

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

hrtimer_start函數將一個hrtimer加入到一個按照到期時間排序的紅黑樹中

如果需要指定到期範圍,則可以使用hrtimer_start_range_ns

hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,  
            unsigned long range_ns, const enum hrtimer_mode mode);  

取消hrtimer:

int hrtimer_cancel(struct hrtimer *timer);  

推遲hrtimer的到期時間:

extern u64  
hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);  

/* Forward a hrtimer so it expires after the hrtimer's current now */  
static inline u64 hrtimer_forward_now(struct hrtimer *timer,  
                      ktime_t interval)  
{  
    return hrtimer_forward(timer, timer->base->get_time(), interval);  
}  

使用示例

#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("hrtimer start\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("test init\n");
    return 0;
}

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

MODULE_LICENSE("GPL");

module_init(test_init);
module_exit(test_exit);

更多hrtimer的知識參考博文:
http://blog.csdn.net/droidphone/article/details/8074892

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章