jiffies的回绕问题

什么是jiffies

          在Linux内核中有一个全局变量jiffies,这个变量被定义在<linux/jiffies.h>文件中。这个全局变量是被用来记录系统启动以来产生的节拍的总数。在内核启动的时候,内核将这个变量初始化为0.此后,每次时钟中断时,这个值就会增加1.而每一秒内要中断的次数是HZ。所以系统的运行时间是jiffies/HZ。

回绕问题的产生

   在Linux系统中,对jiffies有不同的声明。

#define __jiffy_data  __attribute__((section(".data")))
/*
 * The 64-bit value is not atomic - you MUST NOT read it
 * without sampling the sequence number in jiffies_lock.
 * get_jiffies_64() will do this for you as appropriate.
 */
extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

           对于32位机器使用的声明是unsigned long volatile __jiffy_data jiffies,这个变量unisigned long,是一个32位的无符号数。而对于64位机器是无符号的64位无符号数。由于jiffies在使用中用的最多的是存放流失的时间,所以只关心底32位。如果要得到jiffies_64可以通过函数:

u64 get_jiffies_64(void);

           在64位机器中,jiffies只会访问jiffies_64的低32位地址空间。

jiffies的回绕问题

         由于jiffies变量是可能发生溢出的,对于32位无符号长整型来说它的最大值为2^32 - 1,所以jiffies的最大值也就是4294967295.如果这个值再增加的话就会回到0然后一次增加。

    如果单纯的比较大小是不准确的,如下面代码:

unisgned long timeout = jiffies + HZ/2; /*0.5秒后超时*/
/*执行任务*/
/*查看时间是否超过*/
if (jiffies < timeout){
            /*没有超时*/
} else {
           /*超时了*/
}

jiffies回绕问题的解决方法

    对于jiffies的回绕问题,Linux内核是通过4个宏定义来解决的

#define time_after(a,b)        \
    (typecheck(unsigned long, a) && \
     typecheck(unsigned long, b) && \
     ((long)((b) - (a)) < 0))
#define time_before(a,b)    time_after(b,a)

#define time_after_eq(a,b)    \
    (typecheck(unsigned long, a) && \
     typecheck(unsigned long, b) && \
     ((long)((a) - (b)) >= 0))
#define time_before_eq(a,b)    time_after_eq(b,a)


    如果现在将代码修改成下面这样:

unisgned long timeout = jiffies + HZ/2; /*0.5秒后超时*/
/*执行任务*/
/*查看时间是否超过*/
if (time_before(jiffies , timeout){
            /*没有超时*/
} else {
           /*超时了*/
}

          现在就不可能再次产生回绕了,在看上面的宏时我们会发现里面是用的long,而不是声明时的unsigned long。这一步就是不会产生回绕的关键步骤。原因如下:

    我们都知道long是有符号的数据,它的正数范围是[0-0x7FFFFFFF],负数是:[0x80000000-0xFFFFFFFF]之间。

(1)如果a和b都是在正数范围,也就是0~0x7FFFFFFF之间的话,并且a > b,这时,(long)((b) - (a)) 是小于0的。

(2)如果a和b都是负数范围,a本来是大于b,但是在负数中是a小于b,所以就出现了(long)((b) - (a))还是小于0。

(3)如果a在[0-0x7FFFFFFF],而b在[0x80000000-0xFFFFFFFF],这时(long)((b) - (a))还是小于0。

(4)如果a在[0x80000000-0xFFFFFFFF],a在[0-0x7FFFFFFF]之间。这时(long)((b) - (a))还是会小于0。

    通过上面的time_before或者是time_after都是可以绕开jiffies绕回问题的。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值