Linux系统中的计时机制及相关时间函数

from: http://javadino.blog.sohu.com/74292567.html

 

1. 时间相关硬件

计算机系统中的时间主要由三种时钟硬件提供的:实时时钟(Real Time Clock,RTC),可编程间隔定时器(Programmable Interval Timer,PIT),时间戳计数器(Time Stamp Counter,TSC)。这些时钟硬件都是基于固定频率的晶振来提供时钟方波信号输入。

一般说来,Linux内核主要需要两种类型的时间:
一类是单步递增性时钟,不发送中断,需要软件主动去读取其COUNTER寄存器来获得时间的。TSC即属于这一类。
另一种维持一个固定周期的定时器,以提醒内核或用户一段时间已经过去了。通过周期性发送中断达到记时目的。PIT属于这一类。

RTC 通过主板上的电池来供电,在关机时维持日期和时间。RTC为整个计算机提供了一个计时标准,是底层的时钟数据,也被称为硬件时钟CMOS时钟。
PIT 定时/计数器所采用的最典型的芯片是Intel 8253/8254可编程定时/计数芯片。定时/计数器从RTC接收输入脉冲,然后开始递减计数,当计数到零时,产生一个输出脉冲,引发实时中断处理程 序,然后定时/计数器复位又开始从头计数。在开机时,操作系统通过获取RTC中的时间数据来初始化系统时钟,然后通过定时/计数芯片的向下计数引发时钟中 断,形成系统时钟(clock tick),频率大致在100-1000Hz之间。
TSC 是一个不断增加的计数器,它在CPU的每个时钟信号到来时加1。也就是以处理器频率加1。即在主流处理器上更新频率可达到上GHz。

2. 时间相关数据结构

Linux有两个重要的数据结构,一个是32位的无符号整数全局变量jiffies, 每次时钟中断时加1(一般相隔1ms-10ms),linux运行时就是以这个时间来记录的,如进程时间片更新,执行定时服务等,可以视为Linux运行 的心跳。另一个是全局变量xtime,是timeval结构的变量。用来表示当前时间距UNIX时间基准1970-01-01 00:00:00的相对秒数值。其时间精度是纳秒(先前的版本为微秒)。因为xtime主要供查询使用,所以xtime的更新被放到 timer_interrupt()的后半段执行,和jiffies不同,不是每次时钟中断时都执行。因此看起来会比jiffies慢,两者不同步

3. 时间相关系统调用
获取时间的系统调用主要有两个time()和gettimeofday()
time()即简单的把xtime中的tv_sec返回到用户空间。单位为秒。
gettimeofday()用来获取精度为us的当前时间信息和时区信息。首先用当前的jiffies减去上次更新xtime时的 jiffies,得到一个修正值即上次修正xtime到目前的差值,但是这个值是ms级精度的。要获得us精度,需要用当前TSC值减去上次时钟中断发生 时的TSC,用这两个值更新xtime,并将这个值返回到用户空间。在2.6.20中主要的调用路径如下:
sys_gettimeofday()->
do_gettimeofday()->
offset = time_interpolator_get_offset(); ->  
time_interpolator_get_counter(); ->
time_interpolator_get_cycles(); ->
get_cycles(); ->
rdtscll(); ->
get_scheduled_cycles(); ->
native_read_tsc(); ->
asm volatile("rdtsc" : "=A" (val)); //读取TSC的值

4. 获取精度更高的时间
在Linux中xtime的精度为ns,并且有getnstimeofday(),当并没有作为系统调用提供。要在用户空间获得ns级的时间用户可以自己实现。可以参考sys_gettimeofday 和 getnstimeofday():
sys_gettimeofday(struct timeval __user *tv){
offset = time_interpolator_get_offset();
sec = xtime.tv_sec;
nsec = xtime.tv_nsec;
usec = (nsec + offset) / 1000;
ktv->tv_sec = sec;
ktv->tv_usec = usec;
copy_to_user(tv, &ktv, sizeof(ktv));
}

getnstimeofday (struct timespec *tv)
{
sec = xtime.tv_sec;
nsec = xtime.tv_nsec+time_interpolator_get_offset();
tv->tv_sec = sec;
tv->tv_nsec = nsec;
}

5. 时钟同步
在单处理系统中,因为系统时间(由时钟中断更新)和TSC(由处理器CLK信号更新)都是由硬件负责运转,独立运行,所以可能出现不同步的问题(比如Linux时钟中断屏蔽时,jiffies不会更新)。Linux会在合适的时间使用TSC对系统时钟进行校正。
在多处理系统中,因为有多个处理器,时钟中断是在处理器中广播的,而由其中一个处理器进行时钟中断处理。但是TSC是每个处理器独自拥有的,需要在各个TSC间进行同步。
在虚拟系统中(如VMware,Xen), 时钟中断由软件模拟产生,而TSC也不能直接从硬件上读取,需要虚拟软件利用处理器提供的能力,在 TSC真实的值上进行进一步的处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值