假设我们有以下代码:

if (timeout > jiffies)
{
    /* we did not time out, good ... */
}
else
{
    /* we timed out, error ...*
}

当jiffies值不溢出时,此代码可以正常工作。
但是,当jiffies溢出并回零时,此代码将无法正常工作。

Linux显然提供了用于处理此溢出问题的宏
#define time_before(unknown, known) ((long)(unkown) - (long)(known) < 0)

并且上面的代码在替换为该宏后应该可以防止溢出:
// SAFE AGAINST OVERFLOW
if (time_before(jiffies, timeout)
{
    /* we did not time out, good ... */
}
else
{
    /* we timed out, error ...*
}

但是,time_before(和其他time_宏)背后的原理是什么?

time_before(jiffies,timeout)将扩展为
((long)(jiffies) - (long)(timeout) < 0)

此代码如何防止溢出问题?

最佳答案

让我们实际尝试一下:

#define time_before(unknown, known) ((long)(unkown) - (long)(known) < 0)

我会说long只有两个字节来简化很多事情,因此十六进制的值可以在[0, 0xFFFF]范围内。

现在,它已签名,因此可以将范围[0,0xFFFF]分为两个单独的范围[0,0x7FFF],[0x8000,0xFFFF]。这些对应于值[0,32767],[-32768,-1]。这是一个图:
[0x0      -              -                  -               0xFFFF]
[0x0                       0x7FFF][0x8000                   0xFFFF]
[0                         32,767][-32,768                      -1]

假设timeout是32,000。我们想检查是否在超时范围内,但实际上我们溢出了,所以jiffies是-31,000。因此,如果我们天真地尝试评估jiffies < timeout,我们将得到True。但是,插入值:
   time_before(jiffies, offset)
== ((long)(jiffies) - (long)(offset) < 0)
== (-31000 - 32000 < 0)             // WTF is this. Clearly NOT -63000
== (-31000 - 1768 - 1 - 30231 < 0)  // simply expanded 32000
== (-32768 - 1 - 30232 < 0)         // this -1 causes an underflow
== (32767 - 30232 < 0)
== (2535 < 0)
== False
jiffies是4个字节,而不是2个字节,但适用相同的原理。这些帮助有用?

关于c - Linux如何处理Jiffies中的溢出?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8206762/

10-10 05:37