深入Linux内核架构笔记-高分辨率时间

Overview

  • 高分辨率定时器按时间在一颗红黑数上排序
  • 独立于时钟周期,采用纳秒时间戳

数据结构

  • 高分辨率时钟可以基于两种时钟:CLOCK_MONOTONIC和CLOCK_REALTIME,前一种是单调递增的,后一种可以发生跳变
  • 对于系统中的每个CPU,都提供了一个包含两种时钟基础的数据结构,每个时钟基础都有一个红黑树,来排序所有待处理的高分辨率定时器
    在这里插入图片描述
stuct hrtimer_cpu_base {
  struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
#ifdef CONFIG_HIGH_RES_TIMERS
  ktime_t expires_next;
  int hres_active;
  struct list_head cb_pending;
  unsigned long nr_events  
#endif
}
  • HRTIMER_MAX_CLOCK_BASES : 2,对应CLOCK_MONOTONIC和CLOCK_REALTIME
  • expires_next : 将要到期的下一个事件的绝对时间
  • hres_active : 表示高分辨率模式是否启用
  • cb_pengding : 通过软中断HRTIMER_SOFTIRQ处理的定时器
  • nr_events : 记录时钟中断的总数
struct hrtimer_clock_base {
  struct hrtimer_cpu_base *cpu_base;
  clockid_t index;
  struct rb_root active;
  struct rb_node *first;
  ktime_t resolution;
  ktime_t (*get_time)(void);
  ktime_t (*get_softirq_time)(void);
  ktime_t softirq_time;
#ifdef CONFIG_HIGH_RES_TIMERS
  ktime_t offset;
  int (*reprogram)(struct hrtime *t
                   struct  hrtime_clock_base *b,
                   ktime_t n);
#endif
}
  • hrtimer_cpu_base : 指向该时钟基础所属的per-CPU时钟结构
  • index : 区分CLOCK_MONOTONIC和CLOCK_REALTIME
  • rb_root : 红黑树根,用来排序活动的定时器
  • rb_first : 第一个要到期的定时器
  • softirq_time : HRTIMER_SOFTIRQ发出的时间,用来处理高分辨率定时器
  • get_time : 读取细粒度时间,对于CLOCK_MONOTONIC直接返回时钟源的值,对于CLOCK_REALTIME需要转换为实际的系统时间
  • resolution : 该时钟基础对应时钟源的分辨率
  • offest : 在调整实时时钟时,会造成存储在CLOCK_REALTIME时钟基础上的定时器的过期时间和当前实际时间之间的差值
  • reprogram : 对给定的定时器事件进行重新编程
struct hrtimer {
  struct rb_node node;
  ktime_t expires;
  enum hrtimer_restart (*function)(struct hrtimer*);
  struct hrtimer_clock_base *base;
  unsigned long state;
#ifdef CONFIG_HIGH_RES_TIMERS
  struct hrtimer_cb_mode cb_mode;
  struct list_head cb_entry;
#endif  
}
  • node : 将定时器链接到时钟基础的红黑树中
  • expires : 到期时间
  • function : 定时器对应的处理函数
  • base : 执行对应的时钟基础: CLOCK_MONOTONIC或者CLOCK_REALTIME
  • cb_entry : 将定时器链接到以hrtimer_cpu_base->pending为表头的链表中
  • cb_mode
    • HRTIMER_CB_SOFTIRQ : 必须中软中断上下文执行
    • HRTIMER_CB_IRQSAFE : 可能在硬件中断上下文中执行
    • HRTIMER_CB_IRQSAFE_NO_RESTART : 可能在中断上下文执行,不会重启定时器
    • HRTIMER_CB_NO_SOFTIRQ : 必须在中断上下文执行
  • state :
    • HRTIMER_STATE_INACTIVE : 不活动的定时器
    • HRTIMER_STATE_ENQUEUED : 在时钟基础上排队,等待到期的定时器
    • HRTIMER_STATE_CALLBACK : 正在执行回调的定时器
    • HRTIMER_STATE_PENDING : 定时器已经到期,正在回调链表上等待执行
  • enum hrtimer_restart
    • HRTIMER_NORESTART : 不重启定时器
    • HRTIMER_RESTART : 重启定时器
struct hrtimer_sleeper {
  struct hrtimer timer;
  stuct task_struct *task;
}
  • timer : 定时器
  • task : 睡眠的进程

API

void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
        enum hrtimer_mode mode);
int hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode);
int hrtimer_cancel(struct hrtimer *timer)
int hrtimer_try_to_cancel(struct hrtimer *timer)
int hrtimer_restart(struct hrtimer *timer)
  • hrtimer_mode
    • HRTIMER_MODE_ABS
    • HRTIMER_MODE_REL

实现

  • 高分辨率模式下的高分辨率定时器
Y
N
Y
N
hrtimer_interrupt
cpu_base = get hrtimer_cpu_base
now = ktime_get
base = cpu_base->clock_base
i = 0
i < HRTIMER_MAX_CLOCK_BASES
node = base -> first
timer = get hrtimer from node
base.tv64 < timer->expires.tv64
handle the timer by hrtimer_cb_mode
i++
calculate expires_next
tick_program_next - expires_next
rase_softirq -- HRTIMER_SOFTIRQ
N
Y
N
N
run_hrtimer_softirq
hrtimer_cpu_base *cpu_base = __get_cpu_var
&cpu_base->cb_pending is empty
struct hrtimer *timer = get timer from cpu_base->cb_pending
__remove_hrtimer
restart = timer->function
restart == HRTIMER_RESTART
enqueue_hrtimer
hrtimer_active
hrtimer_reprogram
  • 低分辨率模式下的高分辨率定时器
N
run_timer_softirq
hrtimer_run_queues
i = 0
i < HRTIMER_MAX_CLOCK_BASES
run_hrtimer_queue
i++
  • 切换到高分辨率模式

    • hrtimer_run_queues ⇒ tick_check_oneshot_change ⇒ hrtimer_switch_to_hres
      ⇒ tick_init_highres ⇒ tick_switch_to_oneshot(hrtimer_interrupt) ⇒ dev->event_handler = handler;
  • 周期时钟仿真

Y
N
tick_sched_timer
该CPU负责全局时钟
tick_do_update_jiffies64
update_process_times
profile_tick
Set next tick after tick_period
return HRTIMER_RESTART
  • 由tick_setup_sched_timer函数设置,追加一个hrtimer,按照固定时间间隔触发,hrtimer对应的处理函数为:tick_sched_timer
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值