zoukankan      html  css  js  c++  java
  • Linux设备驱动程序 之 度量时间差

    概述

    内核通过定时器中断来跟踪事件流;

    时钟中断由系统定时硬件以及周期性的间隔产生,这个间隔由内核根据HZ的值设定,HZ是一个细节结构有关的常数;作为一般性规则,即使知道对应平台上的确切HZ值,也不应该在编程时依赖该HZ值;

    如果想改变系统时钟中断发生的频率,可以通过修改HZ值来进行,但是,如果修改了头文件中的HZ值,则必须使用新的值重新编译内核以及所有模块;

    每当时钟中断发生时,内核内部计数器的值增加一;这个计数器的值在系统引导值初始化为0,因此,它的值就是上次操作系统引导以来的时钟滴答数;这个计数器是一个64位变量(即使在32位架构上也是64位),称为jiffies_64;但是驱动程序发开者通常访问的是jiffies变量,它是unsigned long类型的变量,要么和jiffies_64相同,要么仅仅是jiffies_64的低23位,根据架构是64位还是32位而定;通常首选使用jiffies,因为对它的访问很快,从而对于64位jiffies_64值的访问并不需要在所有架构上都是原子的;

    使用jiffies计数器

    该计数器和读取计数器的工具函数包含在<linux/jiffies.h>中,但是通常只需要包含<linux/sched.h>文件,后者会自动包含jiffies.h;

    需要说明的是,jiffies和jiffies_64均应该被看成只读变量;

    在代码中需要记录jiffies的当前值时,可简单的访问上面说的unsigned long变量;该变量被声明为volatile,这样可以避免编译器对访问该变量的语句的优化;在代码需要计算未来的时间戳时,必须读取当前的计数器;

    1 #incldue <linux/jiffies.h>
    2 
    3 unsigned long j, stamp_1, stamp_half, stamp_n;
    4 
    5 j = jiffies;
    6 
    7 stamp_1 = j + HZ;
    8 stamp_half = j + HZ/2;
    9 stamp_n = j + n * HZ / 1000;
    时间比较

    只要采用正确的方式来比较不同的值,上述代码不会因为jiffies的溢出而出现问题;比较缓存时间和当前时间,应该使用下面宏:

     1 #define time_after(a,b)        
     2     (typecheck(unsigned long, a) && 
     3      typecheck(unsigned long, b) && 
     4      ((long)((b) - (a)) < 0))
     5 #define time_before(a,b)    time_after(b,a)
     6 
     7 #define time_after_eq(a,b)    
     8     (typecheck(unsigned long, a) && 
     9      typecheck(unsigned long, b) && 
    10      ((long)((a) - (b)) >= 0))
    11 #define time_before_eq(a,b)    time_after_eq(b,a)
    用户空间时间与内核时间的转换

    用户空间的时间使用struct timeval和struct timespec来表示,为了在用户空间时间和内核时间之间进行转换,内核提供了下面的四个辅助函数:包含在<linux/jiffies.h>中

    1 unsigned long timespec_to_jiffies(const struct timespec *value)
    2 void jiffies_to_timespec(const unsigned long jiffies,
    3                        struct timespec *value)
    4 
    5 unsigned long timeval_to_jiffies(const struct timeval *value)
    6 void jiffies_to_timeval(const unsigned long jiffies,
    7                    struct timeval *value)
    访问jiffies_64

    对jiffies_64的访问不像对jiffies的访问那么直接,在64位架构上,两个变量其实是同一个变量;但是在32位架构上,对64位的访问不是原子的,必须借助一个辅助函数,该函数完成了适当的锁定:

    1 #if (BITS_PER_LONG < 64)
    2 u64 get_jiffies_64(void);
    3 #else
    4 static inline u64 get_jiffies_64(void)
    5 {
    6     return (u64)jiffies;
    7 }
    8 #endif
  • 相关阅读:
    Add Two Numbers
    Reverse Linked List II
    Reverse Linked List
    Remove Duplicates from Sorted List
    Remove Duplicates from Sorted List II
    Partition List
    Intersection of Two Linked Lists
    4Sum
    3Sum
    2Sum
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11760846.html
Copyright © 2011-2022 走看看