linux时间子系统(七)

简单介绍linux下的时间子系统。包括clocksource,timekeeper和定时器的内容。

3.2 高精度定时器 

随着内核的不断升级和硬件的不断发展,由于低精度定时器有一定的局限性,内核从2.6.16开始加入了高精度定时器架构。在实现方式上,高精度定时器的实现代码几乎没有借用低精度定时器的数据结构和代码,原因有以下几点:

1 低精度定时器的代码和jiffies的关系太过紧密,并且默认按照32为进行设计,如果要基于它来实现高精度时钟,必然会打破原有的time wheel的概念,而且会引入大量的#if #else判断。

2 虽然大部分时间里,time wheel可以实现O(1)的时间复杂度,但是如果有进位发生,不可预测的O(n)定时器级联迁移,大大的影响了高精度定时器的精度。

3 低精度定时器几乎为超时而设计,为此对它进行了大量的优化,精确时间并不是它的主要目的。

为此,内核为高精度定时器重新设计了一套软件架构,他可以为我们提供纳秒级的定时精度,以满足对精确时间有迫切需求的应用和内核驱动,如多媒体应用,音频设备的驱动程序等等。

3.2.1 hrtimer重要的数据结构

低精度定时器使用5个链表数组来组织timer_list结构,形成了著名的时间轮的概念。而高精度时钟,为了具备稳定而快速的查找、快速的插入和删除定时器的能力以及排序功能,内核的开发者最后选定红黑树,来组织hrtimer。随着系统的运行,hrtimer不断的被创建和销毁,新的hrtimer按照到期时间被插入到红黑树中,红黑树的最左下节点即为最快到期的定时器。内核使用hrtimer结构表示一个高精度定时器。

struct hrtimer {

struct timerqueue_node          node;

ktime_t                         _softexpires;

enum hrtimer_restart            (*function)(struct hrtimer *);

struct hrtimer_clock_base       *base;

unsigned long                   state;

struct list_head                cb_entry;

int                             irqsafe;

#ifdef CONFIG_TIMER_STATS

int                             start_pid;

void                            *start_site;

char                            start_comm[16];

#endif

};

_softexpires,表示到期时间。

function,定时器到期时的回调函数。其返回值是一个枚举值,决定了该定时器是否需要被重新激活。如果返回值为HRTIMER_RESTART,表明需要重新激活。如果为HRTIMER_NORESTART,表明不需要重新激活。

state,用于表示hrtimer当前的状态。

#define HRTIMER_STATE_INACTIVE  0x00    //定时器未激活

#define HRTIMER_STATE_ENQUEUED  0x01    // 定时器已经排入红黑树中

#define HRTIMER_STATE_CALLBACK  0x02    // 定时器的回调函数正在被调用

#define HRTIMER_STATE_MIGRATE   0x04    // 定时器正在cpu间做迁移

base,表示当前定时器是基于哪一种时间基准的。hrtimer到期时间可以基于以下几种时间基准

enum  hrtimer_base_type {

HRTIMER_BASE_MONOTONIC,    //monotonic time

HRTIMER_BASE_REALTIME,    //wall time

HRTIMER_BASE_BOOTTIME,    //boot time

HRTIMER_MAX_CLOCK_BASES,

};

3.2.2 红黑树 

与低精度时钟一样,处于效率和互斥的考虑,每个cpu单独管理属于自己的hrtimer。为此,专门定义了一个结构hrtimer_cpu_base:

struct hrtimer_cpu_base {

raw_spinlock_t                  lock;

unsigned long                   active_bases;

#ifdef CONFIG_HIGH_RES_TIMERS

ktime_t                         expires_next;  //三种时间基准的定时器最先到期定时器的时间

int                             hres_active;

int                             hang_detected;

unsigned long                   nr_events;

unsigned long                   nr_retries;

unsigned long                   nr_hangs;

ktime_t                         max_hang_time;

#endif

#ifdef CONFIG_PREEMPT_RT_BASE

wait_queue_head_t               wait;

#endif

struct hrtimer_clock_base       clock_base[HRTIMER_MAX_CLOCK_BASES];  //每个cpu都有三种时间基准的高精度定时器列表

};

struct hrtimer_clock_base {

struct hrtimer_cpu_base *cpu_base;  //指向所属cpu的hrtimer_cpu_base结构

int                     index;

clockid_t               clockid;  //确定基于哪种时间基准

struct timerqueue_head  active;   //红黑树,含定时器列表

struct list_head        expired;

ktime_t                 resolution;

ktime_t                 (*get_time)(void);

ktime_t                 softirq_time;

ktime_t                 offset;

};

struct timerqueue_node {

struct rb_node node;

ktime_t expires;

};

struct timerqueue_head {

struct rb_root head;

struct timerqueue_node *next;

};

timequeue_head结构在红黑树的基础上,增加了一个next字段,用于保存红黑树中最先到期的定时器节点,实际上就是红黑树的最左下节点。有了next字段,系统就不必遍历整个红黑树,只要取出next字段对应的节点处理即可。

原文地址:https://www.cnblogs.com/kylinos/p/9197794.html

时间: 2024-10-13 11:11:32

linux时间子系统(七)的相关文章

Linux时间子系统(十五) clocksource

一.前言 和洋葱一样,软件也是有层次的,内核往往需要对形形色色的某类型的驱动进行抽象,屏蔽掉其具体的特质,获取该类驱动共同的逻辑,而又根据这些逻辑撰写该类驱动的抽象层.嵌入式系统总是会提供timer的硬件block,软件需要对timer硬件提供的功能进行抽象:linux kernel将timer类型的硬件抽象成两个组件,一是free running的counter,另外一个是指定的counter值上产生中断的能力.本文主要描述第一个组件,在内核中被称作clock source. 二.什么是clo

Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)

在前面章节的讨论中,我们一直基于一个假设:Linux中的时钟事件都是由一个周期时钟提供,不管系统中的clock_event_device是工作于周期触发模式,还是工作于单触发模式,也不管定时器系统是工作于低分辨率模式,还是高精度模式,内核都竭尽所能,用不同的方式提供周期时钟,以产生定期的tick事件,tick事件或者用于全局的时间管理(jiffies和时间的更新),或者用于本地cpu的进程统计.时间轮定时器框架等等.周期性时钟虽然简单有效,但是也带来了一些缺点,尤其在系统的功耗上,因为就算系统目

Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现

上一篇文章,我介绍了传统的低分辨率定时器的实现原理.而随着内核的不断演进,大牛们已经对这种低分辨率定时器的精度不再满足,而且,硬件也在不断地发展,系统中的定时器硬件的精度也越来越高,这也给高分辨率定时器的出现创造了条件.内核从2.6.16开始加入了高精度定时器架构.在实现方式上,内核的高分辨率定时器的实现代码几乎没有借用低分辨率定时器的数据结构和代码,内核文档给出的解释主要有以下几点: 低分辨率定时器的代码和jiffies的关系太过紧密,并且默认按32位进行设计,并且它的代码已经经过长时间的优化

Linux时间子系统专题汇总

DroidPhone关于Linux时间子系统专题: http://blog.csdn.net/DroidPhone/article/category/1263459 Linux时间子系统之一:clock source(时钟源) Linux时间子系统之二:表示时间的单位和结构 Linux时间子系统之三:时间的维护者:timekeeper Linux时间子系统之四:定时器的引擎:clock_event_device Linux时间子系统之五:低分辨率定时器的原理和实现 Linux时间子系统之六:高精

Linux时间子系统(一) 基本概念

本文使用Q & A的方式来和大家以前探讨一下时间的基本概念 一.什么是时间? 这个问题实在是太复杂了,我都不知道这是一个物理学.宇宙学.还是热力学异或是哲学问题,我只是想从几个侧面来了解一下时间这个概念.本节内容都是我坐在公交车上瞎想的,对物理学有兴趣的人可以指出我的错误(一个搞linux kernel的人不会有太深刻的物理学知识的),对Linux时间子系统有兴趣的人还是忽略这个小节吧. 1.时间和空间以及相对性 有没有绝对时间的概念呢?时间是否是独立于一切存在的呢?相信有绝对时间的存在比较符合

Linux时间子系统(十七) ARM generic timer驱动代码分析

一.前言 关注ARM平台上timer driver(clocksource chip driver和clockevent chip driver)的驱动工程师应该会注意到timer硬件的演化过程.在单核时代,各个SOC vendor厂商购买ARM core的IP,然后自己设计SOC上的peripherals,这里面就包括了timer的硬件.由于没有统一的标准,各个厂商的设计各不相同,这给驱动工程师带来了工作量.然而,如果仅仅是工作量的话就还好,实际上,不仅仅如此.linux的时间子系统要求硬件t

Linux时间子系统(十四) tick broadcast framework

一.前言 在内核中,有cpuidle framework可以控制cpu的节电:当没有进程调度到该cpu上执行的时候,swapper进程粉墨登场,将该cpu会被推入到idle状态.当然CPU的idle状态有深有浅,当CPU睡的比较深入的时候,有可能会关闭本地的timer硬件.这样就会引入一个很有意思的问题:local timer将无法唤醒CPU,该cpu上的所有的software timer将无法唤醒cpu.tick broadcast framework就是用来解决这个问题的. 本文中的代码来自

Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()

我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些API基于低分辨率定时器或高精度定时器来实现,本章的内容就是讨论这些方便.好用的API是如何利用定时器系统来完成所需的功能的. /**************************************************************************************

Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()【转】

转自:http://blog.csdn.net/droidphone/article/details/8104433 我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些API基于低分辨率定时器或高精度定时器来实现,本章的内容就是讨论这些方便.好用的API是如何利用定时器系统来完成所需的功能的. /***************************