Jiffies计数器返回一个大小为4字节的无符号整数。 当计数器达到最大值时,再次从0重新开始。 我会用旧值减去最新的值来获得持续时间。 那么我应该如何考虑这样的情况,即当旧的价值是最大的价值,新的价值大于零,这样我会得到错误的持续时间?
您不必做任何事情,只要您使用四个字节的无符号整数进行所有计算,就会有正确的持续时间。 这是以固定宽度二进制算法实现的整数值的魔力。
这是一个8位无符号整数的例子。 你甚至可以看到,即使有溢出,差异仍然有效。
236 - 221 = 11101100 - 11011101 = 11101100 + 00100011 = 00001111 = 15 251 - 236 = 11111011 - 11101100 = 11111011 + 00010100 = 00001111 = 15 10 - 251 = 00001010 - 11111011 = 00001010 + 00000101 = 00001111 = 15 25 - 10 = 00011001 - 00001010 = 00011001 + 11110110 = 00001111 = 15 ...
当计数器的持续时间不小于计数器的最大值时,即当计数器的值可能大于最大值的一半时,就会出现单个问题。
这个建议只有在你的两个事件a和b,a实际发生在b之前,它们之间的距离小于2 ^(32-1)时才是正确的。 如果你计算(ba),那么你得到正确的答案。 如果你从较大的无符号数中减去较小的无符号数(认为定义了它们的时间顺序),那么你可以得到你想要的答案的否定。
所以,你也需要考虑一个新的循环比较操作(参见Linux time_after,time_before并使用它们等)。
无论是有符号还是无符号比较都是错误的,因为环绕的计数器与有符号或无符号数不完全一样。 考虑8位的情况:
a=250, b=20 #8-bit sequence number a was created before b a=120, b=130 #8-bit sequence number a was created before b
比较运算符的实现与具有相同比特数的有符号和无符号值之间的主要区别在于。 由于决定使用1或0来扩展负值,所以当赋值为更多位时,带符号和无符号的符号很重要。
考虑一个新的定义,少于为环绕的数字设计的:
LT_CIRCULAR_32(250,5) == True //like signed? LT_CIRCULAR_32(0,11) == True LT_CIRCULAR_32(127,138) == True //like unsigned?
只要第一个值和第二个值之间的实际距离总是小于2 ^(32-1),就可以进行比较。
想象一个有256个位置的圆圈,而计数器a和b顺时针前进。 如果a以小于2 ^(8-1)的增量达到b,则“a <b”。 这是一个比较考虑,它既没有签名也没有签名:
#define LT_CIRCULAR_LONG(a,b) ((((long)(b)-(long)(a)) < 0)==0)
这就是为什么time_after看起来如此。 b和a的投射分别确保符号延伸一致。 对一个值进行签名并检查小于零是测试高位的技巧。
我现在正在和jiffies(即:-300 jiffies)一起看这个问题的开发者协议,并且看到了TCP序列号和其他一些类似的计数器。 所以,2s恭维不处理所有这一切。