在linux内核中获得比jiffies精度更高的时间值【转】

简介: 转自:http://blog.chinaunix.net/uid-20672257-id-2831219.html 内核一般通过jiffies值来获取当前时间。尽管该数值表示的是自上次系统启动到当前的时间间隔,但因为驱动程序的生命期只限于系统的运行期 (uptime),所以也是可行的。

转自:http://blog.chinaunix.net/uid-20672257-id-2831219.html

内核一般通过jiffies值来获取当前时间。尽管该数值表示的是自上次系统启动到当前的时间间隔,但因为驱动程序的生命期只限于系统的运行期 (uptime),所以也是可行的。驱动程序利用jiffies的当前值来计算不同事件间的时间间隔。 硬件给内核提供一个系统定时器用以计算和管理时间,内核通过编程预设系统定时器的频率,即节拍率(tick rate),每一个周期称作一个tick(节拍)。Linux内核从2.5版内核开始把频率从100调高到1000(当然带来了很多优点,
也有一些缺点)。jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数。譬如,如果计算系统运行了多长时间,可以用 jiffies/tick rate 来计算。

jiffies定义在文件 

如果您需要更精确的时间来测量或者记录某些事情的话,内核中有个xtime全局变量,类型是struct timespec {time_t tv_sec; long tv_nsec;}按照这个数据结构,它是ns级的。

而且还有一个current_kernel_time函数,通过它就可以获取xtime的值。但是xtime是在时钟中断里更新的,而一个tick往往是 10ms或者100ms,它只能保证在时钟中断ISR调用时刻,它返回的值是精确到ns级,并不能保证任何一个调用这个函数的时刻都能这样,原因是xtime的更新速度比它差几个数量级。

如果需要精确到微妙级别,可以使用do_gettimeofday函数。该函数并不返回今天是本周的星期几或类似的信息;它是用微秒值来填充一个指向struct timeval的指针变量。相应的原型如下:

#include 

void do_gettimeofday(struct timeval *tv);

源码中声明的do_gettimeofday在Alpha和Sparc之外的体系结构上有“接近微秒级的分辨率” ,在Alpha和Sparc上和jiffies值的分辨率一样。Sparc的移植版本在2.1.34版的内核中升级了,可以支持更细粒度的时间度量。

void do_gettimeofday(struct timeval *tv)
{
 unsigned long flags;
 unsigned long seq;
 unsigned long nsec, sec, lost;

 do {
  seq = read_seqbegin_irqsave(&xtime_lock, flags);
  usec = system_timer->offset();

  lost = jiffies - wall_jiffies;
  if (lost)
  usec += lost * USECS_PER_JIFFY;

  sec = xtime.tv_sec;
  nsec += xtime.tv_nsec;
 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));

 /* usec may have gone up a lot: be safe */
 while (nsec >= 1000000000) {
  nsec -= 1000000000;
  sec++;
 }

 tv->tv_sec = sec;
 tv->tv_usec = usec;
}


中可以发现,我们只要稍微的修改一下代码就可以达到纳秒的精确度了

void do_gettimeofday_nsec(struct timespec *tv)
{
 unsigned long flags;
 unsigned long seq;
 unsigned long usec, sec, lost;

 do {
  seq = read_seqbegin_irqsave(&xtime_lock, flags);
  usec = system_timer->offset();

  lost = jiffies - wall_jiffies;
  if (lost)
  usec += lost * USECS_PER_JIFFY;

  sec = xtime.tv_sec;
  usec += xtime.tv_nsec / 1000;
 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));

 /* usec may have gone up a lot: be safe */
 while (usec >= 1000000) {
  usec -= 1000000;
  sec++;
 }

 tv->tv_sec = sec;
 tv->tv_usec = usec;
}

注意这里使用了不同的时间结构。

 
【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
|
Java API Android开发
【POI框架实战】——POI设置Excel单元格格式
 “这个excel中的数据怎么不能做加法啊?”、“标头这一行的字体怎么这么小啊,我都看不清”、“这一列能不能换个颜色,明显一些”、“你把这一列的数据给我留两个小数位。”、“这些数据能不能以货币的类型展示啊,就每个三位一个小逗号那种……”
【POI框架实战】——POI设置Excel单元格格式
|
Unix 编译器 Shell
[oeasy]python0033_先有操作系统还是先有编程语言_c语言是怎么来的
本文回顾了计算机语言与操作系统的起源,探讨了早期 Unix 操作系统及其与 C 语言的相互促进发展。Unix 最初用汇编语言编写,运行在 PDP-7 上,后来 Thompson 和 Ritchie 开发了 C 语言及编译器,使 Unix 重写并成功编译。1974 年 Ritchie 发表论文,Unix 开始被学术界关注,并逐渐普及。伯克利分校也在此过程中发挥了重要作用,推动了 Unix 和 C 语言的广泛传播。
242 10
[oeasy]python0033_先有操作系统还是先有编程语言_c语言是怎么来的
|
机器学习/深度学习 人工智能 自然语言处理
AI技术在自然语言处理中的应用
【10月更文挑战第4天】本文将介绍人工智能(AI)在自然语言处理(NLP)领域的应用,包括语音识别、机器翻译、情感分析等方面。我们将通过一些实际案例展示AI如何帮助人们更好地理解和使用自然语言。同时,我们也会探讨AI在NLP领域面临的挑战和未来发展方向。
|
算法 关系型数据库 Java
数据库原理第四章课后题答案(第四版)
数据库原理第四章课后题答案(第四版)
571 0
|
人工智能 物联网
AI 绘画Stable Diffusion 研究(三)sd模型种类介绍及安装使用详解(2)
AI 绘画Stable Diffusion 研究(三)sd模型种类介绍及安装使用详解
922 0
|
存储 程序员 C#
基于C#实现的学生成绩管理系统
基于C#实现的学生成绩管理系统
355 0
[启动流程] RT-Thread是如何启动的?
[启动流程] RT-Thread是如何启动的?
|
数据安全/隐私保护
加密与签名的区别
加密与签名的区别
369 0
|
计算机视觉
OPENCV图像处理提高(一)图像增强
在图像处理学习中会涉及到直方图,直方图很好地表现了图像的灰度信息;同时我们注意到在暗图像中,直方图的分量集中在灰度级的低端;亮图像的灰度值集中在直方图灰度值的高端;低对比度的图像有较窄的直方图,并集中于直方图的中间部分;高对比度的图像中直方图的分量覆盖很宽的范围,而且像素的分布没有太不均匀,只能看到少量垂线比其他高许多。通过图像增强可以有效地减弱这些缺陷
8925 56
|
存储 弹性计算 架构师
游戏上云成标配 云服务器该怎么选?
三大关键点:性能、稳定性和弹性伸缩能力。
游戏上云成标配 云服务器该怎么选?