人們習慣用於表示時間的方法是:年、月、日、時、分、秒、毫秒、星期等等,但是在核心中,為了軟體邏輯和**的方便性,它使用了一些不同的時間表示方法,並為這些表示方法定義了相應的變數和資料結構,本節的內容就是闡述這些表示方法的意義和區別。
核心用jiffies變數記錄系統啟動以來經過的時鐘滴答數,它的宣告如下:
[cpp]view plain
copy
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進行比較時,應該使用以下輔助巨集來實現:
[cpp]view plain
copy
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和毫秒以及納秒之間的轉換:
[cpp]view plain
copy
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);
timeval由秒和微秒組成,它的定義如下:
[cpp]view plain
copy
struct timeval ;
__kernel_time_t
和 __kernel_suseconds_t 實際上都是long型的整數。gettimeofday和settimeofday使用timeval作為時間單位。
timespec由秒和納秒組成,它的定義如下:
[cpp]view plain
copy
struct timespec ;
同樣地,核心也提供了一些輔助函式用於jiffies、timeval、timespec之間的轉換:
[cpp]view plain
copy
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);
[cpp]view plain
copy
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作為時間單位。
linux的通用時間架構用ktime來表示時間,為了相容32位和64位以及big-little endian系統,ktime結構被定義如下:
[cpp]view plain
copy
union ktime tv;
#endif
};
64位的系統可以直接訪問tv64欄位,單位是納秒,32位的系統則被拆分為兩個字段:sec和nsec,並且照顧了大小端的不同。高精度定時器通常用ktime作為計時單位。下面是一些輔助函式用於計算和轉換:
[cpp]view plain
copy
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);
Linux時間子系統之二 表示時間的單位和結構
人們習慣用於表示時間的方法是 年 月 日 時 分 秒 毫秒 星期等等,但是在核心中,為了軟體邏輯和 的方便性,它使用了一些不同的時間表示方法,並為這些表示方法定義了相應的變數和資料結構,本節的內容就是闡述這些表示方法的意義和區別。1.jiffies 核心用jiffies變數記錄系統啟動以來經過的時鐘...
Linux時間子系統之時間的表示
在linux核心中,為了相容原有的 或者符合某種規範,並且還要滿足當前精度日益提高的要求,實現了多種與時間相關但用於不同目的的資料結構 核心用jiffies 64全域性變數記錄系統自啟動以來經過了多少次tick。它的宣告如下 位於kernel time timer.c中 visible u64 ji...
linux 時間子系統 二 時間系統的組成
時間輪是linux kernel處理核心低精度定時器的機制,由週期的定時器中斷驅動。定時器中斷以配置的hz引數為頻率產生,在中斷中更新系統時間jiffies,摘取到期的定時器執行,更新時間輪時間。clock source 硬體計數器的一種抽象,它為系統提供一種時間線,通過時間線,每乙個動作都可以確定...