zoukankan      html  css  js  c++  java
  • 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 ----- ");
    hrtimer_forward(timer, timer->base->get_time(), kt);
    return HRTIMER_RESTART;
    }


    static int __init test_init(void)
    {


    pr_info("timer resolution: %lu ", 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 start --------- ");
    return 0;
    }


    static void __exit test_exit(void)
    {
    hrtimer_cancel(&timer);
    printk("-------- test over ---------- ");
    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

  • 相关阅读:
    GridControl控件绑定RepositoryItemImageComboBox 作为下拉框使用
    ASP.NET MVC 扩展数据验证 转
    ASP.NET MVC Razor HtmlHelper扩展和自定义控件
    Thread锁 Monitor类、Lock关键字和Mutex类
    C# Thread.Join()用法的理解 转
    Redis集群高可用
    .Net Core中GC分析及调优总结-干货
    数据库之MySQL部署MGC方案(四)
    数据库之MySQL部署PXC方案(三)
    数据库之MySQL部署MGR方案(二)
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7098225.html
Copyright © 2011-2022 走看看