嵌入式開發中,幾個時間概念?

我生待明日,萬事成蹉跎。—— 明 · 錢福《明日歌》

1 前言

在嵌入式系統中 (包括大部分電子設備:手機、平板、手環、手錶等等),時間的概念非常重要。如打印 log 時的時間戳、定時關機、心跳上報、日曆功能、鬧鐘等等。上述這些功能都需要一個相對精確的時間系統。

經常涉及的與時間相關的術語包括:硬件時鐘系統時鐘網絡時鐘時區修改和同步。日常生活和工作中可能接觸到的時區概念包括:UTCGMTCSTDST。在網絡時間中可能接觸到的概念又有:NTPSNTPNITZ。本文將會對上述涉及到的概念進行系統的整理和探討。

2 瞭解概念

下面對幾個概念進行集中陳述。

2.1 時區

時區 [1] 是指地球上的不同區域使用同一個時間定義。以前,人們通過觀察太陽的位置(時角)決定時間,這就使得不同經度的地方的時間有所不同(地方時)。1863 年,首次使用時區的概念。通過設立一個區域的標準時間部分地解決了這個問題。

時區劃分規則: 將全球按經線從東到西劃分爲 24 個時區,其中東、西各 12 個時區,每個時區跨越經度 15°,0 區和 12 區跨越東西各 7.5°。規定相鄰區域的時間相差 1 小時,這樣 24 個時區剛好是 24 小時,地球自轉一圈。如下圖是全球時區的劃分明細。常見的時區概念包括:GMTUTCCSTDST

2.2 時鐘

常見的幾個時鐘概念包括:硬件時鐘系統時鐘網絡時鐘

2.3 時間同步

時間同步對嵌入式設備很重要,一些功能業務甚至依賴於時間信息來完成。如自注冊 DM 業務,需要週期性的向運營商服務器上報信息,這些信息上報都是以天或者是月爲週期,不可能靠軟件timer來實現。和此類似的功能都需要以標準時間爲基準,以此完成條件的觸發。下面來探討時間同步的話題。

2.3.1 SNTP

SNTP 是簡單網絡時間協議 (Simple Network Time protocol) 的簡稱,它是目前Internet網上實現時間同步的一種重要工程化方法。SNTPNTP改編而來,SNTP其實是NTP的子集,只是NTP可以 分發和授時,而SNTP只有授時沒有分發,也就是說你只能從SNTP獲取時間,其他的什麼都做不了,SNTP簡化了NTP的全部流程,這樣節約成本,但只能同步一個時間源。SNTP協議採用客戶端 / 服務器的工作方式。SNTP服務器通過接收GPS信號或自帶的原子鐘作爲系統的時間基準。SNTP客戶端 (嵌入式設備) 能夠通過定期訪問SNTP服務器獲得準確的時間信息,用於調整客戶端自身所在系統的時間,達到同步時間的目的。在linux系統中一般有現成的 SNTP 客戶端可以安裝使用,在其他的嵌入式平臺上需要移植或自主開發。一些可用的 SNTP 服務器彙總如下 (親測可以 ping 通):

2.3.2 NITZ

NITZ(Network Identity and Time Zone)是一種通過無線網絡向移動設備提供本地日期和時間、時區、夏時制偏移,以及網絡提供商身份信息的機制,這通常用於無線蜂窩網絡設備 (手機、通信模組) 的自動更新系統時間。對於其他網絡時間協議,NITZ 的質量和執行力度都相對較弱。有些運營商根本就不支持,例如在國內,本地測試 (廣東) 發現,中國移動和中國電信是支持NITZ的,中國聯通就根本不支持。再者,與SNTP相比,SNTP授時能使時間分辨率達到毫秒級,NITZ則 “對於時間只能精確到數分鐘”。但NITZ不用連上互聯網,能駐上無線蜂窩網絡就行,而SNTP必須連接互聯網。

3 應用

3.1 linux 中時間命令

linux 命令中的date命令是用來設置和查詢系統時間的,而hwclock命令是用來設置和讀寫RTC時間 (硬件時間)。有一點需要注意,linux的時間系統是由「新紀元時間」Epoch 開始計算起,單位爲秒,Epoch 則是指定爲 1970 年 1 月 1 日 0 點 0 分 0 秒,格林威治時間 (GMT)。date +%s命令可以讀取從 1970 年 1 月 1 日 0 點 0 分 0 秒開始到當前的秒數。

book@zhang.c:~$ date +%s
1653752545
book@zhang.c:~$ date
Sat May 28 22:41:26 CST 2022
book@zhang.c:~$ date -s "20220501 12:00:00"
Sun May  1 12:00:00 CST 2022
#讀取並打印當前的rtc時間
hwclock -r
#讀取RTC時間並設置到系統時間中去
hwclock -s 
#把當前的系統時間設置到RTC中
hwclock -w     
#完整的設置RTC的時間可執行如下命令
date -s "20220501 12:00:00"
hwclock -w
        Format/result           |       Command              |          Output
--------------------------------+----------------------------+------------------------------
YYYY-MM-DD                      | date -I                    | $(date -I)
YYYY-MM-DD_hh:mm:ss             | date +%F_%T                | $(date +%F_%T)
YYYYMMDD_hhmmss                 | date +%Y%m%d_%H%M%S        | $(date +%Y%m%d_%H%M%S)
YYYYMMDD_hhmmss (UTC version)   | date --utc +%Y%m%d_%H%M%SZ | $(date --utc +%Y%m%d_%H%M%SZ)
YYYYMMDD_hhmmss (with local TZ) | date +%Y%m%d_%H%M%S%Z      | $(date +%Y%m%d_%H%M%S%Z)
YYYYMMSShhmmss                  | date +%Y%m%d%H%M%S         | $(date +%Y%m%d%H%M%S)
YYYYMMSShhmmssnnnnnnnnn         | date +%Y%m%d%H%M%S%N       | $(date +%Y%m%d%H%M%S%N)
YYMMDD_hhmmss                   | date +%y%m%d_%H%M%S        | $(date +%y%m%d_%H%M%S)
Seconds since UNIX epoch:       | date +%s                   | $(date +%s)
Nanoseconds only:               | date +%N                   | $(date +%N)
Nanoseconds since UNIX epoch:   | date +%s%N                 | $(date +%s%N)
ISO8601 UTC timestamp           | date --utc +%FT%TZ         | $(date --utc +%FT%TZ)
ISO8601 UTC timestamp + ms      | date --utc +%FT%T.%3NZ     | $(date --utc +%FT%T.%3NZ)
ISO8601 Local TZ timestamp      | date +%FT%T%Z              | $(date +%FT%T%Z)
YYYY-MM-DD (Short day)          | date +%F\(%a\)             | $(date +%F\(%a\))
YYYY-MM-DD (Long day)           | date +%F\(%A\)             | $(date +%F\(%A\))

3.2 SNTP 和 NITZ

在手機 (包括 Android 和功能機) 和模組產品中,SNTPNITZ兩種同步系統時間的策略一般都會用到。默認使用的是 NITZ 來獲取網絡時間,但是需要有運營商的支持才能使用 (中國聯通就不支持),而有些設備產品只支持 WIFI 等無線網絡,而不支持移動網絡,此時就需要採用SNTP方式來獲取網絡時間進行同步了。SNTP協議時間戳是以 1900 年 1 月 1 日 0 點 0 分 0 秒爲起點,而linux時間戳從 1970 年 1 月 1 日 0 點 0 分 0 秒開始記秒數,即記錄到SNTP結構體中的時間包含了 JAN_1970(從 1900 到 1970 共 70 年的秒數)。在拿到SNTP時間後,往 linux 同步時間時,需要減掉 JAN_1970。

4 總結

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Rm9w7TxhTDGAtFKnokjaMA