假设我们有以下代码:
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/