序言
对于嵌入式系统领域(涵盖了众多电子产品:例如智能手机、平板电脑、智能手环以及手表等),时间这一要素扮演着至关重要的角色。无论是记录日志时附带的时间戳标记、设定自动关机、进行心跳检测报告、管理日历事务还是设置闹钟,所有这些应用场景均离不开一个准确的时间管理系统。
在处理时间问题时,我们常会遇到几个核心概念,包括但不限于:硬件时钟、系统时钟、网络时钟以及时区调整与同步等。日常生活与工作中,我们经常接触到的时区包括:UTC
(协调世界时间)、GMT
(格林威治标准时间)、CST
(中央标准时间)和DST
(夏令时)。而在网络时间同步方面,我们可能会遇到的术语包括:NTP
(网络时间协议)、SNTP
(简单网络时间协议)以及NITZ
(网络标识与时间区)。本篇文章旨在对上述提及的重点概念进行全面梳理与深入剖析。
理解基本术语
在接下来的篇幅中,我们将集中讨论以上提及的几个关键术语。
2.1 时区
时区[1] 是指地球上的不同区域使用同一个时间定义。以前,人们通过观察太阳的位置(时角)决定时间,这就使得不同经度的地方的时间有所不同(地方时)。1863年,首次使用时区的概念。通过设立一个区域的标准时间部分地解决了这个问题。
时区划分规则:将全球按经线从东到西划分为24个时区,其中东、西各12个时区,每个时区跨越经度15°,0区和12区跨越东西各7.5°。规定相邻区域的时间相差1小时,这样24个时区刚好是24小时,地球自转一圈。如下图是全球时区的划分明细。常见的时区概念包括:GMT
、UTC
、CST
、DST
。
-
GMT(Greenwich Mean Time)指格林尼治标准时间,它是第一个世界时。 GMT 12:00
就是指格林尼治天文台当地的正午12:00,而GMT+8 12:00,则是指东八区的北京当地时间的12:00。格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治时)的时间。由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能和实际的太阳时相差16分钟。 -
UTC(Coordinated Universal Time)是指协调世界时,又称世界标准时间。它是以原子时为基础,由于现在世界上最精确的原子钟50亿年才会误差1秒,所以UTC时间标准非常精确。每隔几年协调世界时组织都会给世界时+1秒,让基于原子钟的世界时和基于天文学(人类感知)的格林尼治标准时间(GMT)相差不至于太大。UTC是现在世界使用的标准时间,UTC与GMT时间基本相同。 -
CST(China Standard Time)指中国标准时间。 GMT + 8 = UTC + 8 = CST
。 -
DST(Daylight Saving Time)夏令时,又称:“日光节约时制”。是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。全世界有近110个国家每年要实行夏令时。中国现在已经不再使用夏令时。
2.2 时钟
常见的几个时钟概念包括:硬件时钟、系统时钟、网络时钟。
-
硬件时钟。在嵌入式领域也就是RTC时钟(Real Time Clock)。大多采用精度较高的晶振作为时钟源。在主电源掉电时,还可以工作,需要外加电池供电。通常把集成于芯片内部的 RTC 称为片内 RTC,在芯片外扩展的 RTC 称为外部 RTC。
-
系统时钟。指软件系统的时钟。在 linux
和一些rtos
中,启动时会去读取硬件时钟(RTC),之后则独立运行。独立运行的好处对于普通用户意义不大,但对于linux
网络管理员却有很大的用处。例如,要将一个很大的网络中(跨越若干时区)的服务器同步,假如位于美国纽约的linux
服务器和北京的Linux服务器,其中一台服务器无须改变硬件时钟而只需临时设置一个系统时间,如要将北京服务器上的系统时间设置为纽约时间,两台服务器完成文件的同步后,再与原来的硬件时钟同步一下即可。这样系统时钟和硬件时钟就提供了更为灵活的操作。 -
网络时钟。网络时钟的时间源来自于专业授时的服务器(SNTP、NTP)。实现方案是在网络上指定若干时钟源服务器,为用户提供授时服务,并且这些服务器之间能够相互比较校正,以提高准确度。在移动蜂窝网络中,基站也可以通过无线网络向移动设备提供本地日期和时间、时区、夏时制偏移。网络时钟的精度一般都很高,可以达到毫秒级,可以用来对嵌入式设备进行时间同步。
2.3 时间同步
时间同步对嵌入式设备很重要,一些功能业务甚至依赖于时间信息来完成。如自注册DM业务,需要周期性的向运营商服务器上报信息,这些信息上报都是以天或者是月为周期,不可能靠软件timer
来实现。和此类似的功能都需要以标准时间为基准,以此完成条件的触发。下面来探讨时间同步的话题。
2.3.1 SNTP
SNTP是简单网络时间协议(Simple Network Time protocol)的简称,它是目前Internet
网上实现时间同步的一种重要工程化方法。SNTP
由NTP
改编而来,SNTP
其实是NTP
的子集,只是NTP
可以 分发和授时,而SNTP
只有授时没有分发,也就是说你只能从SNTP
获取时间,其他的什么都做不了,SNTP
简化了NTP
的全部流程,这样节约成本,但只能同步一个时间源。SNTP
协议采用客户端/服务器的工作方式。SNTP
服务器通过接收GPS
信号或自带的原子钟作为系统的时间基准。SNTP
客户端(嵌入式设备)能够通过定期访问SNTP
服务器获得准确的时间信息,用于调整客户端自身所在系统的时间,达到同步时间的目的。在linux
系统中一般有现成的SNTP客户端可以安装使用,在其他的嵌入式平台上需要移植或自主开发。一些可用的SNTP服务器汇总如下(亲测可以ping通):
-
国家授时中心 NTP 服务器:ntp.ntsc.ac.cn -
阿里云公共 NTP 服务器:time.pool.aliyun.com -
腾讯云公共 NTP 服务器:time1.cloud.tencent.com -
教育网(高校自建)服务器:ntp.sjtu.edu.cn
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秒开始到当前的秒数。
-
读取当前秒数(以1970年1月1日0点0分0秒为计算起点);
book@zhang.c:~$ date +%s
1653752545
-
读系统时间: date
;
book@zhang.c:~$ date
Sat May 28 22:41:26 CST 2022
-
设置系统时间: date -s "20220501 12:00:00"
,date -s
命令设置时间只会影响系统时间,不会设置RTC时间,如果需要把当前系统时间同步设置到RTC中,需要额外调用hwclock
命令;
book@zhang.c:~$ date -s "20220501 12:00:00"
Sun May 1 12:00:00 CST 2022
-
有关 rtc
时间的操作,主要是hwclock
命令使用;
#读取并打印当前的rtc时间
hwclock -r
#读取RTC时间并设置到系统时间中去
hwclock -s
#把当前的系统时间设置到RTC中
hwclock -w
#完整的设置RTC的时间可执行如下命令
date -s "20220501 12:00:00"
hwclock -w
-
date
命令格式化的显示时间,可以看如下的Command
这一列。
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和功能机)和模组产品中,SNTP
和NITZ
两种同步系统时间的策略一般都会用到。默认使用的是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 总结
-
UTC
与GMT
时间基本相同; -
硬件时钟和系统时钟同步后,会分开独立运行; -
网络时钟的精度都比较高,可以用 SNTP
或NITZ
来进行同步,尤其SNTP
时间同步精度可以达到毫秒级。 -
linux
系统的计时起点为1970年1月1日0点0分0秒,其他嵌入式系统在做网络时间同步时,也一定要确认好计时起点。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !