【时间子系统】一、概述

  除了计算、存储、网络等核心子系统外,计算机内部还包含时间子系统,它对系统的运行起着重要作用。

什么是计算机的时间子系统?

  计算机内的时间子系统包含多种时间设备,我们可以把这些设备分为两大类:计时设备和定时通知设备。

  我们可以将计时设备理解为生活中所见的”墙上挂钟”或者”手表”,它们为系统提供了时间(时刻)。常见的计时设备有TSC(Time Stamp Counter)、RTC(Real Time Clock)、ACPI_PM:

  • TSC是每个CPU内部的一个计数器,它按CPU主频以固定频率递增,例如一个2400Mhz的CPU,计数器每秒逐一增加2400M个计数值。计数器在CPU启动时初始化为零,假设我们已知CPU启动时刻,那么只要把当前计算器的值除以频率再加上启动时刻,就可以得知当前时间了。
  • RTC是位于CMOS电路中的一个计时设备,它与TSC相比的优点是有独立的电池供电,即使计算机下电,RTC计时器仍可以继续工作;缺点是计数频率较低,因此时间精度较差。通常我们初始时将RTC计数器的值设置为当前时刻相对于1970年1月1日的时间差,因此通过RTC提供的寄存器接口,我们可以直接获取到当前时间。
  • ACPI_PM通常是南桥中的APCI电源管理模块提供的计时设备,其精度较低,通常不推荐使用。

  我们可以将定时通知设备理解为生活中所见的”闹钟”,它们周期性地或者在一定时间间隔后向系统通知到期事件。常见的通知设备有Local APIC Timer、PIT(Programmable Interval Timer)、HPET(High Precision Event Timer)。初始时我们向时间通知设备的计数器中写入一个到期计数值,然后时间通知设备按固定频率递减计数器中的值,当计数器值为零时便通过中断向CPU通知事件发生。

  • Local APIC Timer是每个CPU的本地中断控制器(APIC)内部的定时设备,精度较高,是系统正常运行时采用的通知设备。
  • PIT是CPU之外的独立定时通知设备,属全局设备,精度较低,通常不使用。
  • HPET也是全局定时通知设备,精度较高,需要系统中含专属硬件。

  计算机用户是无法直接使用这些时间设备的,必须通过运行在CPU上的内核程序,应用程序或者用户才能最终获取计时和时间通知服务。因此我们可以将计算机时间子系统分为硬件和软件两部分:各种时间设备属于硬件部分,内核使能这些硬件的模块(也称内核时间子系统)属于软件部分。内核中将计时设备称为时钟源(Clock Source),将定时通知设备称为时钟事件设备(Clock Event Device)。时间子系统整体结构如下图所示(感谢droidphone的分享,原文链接),后续我们将深入内核分析其实现原理。

为什么需要时间子系统?

  基于各种时间设备和内核时间子系统模块,应用程序可以实现计时和到期通知(定时器)功能:例如我们桌面应用中的日历程序就使用了计时功能来提供实时时间,又例如邮件客户端的定时接收功能就使用了定时器。此外,内核自己的进程调度功能也依赖于内核的定时器,从而进行周期性的调度决策。

  下面我们给出了两段示例程序来展示时间子系统的基本使用方法:

//用户态计时功能示例程序

#include<stdio.h>
#include<sys/time.h>
#include<unistd.h>

int main()
{
    struct  timeval    tv;
    struct  timezone   tz;

    gettimeofday(&tv,&tz); /*获取当前时间*/

    printf(“tv_sec:%d\n”,tv.tv_sec);
    printf(“tv_usec:%d\n”,tv.tv_usec);

    printf(“tz_minuteswest:%d\n”,tz.tz_minuteswest);
    printf(“tz_dsttime:%d\n”,tz.tz_dsttime);
}
//用户态定时器参考setitime,这里以内核使用定时器示例

/*1. 初始化定时器结构*/
init_timer(&wb_timer);

/*2. 定时器超时函数*/
wb_timer.function = wb_timer_function; 

/*3.或者初始化定时器和超时函数作为一步(data作为fn的参数)*/
setup_timer(timer, fn, data)    

/*4. 添加定时器*/
add_timer(&buttons_timer); 

/*5. 设置定时器超时时间 1\100 s(修改一次超时时间只会触发一次定时器*/
mod_timer(&buttons_timer, jiffies+HZ/100); 

/*6.删除定时器*/
del_timer(&timer);

内核如何实现时间子系统?

  后续我们将以一系统博文深入分析内核时间子系统的实现:


转载请注明:吴斌的博客 » 【时间子系统】一、概述