參考地址:html
http://blog.csdn.net/jk110333/article/details/8177285app
http://blog.chinaunix.net/uid-23629988-id-3477143.htmlui
補碼的說明:this
http://baike.baidu.com/link?url=qz8yHnVCqqKWguIDLOfcRZDBfLy4h1ekzspS7Rkznu8RdvMYm0QnK_vhBTHP_SSQRzV--lhiGS7lF32fB4xC5qurl
說明:spa
計算機位數限制,能表示的數值範圍也是有限的;好比129在8位的計算機中,表示爲1000 0001,按有符號數讀取的話就是-127,無符號讀取就是129..net
因此在判斷結果是否小於0的時候,應該看存儲的二進制的最高位是否爲1.unix
好比127-(-3)=130,雖然看起來是個正數,可是在8位計算機中,以有符號數讀取的話就是負數,由於130存儲爲1000 0010.code
Linux內核爲了解決jiffies的迴繞問題,提供了現成的宏,用於判斷時間的前後。今天就以time_after爲例,看看它爲何能夠應對jiffies的迴繞問題。 orm
/*
* 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迴繞問題。