概述
简单介绍linux下的时间子系统。包括clocksource,timekeeper和定时器的内容。
2.2 timekeeper
对于真实用户来说,感知的是真实世界的真实时间,也就是所谓的墙上时间。clocksource只是提供一个按周期递增的周期计数。在Linux内核中,使用timekeeper对clocksource进行进一步的封装,将周期转换时间并转换成合适的格式。
2.2.1 time type
内核中管理着多种时间,他们分别是RTC time, wall time(xtime), monotonic time, raw monotonic time, boot time。这里,我们简单分析一下各种类型的时间。
RTC time,又叫CMOS时间。它通常由一个专门的计时硬件来实现,软件可以通过读取该硬件来获取年月日,时分秒等时间信息。一般来说,RTC time是一种可持续计时的。也就是说,无论系统是否上电,RTC硬件中的时间都不会丢失,计时会一直持续进行。硬件上通常由一个后备电池对RTC硬件进行单独的供电。由于RTC硬件的多样性,开发者需要为每种RTC时钟硬件提供相应的驱动程序,内核和用户空间通过驱动程序访问RTC硬件来获取或设置时间信息。
wall time,和RTC time一样,都是人们日常所使用的墙上时间,只是RTC time的时钟精度通常比较低,大多数情况下只能达到毫秒级别的精度。而且如果使用外部的RTC芯片,访问的速度也比较慢。为此,内核维护了另外一个wall time时间:xtime。xtime的精度取决于其用于计时的clocksource,有的甚至可以达到纳秒级。因为xtime实际上是一个内存变量,它的访问速度可以非常快,所以内核的大部分代码都使用xtime来获取当前时间信息。xtime记录的是自1970年1月1日24时到当前时刻所经历的纳秒数。
monotonic time,该时间会从开机后一直单调的增加。不会像xtime可以因用户调整时间而产生跳变。但是该时间不会统计系统休眠的时间。也就是说,系统休眠时,monotonic time不会增加。
raw monotonic time,与monotonic time类似,也是单调递增的时间。与monotonic time不同的是,raw monotonic time不会受到NTP时间调整的影响,它代表着系统独立时间硬件对时间的统计。
boot time,与monotonic time类似,不过会加上系统休眠时间。它代表着系统上电后的总时间。
2.2.2 相关数据结构
内核中,为了实现之上的多种时间,定义了几个静态全局变量。
static struct timespec xtime __attribute__ ((aligned (16)));
static struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
static struct timespec total_sleep_time;
/*
* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock.
*/
static struct timespec raw_time;
struct timekeeper {
/* Current clocksource used for timekeeping. */
struct clocksource *clock;
/* The shift value of the current clocksource. */
int shift;
/* Number of clock cycles in one NTP interval. */
cycle_t cycle_interval;
/* Number of clock shifted nano seconds in one NTP interval. */
u64 xtime_interval;
/* shifted nano seconds left over when rounding cycle_interval */
s64 xtime_remainder;
/* Raw nano seconds accumulated per NTP interval. */
u32 raw_interval;
/* Clock shifted nano seconds remainder not stored in xtime.tv_nsec. */
u64 xtime_nsec;
/* Difference between accumulated time and NTP time in ntp
* shifted nano seconds. */
s64 ntp_error;
/* Shift conversion between clock shifted nano seconds and
* ntp shifted nano seconds. */
int ntp_error_shift;
/* NTP adjusted clock multiplier */
u32 mult;
};
xtime,即wall time。他是一个timespec结构变量,记录了自1970年1月1日以来所经历的时间。因为是timespec结构,所以精度可以达到纳秒级。但是需要系统的硬件支持这一精度。
monotonic time,表示自系统启动以来所经历的时间。该时间只能单调递增。xtime正常情况下也是单调递增的,但是用户可以主动向前或向后调整wall time,从而修改xtime的值。系统定义了变量wall_to_monotonic,表示monotonic time和xtime之间的偏移量,当需要获取monotonic time时,把xtmie和wall_to_monotonic时间相加即可。由于系统启动时monotonic time初始值应该为0,所以在初始化时wall_to_monotonic应该是个负值。
total_sleep_time,用来记录系统休眠的时间。每次休眠被唤醒后,会重新累加该时间和xtime,调整wall_to_monotonic的值,保证monotonic time的时间不会发生跳变。由于wall_to_monotonic的值被调整,如果想要获取boot time,可以使用monotonic time与total_sleep_time之和。
raw_time,用来表示真正的硬件时间。也就是raw monotonic time。它不受时间调整的影响,monotonic time虽然也不受settimeofday的影响,但是会受到ntp调整的影响,因为monotonic time与xtime有关。而raw_time不受ntp调整的影响。raw_time在开机完成后就单调的递增。在用户空间,可以使用clock_gettime获取xtime, monotonic time和raw time,对应的ID参数分别为CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW(有可能参数没有定义,但是使用其值4,可能成功获取时间。直接使用值可能有移植的问题)。
timekeeper结构中比较重要的字段有clock,shift,mult。这里,clock字段对应的是当前系统选用的时钟源。一般来说,rating值越高,被选择为最终时钟源的可能性越大。但是Linux为了可靠性,在选定最终时钟源之前,使用watchdog来判定时钟源是否可靠。判定方式是给定时器设定定时任务,时间为0.5s,如果唤醒任务的时间误差大于0.0625s,则认为时钟源是不可靠的。在退出监控时会将时钟源的rating值设置为0,表明时钟源及其不精确。之后选用rating值最高的时钟源作为系统的时钟源,同时赋值给timekeeper.clock字段。而shift和mult字段的意义和clocksource结构中的相同。在初始化时,内核会将clocksource的mult和shift赋值给timekeeper的mult和shift字段。只是随着系统的运行,ntp调整会改变timekeeper结构中mult字段的值,而clocksource结构中的相应字段不会被改变。
(持续更新中。。。)
转载于:https://www.cnblogs.com/kylinos/p/8624912.html
最后
以上就是端庄嚓茶为你收集整理的linux时间子系统(二)的全部内容,希望文章能够帮你解决linux时间子系统(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复