linux中應用層(非內核層)time是怎樣處理的?時區是怎樣設置的?夏令時時是怎樣實現的?NTP時間同步是怎么回事?本篇文章就在嵌入式linux應用中time和timezone相關問題總結。
1. NTP
經常說時間同步,同步就是為了獲取統一的時間參考點。同步的時間來自授時中心,如ntp.pool.org。那NTP同步的時間是什么時間,包含時區嗎?
NTP同步的時間是UTC-0時間,所有授時中心的時間都是UTC-0時間。NTP遵循NTPv4協議,通過時間偏差來調整本地基准(或參考時間,由time()或gettimeofday()獲取)。
2. time
linux應用中的基准時間是?
通過man7 time可知UNIX systems represent time in seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)。
A program can determine the calendar time using gettimeofday(2), which returns time (in seconds and microseconds) that have elapsed since the Epoch;
time(2) provides similar information, but only with accuracy to the nearest second.
When interpreted as an absolute time value, it represents the number of seconds elapsed since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
time()或gettimeofday()返回的時間是日歷時間,也是絕對時間,是unix系統應用基准時間。該時間表示自Epoch, 1970-01-01 00:00:00 +0000 (UTC)過去的秒數(或微妙數),與時區無關。
所有系統在同一時間調用time()返回值都一樣(除去誤差),不管在什么時區,是否采用夏令時。
time()返回time_t,是絕對秒數。
gettimeofday()返回struct timeval,包含tv_sec絕對秒數,tv_usec絕對微妙數。 兩個函數均是系統調用。
3. timezone
時區設置由libc庫函數tzset()實現,其讀取並解析文件/etc/TZ或環境變量TZ,將時區、是否采用夏令時保存到靜態變量中,供localtime_r()轉換本地時間時調用。
void tzset (void);
extern char *tzname[2];
extern long timezone;
extern int daylight;
這些都是庫函數,包含在頭文件time.h中。
4. broken-down time分解時間
broken-down time由struct tm存儲,包含年月日周天時分秒。最典型由localtime()函數獲取,其為本地化時間(已轉換為系統時區時間,並由變量tm_isdst指定是否支持夏令時)。
localtime_r()是libc庫函數,調用time()將其返回的時間轉換為本地時間,其轉換包含時區信息。
5. 字符串時間
雖然localtime()包含可識別的時間,但不便於打印,需要轉換為字符串。
strftime()按指定格式打印時間,asctime()按標准格式打印時間。
6. date
date顯示的是本地時間(包含時區信息),底層實現調用localtime_r()(busybox實現)。也就是說date將絕對時間顯示為本地時間,其根據時區調整顯示時間。這樣,上層應用(如時區更換)時換算更簡單(都以絕對時間為參考)。
根據以上分析,無論時區是否改變,是否采用夏令時,日歷時間(或絕對時間)都不會改變。當設置的時區中包含夏令時時間段時,當夏令時時間切換時,上層應用調用localtime_r()自動將時間切換為夏令時時間。
附:時間轉換經典配圖
附:時間相關概念,轉自linux編程中與時間相關的問題總結
-
GMT:Greenwich Mean Time,格林尼治平均時。格林尼治標准時間是19世紀中葉大英帝國的基准時間,同時也是事實上的世界基准時間。
-
UTC:Universal Time Coordinated,環球通用協調時間。基本上UTC的本質強調的是比GMT更為精確的世界時間標准,在不需要精確到秒的情況通常也將GMT和UTC視作等同。
-
DST:Daylight Saving Time,指在夏天太陽升起的比較早時,將時鍾撥快一小時以提早日光的使用;
-
CST:CST可以同時表示美國UT-6:00,澳大利亞UT+9:30,中國UT+8:00,古巴UT-4:00四個國家的標准時間;
-
Epoch:時間軸上特定的一個時間點,定義為從格林威治時間1970年01月01日00時00分00秒。記為1970年1月1日00:00:00 UTC。
-
UNIX時間戳:英文表示為Unix timestamp、Unix time或者POSIX time。是從Epoch開始所經過的秒數,不考慮閏秒。在大多數的UNIX系統中UNIX時間戳存儲為32位,這樣會引發2038年問題或Y2038。
-
Calendar Time:表示的意義同UNIX時間戳。
-
Broken-down Time:使用tm結構存儲的時間,tm 數據結構將時間分別保存到代表年,月,日,時,分,秒等不同的變量中,不再是一個令人費解的64位整數。tm數據結構是各種自定義格式轉換函數所需要的輸入形式。
-
Real-Time:也稱wall-clock,即我們人類自然感受的時間。
-
Virtual-Time:進程執行所占用的cpu時間(即站在進程的角度看時間),如果在過去的一秒鍾指定進程沒有被調用,則virtual time為0s,real time為1s。
-
Prof-Time:系統在用戶態和內核態所占用cpu時間的總和;
-
clock tick:時鍾滴答,當PIT通道0的計數器減到0值時,它就在IRQ0上產生一次時鍾中斷,即一次時鍾滴答。
-
jiffies:記錄着從電腦開機到現在總共的”時鍾中斷”的次數。啟動時內核將該變量初始化為0,此后每次時鍾中斷處理程序都會增加該變量的值。jiffies類型為無符號長整型(unsigned long),其他任何類型存放它都不正確。
-
xtime:從cmos電路或rtc芯片中取得的時間,一般是從某一歷史時刻開始到現在的時間;
參考:
3. time函數
5. NTP協議