# Linux如何管理和度量时间
Date: 2019-08-03


#### **Timing Measurement**

Linux 内核的Timer必须要完成两种**定时测量（timing measurement）**

- 保存当前的日期时间
- 维护定时器（Timer）

     保存当前时间提供给相关系统调用time(), ftime(),gettimeofday(),以便他们将日期时间返回给用户程序；维护定时器提醒内核某一段时间已经过去。要实现以上定时测量就离不开相关硬件的支持，下面看下X86体系下相关时钟和定时电路有哪些。

#### **时钟和定时电路**

     下面仅列出X86体系结构下常见的时间相关硬件定时器、时钟。

- RTC ：[**Real Time Clock**](https://wiki.osdev.org/Real_Time_Clock)

实时时钟， 依靠电池供电，集成在CMOS芯片上（结合NVRAM和RTC），可以得到日期和时间

- TSC ：[**Time Stamp Counter**](https://wiki.osdev.org/TSC)

 80x86处理器通过CLK引线，接收外部时钟信号，从Pentium开始 80x86处理器提供了一个TSC寄存器， 收到时钟信号后加一。可以通过rtdsc指令获取该值。因此TSC可以做为时钟设备。

- PIT ：[**Programmable Interval Timer**](https://wiki.osdev.org/Programmable_Interval_Timer)

又被称作8253/8254芯片， 这种设备不是通过振铃而是通过发出一种特殊中断，时钟中断通知内核一个时间间隔又过去了。时钟频率大约1.193182 MHz

- CPU Local APIC Timer： **[APIC timer](https://wiki.osdev.org/APIC_timer)**

由于是CPU内部的振荡器所有避免了资源抢占，APIC timer分为三种模式： Periodic Mode（周期模式），One-Shot Mode（一次性模式），TSC-Deadline Mode（Deadline模式） 

- HPET： [**High Precision Event Timer**](https://wiki.osdev.org/HPET)

是Intel和Microsoft设计的硬件，用于替换PIT，RTC, 提供更高的频率， 包含一个64位的主计数器和3到32个32位或64位的比较器。工作模式分为： eriodic Mode（周期模式），One-Shot Mode（一次性模式）

- ACPI PMT:  **[ACPI Power Management Timer](https://wiki.osdev.org/ACPI)**

         在所有基于 ACPI 的主板， 频率为 3.579545 MHz

         关于 **[Timer Interrupt Sources](https://wiki.osdev.org/Timer_Interrupt_Sources)** 的比较

<figure>

![](https://garlicspace.com/wp-content/uploads/2019/08/Timer-Interrupt-Sources-1024x353.png)

<figcaption>

[https://wiki.osdev.org/Timer\_Interrupt\_Sources](https://wiki.osdev.org/Timer_Interrupt_Sources)

</figcaption>

</figure>

       从上面表格也可以看到 这些硬件设备提供的功能非常简单：中断、计数，要基于这些硬件进行时间管理，还需要Linux Kernel做很多工作。 

#### **Linux 内核中的时间概念**

            内核依据硬件提供的时钟，以特定的频率称作 tick rate， 触发时钟中断，通过中断处理程序对其进行处理。

- 内核通过tick rate可以知道两次时钟中断的时间， 等于1/（tick rate）秒。
- 通过已知的时钟中断来跟踪实际时间（Wall time）和系统运行时间。
- 内核依据实际时间（Wall time）给用户空间提供一组相关系统调用。
- 系统运行时间-自系统启动后的时间，对于内核空间和用户空间都非常有用。

#### **利用时钟中断进行的工作**

- 更新系统时间
- 更新实际时间
- SMP系统中均衡调度程序中各处理器上运行队列
- 运行已超时的动态计数器
-  更新资源消耗和处理时间的统计值。

#### **The Tick Rate ：HZ**

        HZ是通过静态预处理定义的，在系统启动时按照HZ值对硬件进行设置。根据体系结构不通HZ值也不同。时钟中断周期为 1/HZ。

        X86下默认HZ 100， 一个时钟中断周期为10ms，下面X86 CentOS 环境的设置。

```
[root@centosgpt asm-generic]# pwd
/usr/include/asm-generic
[root@centosgpt asm-generic]# cat param.h
#ifndef __ASM_GENERIC_PARAM_H
#define __ASM_GENERIC_PARAM_H

#ifndef HZ
#define HZ 100
#endif
```

- 高HZ的优点
    - 内核计数器以更精细的分辨率（ finer resolution）和更高的准确度（increased accuracy）运行。
    - 测量（measurement)以更精细的分辨率记录
    - 进程抢占更准确地发生
- 高HZ的缺点
    - 更大的开销
    - 处理器花费更多时间在时间中断上
    - 更频繁执行中断打乱了处理器高速缓存，并增加耗电
- tickless

 编译内核是可以通过CONFIG\_HZ选项设置，系统可以根据需要动态调整时钟中断，在不需要终端的空档期， 不触发时钟中断，从而减少消耗。配置tickless

#### **jiffies**

          全局变量jiffies用来记录系统启动以来产生的节拍的总数， 启动时，初始化为0， 每次时钟中断处理程序会递增。

           jiffies与HZ， 一秒钟内时钟中断次数等于HZ，jiffies一秒中增加的值就是HZ，系统运行时间以秒为单位等于jiffies/HZ； 以秒为单位的时间转化为jiffies（seconds \* HZ），

- The jiffies 变量总是一个 unsigned long类型,  32-bit 体系结构 32位，  64-bit 体系结构是64位
- 在100HZ情况下， 497天会溢出，1000HZ情况下49.7天会溢出，如果是64位的jiffies，由于数值非常大， 1000HZ情况下，大约 ‭213503982334.6天会溢出‬。
- jiffies溢出后的回绕。
- 变量 extern u64 jiffies\_64 ，jiffies读取jiffies\_64低32位,通过get\_jiffies\_64()获得全部的64-bits值。

          **2038年问题** 与jiffies回绕（wrap round）相关的问题，time\_t被定义为32位的相关系统，在其上运行的应用如果使用POSIX时间的程序都将[涉及2038年问题](https://zh.wikipedia.org/wiki/2038%E5%B9%B4%E9%97%AE%E9%A2%98)， 也就是到了2038年1月19日， time\_t数字将无法工作。

#### **定时器**

- **定时器使用：**设置一个超时时间， 指定超时发生后函数， 然后激活定时器就可以了。
-  **定时器的竞争条件：**定时器执行的与当前代码异步，所以可能存在潜在的竞争条件。
- **实现定时器：**内核在时钟中断发生后执行定时器 ， 定时器做为软中断在下半部上下文执行。

####  **延迟**

-   **忙等待：需要一致循环，替代方案是使用cond\_reched()**
-   **短延时：内核提供的三个延迟函数ji，他们没有使用jiffies**
    - void udelay(unsigned long usecs)
    - void ndelay(unsigned long nsecs)
    - void mdelay(unsigned long msecs)
- **schedule\_timeout()** 让需要延时的任务睡眠到指定延时时间耗尽然后重新运行。

           依赖于硬件提供的时钟中断和计数， 通过jiffies记录时钟tick， 完成对时间度量， 通过时间度量也完成了时间记录，定时器使用和延时的设置。

# 参考

            [Linux 核心設計: Timer 及其管理機制](https://hackmd.io/@sysprog/HJElbeHkr)

            [Linux 时间系统分析](https://www.binss.me/blog/linux-time-system-analysis/)

           [What is the difference between CMOS and RTC?](https://www.quora.com/What-is-the-difference-between-CMOS-and-RTC)

           [2038年问题](https://zh.wikipedia.org/wiki/2038%E5%B9%B4%E9%97%AE%E9%A2%98)

           [64-bit computing - Wikipedia](https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)

