人們習慣用於表示時間的方法是:年、月、日、時、分、秒、毫秒、星期等等,但是在核心中,為了軟體邏輯和代碼的方便性,它使用了一些不同的時間表示方法,並為這些表示方法定義了相應的變數和資料結構,本節的內容就是闡述這些表示方法的意義和區別。
/*****************************************************************************************************/
聲明:本博內容均由http://blog.csdn.net/droidphone原創,轉載請註明出處,謝謝!
/*****************************************************************************************************/
1. jiffies
核心用jiffies變數記錄系統啟動以來經過的時鐘滴答數,它的聲明如下:
extern u64 __jiffy_data jiffies_64;extern unsigned long volatile __jiffy_data jiffies;
可見,在32位的系統上,jiffies是一個32位的無符號數,系統每過1/HZ秒,jiffies的值就會加1,最終該變數可能會溢出,所以核心同時又定義了一個64位的變數jiffies_64,連結的指令碼保證jiffies變數和jiffies_64變數的記憶體位址是相同的,通常,我們可以直接存取jiffies變數,但是要獲得jiffies_64變數,必須通過輔助函數get_jiffies_64來實現。jiffies是核心的低精度定時器的計時單位,所以核心配置的HZ數決定了低精度定時器的精度,如果HZ數被設定為1000,那麼,低精度定時器(timer_list)的精度就是1ms=1/1000秒。因為jiffies變數可能存在溢出的問題,所以在用基於jiffies進行比較時,應該使用以下輔助宏來實現:
time_after(a,b)time_before(a,b)time_after_eq(a,b)time_before_eq(a,b)time_in_range(a,b,c)
同時,核心還提供了一些輔助函數用於jiffies和毫秒以及納秒之間的轉換:
unsigned int jiffies_to_msecs(const unsigned long j);unsigned int jiffies_to_usecs(const unsigned long j);unsigned long msecs_to_jiffies(const unsigned int m);unsigned long usecs_to_jiffies(const unsigned int u);
2. struct timevaltimeval由秒和微秒組成,它的定義如下:
struct timeval {__kernel_time_ttv_sec;/* seconds */__kernel_suseconds_ttv_usec;/* microseconds */};
__kernel_time_t 和__kernel_suseconds_t 實際上都是long型的整數。gettimeofday和settimeofday使用timeval作為時間單位。
3. struct timespectimespec由秒和納秒組成,它的定義如下:
struct timespec {__kernel_time_ttv_sec;/* seconds */longtv_nsec;/* nanoseconds */};
同樣地,核心也提供了一些輔助函數用於jiffies、timeval、timespec之間的轉換:
static inline int timespec_equal(const struct timespec *a, const struct timespec *b);static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs);static inline int timeval_compare(const struct timeval *lhs, const struct timeval *rhs);extern unsigned long mktime(const unsigned int year, const unsigned int mon, const unsigned int day, const unsigned int hour, const unsigned int min, const unsigned int sec);extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec);static inline struct timespec timespec_add(struct timespec lhs,struct timespec rhs);static inline struct timespec timespec_sub(struct timespec lhs,struct timespec rhs);static inline s64 timespec_to_ns(const struct timespec *ts);static inline s64 timeval_to_ns(const struct timeval *tv);extern struct timespec ns_to_timespec(const s64 nsec);extern struct timeval ns_to_timeval(const s64 nsec);static __always_inline void timespec_add_ns(struct timespec *a, u64 ns);
unsigned long timespec_to_jiffies(const struct timespec *value);void jiffies_to_timespec(const unsigned long jiffies, struct timespec *value);unsigned long timeval_to_jiffies(const struct timeval *value);void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value);
timekeeper中的xtime欄位用timespec作為時間單位。
4. struct ktimelinux的通用時間架構用ktime來表示時間,為了相容32位和64位以及big-little endian系統,ktime結構被定義如下:
union ktime {s64tv64;#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)struct {# ifdef __BIG_ENDIANs32sec, nsec;# elses32nsec, sec;# endif} tv;#endif};
64位的系統可以直接存取tv64欄位,單位是納秒,32位的系統則被拆分為兩個欄位:sec和nsec,並且照顧了大小端的不同。高精度定時器通常用ktime作為計時單位。下面是一些輔助函數用於計算和轉換:
ktime_t ktime_set(const long secs, const unsigned long nsecs); ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs); ktime_t ktime_add(const ktime_t add1, const ktime_t add2); ktime_t ktime_add_ns(const ktime_t kt, u64 nsec); ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec); ktime_t timespec_to_ktime(const struct timespec ts); ktime_t timeval_to_ktime(const struct timeval tv); struct timespec ktime_to_timespec(const ktime_t kt); struct timeval ktime_to_timeval(const ktime_t kt); s64 ktime_to_ns(const ktime_t kt); int ktime_equal(const ktime_t cmp1, const ktime_t cmp2); s64 ktime_to_us(const ktime_t kt); s64 ktime_to_ms(const ktime_t kt); ktime_t ns_to_ktime(u64 ns);