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

简介:

转自: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博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/5314237.html ,如需转载请自行联系原作者
相关文章
|
1天前
|
存储 算法 Linux
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
|
1天前
|
安全 Linux
【Linux】详解用户态和内核态&&内核中信号被处理的时机&&sigaction信号自定义处理方法
【Linux】详解用户态和内核态&&内核中信号被处理的时机&&sigaction信号自定义处理方法
|
1天前
|
存储 Linux
【Linux】对信号产生的内核级理解
【Linux】对信号产生的内核级理解
|
1天前
|
消息中间件 算法 Linux
【Linux】对system V本地通信的内核级理解
【Linux】对system V本地通信的内核级理解
|
2天前
|
Linux 编译器 调度
xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务
本文介绍了如何将POSIX应用程序编译为在Xenomai实时内核上运行的程序。
16 1
xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务
|
2天前
|
算法 Linux 调度
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
6 1
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
|
2天前
|
Linux 调度 数据库
|
2天前
|
存储 缓存 Linux
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
本文介绍了Xenomai中的XDDP(Xenomai Distributed Data Protocol)通信机制,XDDP用于实时和非实时进程之间的数据交换。XDDP在Xenomai内核中涉及的数据结构和管理方式,以及创建XDDP通道后的实时端和非实时端连接过程。
8 0
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
|
3天前
|
缓存 安全 网络协议
Linux内核详解,什么是linux内核?
Linux内核详解,什么是linux内核?
13 0
|
4天前
|
存储 缓存 安全
Linux系统内核面试题
Linux系统内核面试题
20 3