參考位址:
http://blog.csdn.net/jk110333/article/details/8177285
http://blog.chinaunix.net/uid-23629988-id-3477143.html
補碼的說明:
http://baike.baidu.com/link?url=qz8yHnVCqqKWguIDLOfcRZDBfLy4h1ekzspS7Rkznu8RdvMYm0QnK_vhBTHP_SSQRzV--lhiGS7lF32fB4xC5q
說明:
計算機位數限制,能表示的數值範圍也是有限的;比如129在8位的計算機中,表示為1000 0001,按有符号數讀取的話就是-127,無符号讀取就是129.
是以在判斷結果是否小于0的時候,應該看存儲的二進制的最高位是否為1.
比如127-(-3)=130,雖然看起來是個正數,但是在8位計算機中,以有符号數讀取的話就是負數,因為130存儲為1000 0010.
Linux核心為了解決jiffies的回繞問題,提供了現成的宏,用于判斷時間的先後。今天就以time_after為例,看看它為什麼可以應對jiffies的回繞問題。
/*
* These inlines deal with timer wrapping correctly. You are
* strongly encouraged to use them
* 1. Because people otherwise forget
* 2. Because if the timer wrap changes in future you won't have to
* alter your driver code.
*
* time_after(a,b) returns true if the time a is after time b.
* Do this with "<0" and ">=0" to only test the sign of the result. A
* good compiler would generate better code (and a really good compiler
* wouldn't care). Gcc is currently neither.
*/
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(b) - (long)(a) < 0))
這個宏定義很簡單,可以忽略typecheck,其就是用于檢查參數的類型是否正确。如這裡就是用于判斷a和b是否為unsigned long類型。
最關鍵的就是((long)(b) - (long)(a) < 0)。
在理想的情況下,時間是可以不停增長的,後來的時間值一定比前面的值大。是以b-a一定小于0。然後計算機的世界不是一個理想的世界,
所有的值都有其位數限制的。在32位平台上,long的位數為32位。按照二進制補碼的表示方式,從0到0x7fffffff的區間,值是逐漸遞增的。
從0x80000000到0xFFFFFFFF這個區間,值是逐漸縮小的。
這就有4中情況:
1. a和b都在0到0x7FFFFFFF之間:
a若在b之後發生,則a的值大于b。那麼(long)b-(long)a<0。
2. a和b都在0x80000000到0xFFFFFFFF之間:
a若在b之後發生,b為較大的負數,a為較小的負數,那麼(long)b-(long)a<0。
3. b在0到0x7FFFFFFF之間,而a在0x80000000到0xFFFFFFFF之間:
a為負數。b-a,相當于b+(-a)。隻要a與b之間的絕對內插補點小于或等于0x80000000,則b+(-a)仍然為負數。
4. b在0x80000000到0xFFFFFFFF之間,而a在0到0x7FFFFFFF之間:
b為負數,b-a等于b+(-a)。同樣在a與b之間的絕對內插補點小于或等于0x80000000,則b+(-a)仍然為負數。
總結這四種情況,在a與b的絕對值相差不到0x80000000時,這個宏是正确的。而在利用jiffies作為時間度量和比較機關時,時間差并不會太大。
是以這個time_after可以有效的避免jiffies回繞問題。
本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sky-heaven/p/5748462.html,如需轉載請自行聯系原作者