Linux time subsystem (2)

A brief introduction to the time subsystem under linux. Including clocksource, timekeeper and timer content.

2.2 timekeeper

  For real users, what is perceived is the real time in the real world, which is the so-called wall time. The clocksource just provides a cycle count that is incremented by cycle. In the Linux kernel, use timekeeper to further encapsulate the clocksource, convert the cycle time and convert it into a suitable format.

2.2.1 time type

  There are many kinds of time managed in the kernel, they are RTC time, wall time(xtime), monotonic time, raw monotonic time, boot time. Here, we briefly analyze the various types of time.

  RTC time , also known as CMOS time. It is usually implemented by a special timing hardware, and the software can obtain time information such as year, month, day, hour, minute, and second by reading the hardware. Generally speaking, RTC time is a kind of continuous timekeeping. That is, regardless of whether the system is powered on, the time in the RTC hardware will not be lost, and the timing will continue. The hardware is usually powered by a backup battery to independently power the RTC hardware. Due to the diversity of RTC hardware, developers need to provide corresponding drivers for each RTC clock hardware. The kernel and user space access the RTC hardware through the driver to obtain or set time information.

  wall time , like RTC time, is the wall time that people use every day, but the clock accuracy of RTC time is usually relatively low, and in most cases it can only reach the precision of milliseconds. And if an external RTC chip is used, the access speed is also relatively slow. To this end, the kernel maintains another wall time: xtime. The accuracy of xtime depends on the clocksource used for timing, and some can even reach nanosecond level. Because xtime is actually a memory variable, its access speed can be very fast, so most of the code of the kernel uses xtime to get current time information. xtime records the number of nanoseconds elapsed from 24:00 on January 1, 1970 to the current moment.

  monotonic time , the time will increase monotonically after booting. Unlike xtime, which can jump due to user adjustment of the time. However, this time does not count the time the system sleeps. That is, the monotonic time does not increase when the system is hibernating. raw monotonic time , similar to monotonic time, is also monotonically increasing time. Different from monotonic time, raw monotonic time is not affected by NTP time adjustment, it represents the statistics of time by system independent time hardware. boot time , similar to monotonic time, but adds the system sleep time. It represents the total time since the system was powered on.
  
  


 

2.2.2 Related data structures 

  In the kernel, several static global variables are defined in order to realize the above various times.

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结构中的相应字段不会被改变。

(持续更新中。。。)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325756480&siteId=291194637