-
2022-05-20 13:35:49
Linux时间同步
一、NTP
1、什么是NTP
NTP是用来使计算机时间同步化的一种协议,全称是Network Time Protocol。它可以在大规模的设备范围内同步矫正时间到几ms级别的精度,在网络稳定的局域网内,精度甚至可以达到微秒级别。
2、 计算机内的时间管理
2.1格林威治时间
在引入标准时间之前,文明世界的每个城市根据太阳的地方位置(见太阳时间)设置其官方时钟。 这种状况直到在英国引入铁路旅行后才发生改变,因为铁路的出现使得有可能在很长的距离上旅行足够快,要求连续重新设置时钟,因为火车在日常运行中就会通过几个城镇。为了解决这个问题,建立了格林威治平均时间(Greenwich Mean Time),做法是将英国的所有时钟设置为相同的时间, 同时使用计时器或电报来同步这些时钟。
2.2协调世界时
1884年10月13日,在美国华盛顿召开的国际经度会议上决定,以经过英国格林尼治皇家天文台的经线为本初子午线(O°经线),作为计算地理经度的起点,也是世界标准“时区”的起点,格林尼治时间(格林尼治的地方时,GMT)正式被采用为国际标准时间(又称协调世界时,UTC)。
2.3Unix 时间戳
Unix 时间戳是一种时间表示方式,定义为从格林尼治时间 1970年01月01日 00时00分00秒 起至现在的总秒数。各种编程语言的时间戳应该指的就是这个,由此编写的各类程序涉及到的时间都以这个Unix时间戳为基准。
2.4时区
地球的自转方向为由西向东,而不是由东向西,这就导致东边的地方天亮的早,西边的地方天亮的晚,这就是所谓的“时间差”。随着近代工业革命的发展,世界各国之间的贸易逐渐繁盛起来,时间差的问题也随之浮现,特别是近代人民对时间的精确度,达到了分秒的级别,不像古人可能在交易时,会将时间设定在几月几号,一整天都是交易时间。
时间计量的混乱引起了全球各国的注意,于是在1884年,国际子午线会议在华盛顿召开,大会经过一番商量,最终决定把地球分为24个时区,东西各12个。以东西经180度为界,以英国格林尼治天文台为轴心,向东(西)每隔15度就设定一个时区,彼此相邻的两个时区,它们之间的时间差为1小时。
即相同的格林威治时间,由西向东每隔一个时区,时间减少一个小时。2.5计算机时区
计算机系统存储的都是世界时,但由于时区的存在,需要将时间由时间戳转换各时区的时间显示。
例如:中国时间和国外的时间的时间戳都一样,但时区不同,导致时间也会不同。
计算当地时间:当地时间=UTC+时区偏移。
拿中国举例:中国位于东八区,时区偏移为(+8:00)
中国时间=UTC+8:00。date +"%Z%z" #显示时区
设置时区为东8区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
3.Linux的ntp配置
3.1 服务器NTP配置
安装ntp服务
yum install ntp -y
修改配置
vim /etc/ntp.conf
修改内容
driftfile /var/lib/ntp/drift #系统时间与BIOS事件的偏差记录 restrict default nomodify notrap nopeer noquery#不限制,所有主机都可连接这个服务器同步时间。 restrict 127.0.0.1 restrict ::1 server 服务器1ip或域名 prefer# #server 服务器2ip或域名 iburst# server 127.127.1.0 fudge 127.127.1.0 stratum 15 #这两行设置连不到上级服务器时,和本机硬件保持同步。设为0则为顶级,如果要向别的NTP服务器更新时间,请不要把它设为0 includefile /etc/ntp/crypto/pw keys /etc/ntp/keys disable monitor
权限的设定主要以restrict这个参数来设定,语法为:
restrict IP地址 mask 子网掩码 参数
说明:
IP可以是IP地址也可以是default,default是指所有的IP,默认是default,为了安全可将default替换
为网段。
参数主要有以下几个:
ignore :关闭所有的 NTP 联机服务
nomodify:客户端不能更改服务端的时间参数,但是客户端可以通过服务端进行网络校时。
notrust:客户端除非通过认证,否则该客户端来源将被视为不信任子网
noquery:不提供客户端的时间查询上级时间服务器配置
server host [ key n ] [ version n ] [ prefer ] [ mode n ] [ minpoll n ] [ maxpoll n ] [ iburst ]
说明:
其中host是上层NTP服务器的IP地址或域名,随后所跟的参数解释如下所示:
key: 表示所有发往服务器的报文包含有秘钥加密的认证信息,n是32位的整数,表示秘钥号。
version: 表示发往上层服务器的报文使用的版本号,n默认是3,可以是1或者2。
prefer: 如果有多个server选项,具有该参数的服务器优先使用。
mode: 指定数据报文mode字段的值。
minpoll: 指定与查询该服务器的最小时间间隔为2的n次方秒,n默认为6,范围为4-14。
maxpoll: 指定与查询该服务器的最大时间间隔为2的n次方秒,n默认为10,范围为4-14。
iburst: 当初始同步请求时,采用突发方式接连发送8个报文,时间间隔为2秒。启动并设置开机启动
systemctl enable ntpd systemctl start ntpd systemctl is-enabled ntpd #查看是否在开机启动项 systemctl list-unit-files | grep ntp #查看是否在开机启动项 systemctl status ntpd #查看ntpd服务的状态
扩展:
systemctl enable ntpd --now # 设置开机启动并启动服务
查看和上级服务器的同步状态
ntpq -p
结果解释见:链接: link
查看时间同步服务状态ntpstat
3.2 客户端NTP配置
3.2.1 ntp同步
安装ntp服务
yum install ntp -y
修改配置
vim /etc/ntp.conf
修改内容
driftfile /var/lib/ntp/drift #系统时间与BIOS事件的偏差记录 restrict default nomodify notrap nopeer noquery#不限制,所有主机都可连接这个服务器同步时间。 restrict 127.0.0.1 restrict ::1 server 时间服务器ip prefer includefile /etc/ntp/crypto/pw keys /etc/ntp/keys disable monitor
3.2.2 ntpdate同步
每天12点整使用ntpdate同步时间。
echo '0 12 * * * /usr/sbin/ntpdate 时间服务器ip' >> /var/spool/cron/root
3.2.3 异同
ntpdate会导致时间跳变。
ntpd服务是逐渐调整客户端时间和时间服务器保持一致。
在ntpd启动的情况下不能使用ntpdate,如要使用加-u参数:ntpdate -u ip。3.2.4 其他优化
设置ntpd服务慢同步。
据说某些版本当时间差过大时,ntpd也会跳变。加入此参数可保证一定是慢同步
vim /etc/sysconfig/ntpd
检查OPTIONS参数中是否有-x参数,如果没有需加入。
重启服务器后ntpd没开机启动
systemctl disable chronyd
要把chronyd.service 禁用
systemctl disable chronyd.service
然后systemctl enable ntp 设置开机自启生效 生效
硬件时间
更多相关内容 -
多传感器时间同步
2021-11-15 21:28:48时间同步 第一次谈及时间同步,可能会有点懵逼。其实这在我们生活中是很常见的,小时候应该都用过那种电子手表,这种电子手表往往隔一段时间就会不准确,需要手动进行校准。这种手动校准的过程就可以认为...时间同步
第一次谈及时间同步,可能会有点懵逼。其实这在我们生活中是很常见的,小时候应该都用过那种电子手表,这种电子手表往往隔一段时间就会不准确,需要手动进行校准。这种手动校准的过程就可以认为是时间同步。想想看,若是没有时间同步,那可真是乱了套了,想要在家看个世界杯,都不能及时的和别人分享进球的喜悦,这这这…是不是也太难受了…
好了,下面就重点来说说多传感器的时间同步。多传感器数据的时间同步是多传感器信息融合的必备条件之一。实际上,由于各个传感器独立封装并按照自己的时钟基准运行,往往采样频率也不尽不同,这些将导致种采样数据时间上不同步。针对这一问题有硬同步和软同步两种解决方案。硬件同步是指定制传感器,使得多个传感器能在同一时刻触发采样,例如多个传感器安装于同一个晶振下工作。软件同步是指通过统一的主机给各个传感器提供基准时间,使得传感器每帧数据同步到统一的时间戳上。
1.1 软同步
软件同步的方法主要就是利用时间戳进行不同传感器的匹配。通常是将各传感器数据统一到扫描周期较长(频率较小)的传感器数据上。拿某4线激光雷达(采样频率约12.5Hz)和某相机(采样频率约30Hz)来说明,显然记过雷达的周期大,则以激光雷达的采样频率为基准进行匹配,如下图所示:
图中绿色虚线框表示激光雷达采集频率,蓝色虚线框表示相机采集频率,横轴表示统一的时间戳。传感器的每个采样时刻记录在统一的时间序列上。当激光雷达完成一次采样时,寻找与该时刻最近邻时刻的图像,这样便完成了两种数据的时间匹配,如图中红色方框所示。
可以看出,这种时间同步的方式可能存在一些问题:上文红色字体所述的最近邻时刻较为模糊,若最近邻的时刻同样和激光雷达采样时间差距较大,那最终的时间同步的效果肯定不好;另一方面,如若随着需要进行时间同步的传感器越来越多,那么匹配的难度必然加大,匹配的精度也大大折扣。这时候可能就需要别的方法来支持时间同步了,硬件同步就油然而生。
1.2 硬同步
硬同步主要是通过GNSS进行授时的,传感器自身集成了GPS通信接口,可以接收一些数据和信号。目前使用较多的是使用PTP协议解决各传感器设备时间同步的问题。
首先先来介绍一下PTP协议,其是基于数据包的时间同步协议。数据传输和时间同步使用同一网络,它描述了如何在基于数据包网络(比如以太网)上分配同步时间的机制。时钟精度达到亚微秒级。PTP是一种主从式的时间同步系统,采用硬件时间戳,因此可以大幅减少软件处理时间。同时PTP可运行在L2层(MAC层)和L4层(UDP层),运行在L2层网络时,直接在MAC层进行报文解析,不用经过四层UDP协议栈,从而大幅减少协议栈驻留时间,进一步提高时间同步精度,对于自动驾驶系统来说非常友善。
好了,是不是没怎么看懂,我也是。我觉得姑且可以认为这种方法还是蛮不错的,可以较好的完成时间同步的任务。下面具体阐述通过PTP协议进行时间同步的过程。
还是先来对一些基本概念进行一个了解。设备中运行PTP协议的网络端口称为PTP端口,PTP主端口用来发布时间,PTP从端口用来接收时间。同时还定义了如下三种始终节点:
PTP通过在主从设备之间交互同步报文,并记录下报文发送时间,从而计算网络传输延迟和主从设备间时钟的偏差。PTP定义了四条同步报文:Sync、Follow_Up、Delay_Req、Delay_Resp,精确同步过程如下。
1、PTP主端口向从端口发送Sync报文,同步记录下Sync发送的时间t1。从端口收到Sync报文后,记录下收到的时间t2。
2、紧接着主端口将t1时间放到Follow_Up报文发送给从端口,从端口收到此报文后就可以解析出t1,并由此得到第一个方程式:t1+网络延时+时钟偏差=t2。
3、从端口向主端口发送Delay_Req报文,同步记录下Delay_Req发送的时间t3。主端口收到报文后,记录下收到的时间t4。
4、紧接着主端口将t4时间放到Delay_Resp报文发送给从端口,从端口收到此报文后就可以解析出t4,并由此得到第一个方程式:t3+网络延时-时钟偏差=t4。
上文红色公式有两个未知数,两个方程组,应用初中数学知识可以解出:网络延时Delay=[(t2-t1)+(t4-t1)]/2,时钟偏差Offset=[(t2-t1)-(t4-t3)]/2。
知道了Delay和Offset就能对传感器的时间进行调整,从而进行传感器的时间同步。
咻咻咻咻~~duang~~点个赞呗
参考文章: https://zhuanlan.zhihu.com/p/135938786
https://mp.weixin.qq.com/s/zE32DmNAVthRBlPXK9OA3w -
C语言实现的NTP, 可时间同步
2015-01-28 10:17:09PC端可用时间同步ntp,交叉编译到板子上未测试, 配置文件格式ip@132.163.4.2@ip -
网络时间同步机制
2022-03-12 19:00:32android 7.1网络时间同步机制流程解析网络时间同步机制
系统版本:android7.1
涉及类
//监控网络时间并更新系统时间策略类 NetworkTimeUpdateService.java //与远程 NTP 服务器连接,获取网络时间 NtpTrustedTime.java //真正接受网络时间的类 SntpClient.java
NetworkTimeUpdateService解析
NetworkTimeUpdateService启动流程
NetworkTimeUpdateService是在SystemServer.java里面的startOtherServices方法中创建的,分别调用NetworkTimeUpdateService的构造方法和systemReady方法,最终网络同步系统时间服务启动完成。
private void startOtherServices() { ... NetworkTimeUpdateService networkTimeUpdater = null; ... //初始化时间同步服务 networkTimeUpdater = new NetworkTimeUpdateService(context); //添加到binder管理 ServiceManager.addService("network_time_update_service", networkTimeUpdater); ... final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater; mActivityManagerService.systemReady(new Runnable() { ... try { if (networkStatsF != null) networkStatsF.systemReady(); } catch (Throwable e) { reportWtf("making Network Stats Service ready", e); } ... } }
NetworkTimeUpdateService构造方法解析
主要的工作内容- 创建NtpTrustedTime对象,该对象用于获取网络时间。
- 设置更新时间的广播Intent
- 获取framework/base/core/res/res/value/config.xml中的配置信息
//继承Binder,这样就可以添加到ServiceManager中 public class NetworkTimeUpdateService extends Binder { public NetworkTimeUpdateService(Context context) { mContext = context; //用于连接ntp服务器,获取网络时间 mTime = NtpTrustedTime.getInstance(context); //获取AlarmManager对象,用来设置系统时间 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); //com.android.server.NetworkTimeUpdateService.action.POLL广播 Intent pollIntent = new Intent(ACTION_POLL, null); //设置请求更新时间广播 mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0); //24小时 mPollingIntervalMs = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpPollingInterval); //1分钟 mPollingIntervalShorterMs = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpPollingIntervalShorter); //3次 mTryAgainTimesMax = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpRetry); //5秒 mTimeErrorThresholdMs = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpThreshold); //持有唤醒锁 mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, TAG); } }
systemReady解析
主要的工作内容- 创建sim同步运营商同步时间监听。
- 创建com.android.server.NetworkTimeUpdateService.action.POLL广播监听。
- 创建网络变化广播监听
- 创建带handler的子线程,用于后面获取网络时间和同步时间到系统中
- 发送同步时间广播,执行开机后第一次时间同步
- 设置SettingsObserver对象监听Settings.Global.AUTO_TIME属性变化,就是系统设置里面那个是否开启同步时间的设置项修改的值。
/** Initialize the receivers and initiate the first NTP request */ public void systemRunning() { //注册sim同步时间监听 registerForTelephonyIntents(); //注册com.android.server.NetworkTimeUpdateService.action.POLL广播 registerForAlarms(); //注册网络变化广播 registerForConnectivityIntents(); //创建带handler的子线程 HandlerThread thread = new HandlerThread(TAG); thread.start(); mHandler = new MyHandler(thread.getLooper()); //同步时间 // Check the network time on the new thread mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget(); //监听Settings.Global.AUTO_TIME变化 mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED); mSettingsObserver.observe(mContext); }
其中registerForTelephonyIntents()要说明下,该方法监听的广播收到会改变mNitzTimeSetTime的值,但是不是更新系统时间,该ACTION_NETWORK_SET_TIME和ACTION_NETWORK_SET_TIMEZONE广播是sim卡同步运营商时间时,设置系统时间后再发出来的,故发送广播之前就同步时间,感兴趣可以在系统源码中搜索下ACTION_NETWORK_SET_TIME广播是哪里发的就可以找到同步的地方了。
private void registerForTelephonyIntents() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME); intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE); mContext.registerReceiver(mNitzReceiver, intentFilter); } /** Receiver for Nitz time events */ private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (DBG) Log.d(TAG, "Received " + action); if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) { mNitzTimeSetTime = SystemClock.elapsedRealtime(); } else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) { mNitzZoneSetTime = SystemClock.elapsedRealtime(); } } };
除了sim广播外,其他监听触发后都是给handler发送消息同步时间。先看下NetworkTimeUpdateService中的Handler类。
private class MyHandler extends Handler { public MyHandler(Looper l) { super(l); } @Override public void handleMessage(Message msg) { switch (msg.what) { case EVENT_AUTO_TIME_CHANGED: case EVENT_POLL_NETWORK_TIME: case EVENT_NETWORK_CHANGED: //msg.what表示触发导致的同步时间 onPollNetworkTime(msg.what); break; } } }
最终调用的的onPollNetworkTime方法
onPollNetworkTime方法的主要工作内容:- 判断Settings.Global.AUTO_TIME属性是否不为零,即自动同步时间开关是否打开,若没打开就停止同步流程。
- 调用onPollNetworkTimeUnderWakeLock,执行同步时间策略。
private void onPollNetworkTime(int event) { //判断是否启动时间统同步 // If Automatic time is not set, don't bother. if (!isAutomaticTimeRequested()) return; //获取唤醒锁 mWakeLock.acquire(); try { onPollNetworkTimeUnderWakeLock(event); } finally { mWakeLock.release(); } }
onPollNetworkTimeUnderWakeLock的主要工作内容如下:
- 判断是否sim同步过时间,并且同步的时间间隔不超过24h,是的话停止同步,等待24小时候再同步,防止多次同步。
- ntp没有同步过时间或者距离上次同步时间超过24小时,或者Settings.Global.AUTO_TIME改变,则开始时间同步,否则再等24小时同步时间。
- 调用NtpTrustedTime的forceRefresh方法获取ntp时间。
- 调用NtpTrustedTime的currentTimeMillis方法获取从ntp服务上获取的时间。
- 调用SystemClock.setCurrentTimeMillis将同步的时间设置到系统中。
- 若forceRefresh获取时间失败会另外有3次机会从ntp上获取时间,间隔5秒,三次都失败了则再过24小时同步时间。
private void onPollNetworkTimeUnderWakeLock(int event) { final long refTime = SystemClock.elapsedRealtime(); //sim卡时间同步过,并且同步时时间不到24小时 // If NITZ time was received less than mPollingIntervalMs time ago, // no need to sync to NTP. if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) { resetAlarm(mPollingIntervalMs); return; } final long currentTime = System.currentTimeMillis(); if (DBG) Log.d(TAG, "System time = " + currentTime); //没有同步过时间,或者上次时间同步超过24小时,或者Settings.Global.AUTO_TIME属性改变引起的 // Get the NTP time if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs || event == EVENT_AUTO_TIME_CHANGED) { if (DBG) Log.d(TAG, "Before Ntp fetch"); //距上次同步时间过了24小时获取没有同步过 // force refresh NTP cache when outdated if (mTime.getCacheAge() >= mPollingIntervalMs) { //重新获取网络时间 mTime.forceRefresh(); } //距离上次时间小于24小时,说明同步时间成功,24小时内同步过一次 // only update when NTP time is fresh if (mTime.getCacheAge() < mPollingIntervalMs) { //获取ntp时间 final long ntp = mTime.currentTimeMillis(); mTryAgainCounter = 0; // If the clock is more than N seconds off or this is the first time it's been // fetched since boot, set the current time. if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs || mLastNtpFetchTime == NOT_SET) { // Set the system time if (DBG && mLastNtpFetchTime == NOT_SET && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) { Log.d(TAG, "For initial setup, rtc = " + currentTime); } if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp); // Make sure we don't overflow, since it's going to be converted to an int if (ntp / 1000 < Integer.MAX_VALUE) { //设置系统时间 SystemClock.setCurrentTimeMillis(ntp); } } else { if (DBG) Log.d(TAG, "Ntp time is close enough = " + ntp); } //更新mLastNtpFetchTime属性 mLastNtpFetchTime = SystemClock.elapsedRealtime(); } else { //说明同步时失败,没5秒同步一次,同步三次,三次后再过24小时 // Try again shortly mTryAgainCounter++; if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) { resetAlarm(mPollingIntervalShorterMs); } else { // Try much later mTryAgainCounter = 0; resetAlarm(mPollingIntervalMs); } return; } } resetAlarm(mPollingIntervalMs); }
NtpTrustedTime与SntpClient解析
前面已经研究完同步策略了,下面讲下,如何系统是如何与ntp服务器联系并且获取到网络时间的。先讲下NtpTrustedTime,该类是个单例,所以从它的getInstance方法讲起。主要做如下工作:
- 获取ntp服务器的地址和连接超时时间。
- 创建NtpTrustedTime对象,将ntp服务器的地址和连接超时时间和地址传入进去。
private NtpTrustedTime(String server, long timeout) { if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server); mServer = server; mTimeout = timeout; } public static synchronized NtpTrustedTime getInstance(Context context) { if (sSingleton == null) { final Resources res = context.getResources(); final ContentResolver resolver = context.getContentResolver(); //默认ntp服务器地址 2.android.pool.ntp.org final String defaultServer = res.getString( com.android.internal.R.string.config_ntpServer); //5秒 final long defaultTimeout = res.getInteger( com.android.internal.R.integer.config_ntpTimeout); final String secureServer = Settings.Global.getString( resolver, Settings.Global.NTP_SERVER); final long timeout = Settings.Global.getLong( resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout); final String server = secureServer != null ? secureServer : defaultServer; sSingleton = new NtpTrustedTime(server, timeout); sContext = context; } return sSingleton; }
解析获取网络时间方法forceRefresh,主要工作如下:
- 判断设备是否有网。
- 创建SntpClient对象,用于获取网络时间的。
- 向ntp请求网络时间。
- 获取网络请求的时间进行保存。
public boolean forceRefresh() { ... //设备是否有网 final NetworkInfo ni = mCM == null ? null : mCM.getActiveNetworkInfo(); if (ni == null || !ni.isConnected()) { if (LOGD) Log.d(TAG, "forceRefresh: no connectivity"); return false; } if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); //创建SntpClient对象,用于获取网络时间的 final SntpClient client = new SntpClient(); //向ntp请求网络时间 if (client.requestTime(mServer, (int) mTimeout)) { //表示有缓冲 mHasCache = true; //将SntpClient获取的网络时间同步过来 mCachedNtpTime = client.getNtpTime(); //记录相应ntp后的机器开机后的时间 mCachedNtpElapsedRealtime = client.getNtpTimeReference(); mCachedNtpCertainty = client.getRoundTripTime() / 2; return true; } else { return false; } }
NetworkTimeUpdateService中有调用NtpTrustedTime的getCacheAge和currentTimeMillis,我们依次解析下
public long getCacheAge() { //mHasCache为false表示之前没有同步过时间 if (mHasCache) { //获取距离上次同步时间的间隔 return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime; } else { return Long.MAX_VALUE; } } public long currentTimeMillis() { if (!mHasCache) { throw new IllegalStateException("Missing authoritative time source"); } if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit"); //计算出当前时间放回给调用者。 // current time is age after the last ntp cache; callers who // want fresh values will hit makeAuthoritative() first. return mCachedNtpTime + getCacheAge(); }
最后解析下SntpClient对象,真正与ntp服务其对接的逻辑都在这个类里面,才有socket通信。该类构造方法是默认构造方法,没有自己定义,我们直接解析它的requestTime方法。主要内容
- 根据host地址创建InetAddress对象。
- 创建DatagramSocket对象,用于ntp服务器通讯。
- 创建请求对象DatagramPacket的类对象request。
- 调用DatagramSocket对象的send方法,将请求传递给ntp服务器。
- 创建接收ntp服务器信息的DatagramPacket的类对象response。
- 调用socket.receive方法,将ntp服务器里的信息传递给response。
- response里面的信息赋值給SntpClient各个参数,供NtpTrustedTime调用。
public boolean requestTime(String host, int timeout) { InetAddress address = null; try { //根据host创建网络地址 address = InetAddress.getByName(host); } catch (Exception e) { if (DBG) Log.d(TAG, "request time failed: " + e); return false; } //设置地址和端口以及超时时间 return requestTime(address, NTP_PORT, timeout); } public boolean requestTime(InetAddress address, int port, int timeout) { DatagramSocket socket = null; try { //创建数据报socket对象 socket = new DatagramSocket(); socket.setSoTimeout(timeout); byte[] buffer = new byte[NTP_PACKET_SIZE]; //创建请求 DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, port); // set mode = 3 (client) and version = 3 // mode is in low 3 bits of first byte // version is in bits 3-5 of first byte buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3); // get current time and write it to the request packet final long requestTime = System.currentTimeMillis(); final long requestTicks = SystemClock.elapsedRealtime(); writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime); //发送请求 socket.send(request); // read the response DatagramPacket response = new DatagramPacket(buffer, buffer.length); //获取服务返回数据 socket.receive(response); //设置参数 final long responseTicks = SystemClock.elapsedRealtime(); final long responseTime = requestTime + (responseTicks - requestTicks); // extract the results final byte leap = (byte) ((buffer[0] >> 6) & 0x3); final byte mode = (byte) (buffer[0] & 0x7); final int stratum = (int) (buffer[1] & 0xff); final long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET); final long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET); final long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET); /* do sanity check according to RFC */ // TODO: validate originateTime == requestTime. checkValidServerReply(leap, mode, stratum, transmitTime); long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime); // receiveTime = originateTime + transit + skew // responseTime = transmitTime + transit - skew // clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2 // = ((originateTime + transit + skew - originateTime) + // (transmitTime - (transmitTime + transit - skew)))/2 // = ((transit + skew) + (transmitTime - transmitTime - transit + skew))/2 // = (transit + skew - transit + skew)/2 // = (2 * skew)/2 = skew long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2; if (DBG) { Log.d(TAG, "round trip: " + roundTripTime + "ms, " + "clock offset: " + clockOffset + "ms"); } // save our results - use the times on this side of the network latency // (response rather than request time) mNtpTime = responseTime + clockOffset; mNtpTimeReference = responseTicks; mRoundTripTime = roundTripTime; } catch (Exception e) { if (DBG) Log.d(TAG, "request time failed: " + e); return false; } finally { if (socket != null) { socket.close(); } } return true; }
-
关于车载 时间同步 的理解
2021-08-22 10:17:231. 时间同步的应用场景 2.时间同步协议的理解 2.1 请求应答机制同步原理 2.2 端延时机制同步原理 3.基于Autosar CAN时间同步 3.1 同步流程 3.2 CAN同步消息结构 3.3 基于CAN消息的实际...目录
1. 时间同步的应用场景
考虑自动驾驶/ADAS领域,这类控制器,一般包含各类的传感器,如ODO,GPS,地图,摄像头,毫米波雷达,超声波雷达等,因此这些传感器数据精确的采集时间显得尤为重要,因为直接关系到最后做传感器融合以及决策规划,因此必须保证精确使用哪一个时刻的数据。
2.IEEE1588 时间同步协议的理解
车载里面,常用的时间同步协议是 IEEE 1588 即所谓的PTP( precise time protocol,精确时间协议),下面就针对PTP进行详细解释说明。
IEEE 1588 是精确时间同步协议,精度可以达到微秒级,以下针对其时间同步原理说明。
2.1 请求应答机制同步原理
如图所示,包含主时钟和从时钟,主时钟是发送时钟的节点,所有节点和它对比,进行时间同步。
主要过程分为四步:
(1)Sync,主时钟发出 sync 报文,并记录下 sync 报文离开主时钟的精确发送时间 T1;
(2)Follow_up,主时钟将精确发送时间 T1 封装到 Follow_up 报文中,发送给从时钟;
(3)Delay_Req,从时钟向主时钟,发送Delay_Req报文,用于方向传输延时计算,并记录发送时刻T3,主时钟收到该报文后,记录接收时刻T4;
(4)Delay_Resp,主时钟收到Delay_Req后,回复一个Delay_Resp的报文,将T4告诉从时钟。
从第二张图,我们可以清晰的看到,从时钟已经精确知道T1 ,T2,T3,T4四个时刻。
主-->从,发送传输延时 T2-T1;
从-->主,发送传输延时 T4-T3;
但是以上的计算是基于主时钟和从时钟同步的场景,真实情况是主时钟和从时钟存在偏差,我们假设这个偏差为offset,即 T主-T从 = offset。
在网络中,一般主-->从,从-->主 网络延时是一样;
T4 - T3 = delay - offset;
T2 - T 1 = delay+ offset;
因此传递的延时 :
delay = [(T2-T1) + (T4-T3)] / 2
由于offset存在,映射到从时钟 时间轴上计算offset:
offset = [(T2-T1) - (T4-T3)] / 2
这里offset 很好理解的一点是,T2 - T1 = offset+delay 记住这一点就好理解。
考虑到是否需要Follow_up报文,这里有分为单步模式和双步模式;
所谓的单步模式,是没有Follow_up报文,T1的时间戳,直接由sync 报文发出;
所谓的双步模式,即有Follow_up报文,T1的时间戳,由Follow_up报文携带。
2.2 端延时机制同步原理
所谓的端延时机制,是在请求响应延时的基础上,增加pdelay_resp和Pdelay_resp_follow_up的计算,主要是为了进一步考虑上游链路的延时;
进而得到delay:
delay = [(T4-T3) + (T6-T5)] / 2
进而得到offset:
offset = (T2-T1) - {[(T4-T3) + (T6-T5)] / 2}
这里offset 很好理解的一点是,T2 - T1 = offset+delay
当然这里根据是否需要follow_up 报文,也可以分为单步模式或双步模式,不进一步说明。
3.基于Autosar CAN时间同步
CAN的时间同步和上文提到的IEEE1588 区别较大,请注意区分。
3.1 同步流程
Autosar中专门用于CAN 时间同步的模块是CanTSyn,同步的流程如下图
第一步. Master在t1r时刻先发送一个SYNC信号,但这个信号写的是之前要发送SYNC时的时间点(t0r),然后在t2r时刻Slave接收到了这个SYNC信号。
第二步. Master再次发送一个FUP信号,这个信号的内容就是他t1r-t0r的值。
第三步. 最后在Slave方,我们就可以计算出本地当下的同步时间值=(t3r-t2r)+t1r
3.2 CAN同步消息结构
以不带CRC的为例说明
SYNC报文,这里Byte4~7放入我们需要同步的时间
FUP报文 ,这里Byte4~7放入我们需要同步的时间
这里需要特别注意的是,SYNC和FUP共用一个CAN ID,他们只是type不一样。
3.3 基于CAN消息的实际用法
首先,在SYNC报文中,塞入基于秒的时间,即所谓的t0r;
然后,在FUP报文中,塞入基于纳秒的时间,即所谓的t4r = t1r - t0r,此时从节点知道,发送方真实的发送时刻为 t1r ,即t0r秒t4r纳秒
这样 从节点就可以得到当前真实的时间,current_time = t0r + t4r + t3r-t2r
这里t3r,表示计算时刻,从节点本地的时间。
下文是原文,意思同上面提到的表述是一个意思,有兴趣的可以仔细查看。
4.基于Autosar 以太网时间同步
4.1 Autosar 以太网时间同步说明
Autosar中,以太网同步模块是EthTSyn,Autosar以太网的时间同步,与IEEE 1588 / IEEE802.1AS稍有不同,主要不同点是,Autosar时间同步:
- 定义ECU的优先级
- 只考虑静态配置情况
整体架构如下图
4.2 Autosar 以太网时间同步原理
计算过程参考IEEE 1588/IEEE 802.1AS;
4.3 Autosar 以太网时间同步消息格式
参考Autosar标准即可,此处不做展开。
-
机器人&自动驾驶中的时间同步
2021-09-26 15:22:090.时间同步技术介绍 对于自动驾驶技术的实现,涉及到感知、规划、执行三个层面。由于车辆行驶在未知动态环境中,需要事先构建出环境地图并在地图中进行自我定位,这其中涉及到各传感器数据的精确时间同步。然后根据... -
windows 2016 域服务器时间同步
2021-10-29 11:52:50设置NTP服务器,和外网时间同步。以下是设置步骤: 修改PDC主域控制器上同步Internet时间服务器: 1.主域控制器修改 运行gpedit.msc 打开本地策略组(Winserver2012和2016应该是一样的),路径为:计算机配置->... -
windows7 internet系统时间同步出错超时怎么办?国内NTP时间同步服务器地址
2021-01-11 20:11:56下面跟我一起来解决win7 Internet系统时间同步出错的这个问题吧,顺便给大家一些速度比较快的国内NTP时间同步服务器地址,以便大家成功同步系统时间。windows 7系统 Internet 系统时间同步出错... -
centos7时间同步
2021-07-02 16:05:47NTP 是网络时间协议(Network Time Protocol)的简称,就是通过网络协议使计算机之间的时间同步化。 时区管理 查看当前时区 timedatectl 查看当前可用时区 timedatectl list-timezones 设置时区 timedatectl... -
debian时间同步_如何在Debian 10上设置时间同步
2020-08-10 11:35:39debian时间同步 介绍 (Introduction) Accurate timekeeping has become a critical component of modern software deployments. Whether it’s making sure logs are recorded in the right order or database ... -
linux时间同步,ntpd、ntpdate
2020-12-24 10:33:32一、window与linux系统时间介绍在Windwos中,系统时间的...但在Linux下,默认情况下,系统时间和硬件时间,并不会自动同步。在Linux运行过程中,系统时间和硬件时间以异步的方式运行,互不干扰。硬件时间的运行,... -
Linux配置NTP时间同步
2021-07-12 14:55:05网络时间同步协议,就是用来同步网络中各个计算机的时间的协议。 2. NTP服务端配置 1.检查系统是否安装了NTP包(linux系统一般自带NTP4.2),没有安装我们直接使用yum命令在线安装: yum install ntp 2.NTP服务端... -
xp电脑时间同步出错该怎么解决?电脑时间同步错误解决方法
2021-08-06 05:02:05WinXP系统时间总是与网络...接下来,小编就xp系统时间同步出错分享该问题的具体解决方法。电脑时间同步错误的解决方法如下:1.打开运行对话框(通常按win+R组合键打开),输入w32tm/register注册。2.接着在对话框中输... -
5G的高精度时间同步服务器网络实现方案
2020-05-06 11:49:57摘要:讨论面向5G的同步支撑网在网络架构、同步精度、安全性、可靠性、监测性等方面的需求,介绍一种基于光纤的高精度时间同步网的实现方案,并给出经过现网1300km、19个节点传递的时间同步测试结果。利用该方案既... -
ntp时间同步
2022-04-03 11:31:10操作系统:需要时钟同步的操作系统Centos7 网络环境:离线 时钟服务器:winserver2019 openssl: OpenSSL 1.0.2k-fips 26 Jan 2017(尝试过低版本未成功) winserver 时钟服务器 设置: 参考连接:Windows10... -
linux怎么查看硬件时间同步
2021-05-09 06:35:54有时候想查看Linux的时间同步,不知道该怎么办,下面是学习啦小编带来的关于linux怎么查看硬件时间同步的内容,欢迎阅读!linux怎么查看硬件时间同步?linux的系统时钟在很多地方都要用到,要是不准,就会出现一些奇怪... -
Linux系统时间同步
2022-01-22 11:34:37文章目录Linux系统时间同步一、第一步:搭建用于时间同步的服务器1.1 先安装npt模块:`sudo yum -y install ntp`1.2 写配置文件`/etc/npt.conf`1.3 启动ntp服务二、第二步:在需要同步时间服务器上进行时间同步2.1 ... -
linux时间同步,ntpd、ntpdate 【转】
2020-12-24 10:33:35但在Linux下,默认情况下,系统时间和硬件时间,并不会自动同步。在Linux运行过程中,系统时间和硬件时间以异步的方式运行,互不干扰。硬件时间的运行,是靠Bios电池来维持,而系统时间,是用... -
西门子PLC如何设NTP网络时间同步(全解)
2021-12-02 17:22:46西门子PLC如何设NTP网络时间同步(全解) -
centos 设置时间同步
2021-01-17 14:52:511、安装ntpdate,一般情况下都自带了,执行一下也无妨yum install -y ntpdate2、停止ntpdate服务/etc/init.d/ntpdate stop3、手动执行时间同步/usr/sbin/ntpdate ntp.fudan.edu.cn如果出现如下类似信息,表示成功13 ... -
centos时间同步方案
2021-08-06 10:14:161.时间同步策略 A.针对跳板机登录 Zabbix server作为时间服务器,它同步阿里云时间服务器时间,各地市跳板机作为该地市的时间服务器,它同步zabbix server时间,该地市其他服务器从该跳板机同步时间 同步网络时间... -
电脑时间同步,小编教你怎么让电脑时间和网络时间同步
2021-06-22 22:38:13对于怎么让电脑时间和网络时间同步这个问题,小编觉得是我们要学会的,因为我们或许会经常遇到这样的问题,所以还是预防一下为好。下面小编就来和你们说说怎么让电脑时间和网络时间同步。有的时候我们会发现电脑的... -
Win10时间同步出错怎么办 Win10时间同步出错解决方法
2021-08-12 06:53:15Win10系统的时间一般通过时间同步更加准确,毕竟系统时间是否准确是很重要的,但是一些用户反馈win10时间同步出错,那么遇到这样的问题时要如何解决呢,其实win10时间同步出错主要是由于时间同步服务器无法连接,... -
linux实现时间同步有哪几种方法
2021-05-14 15:37:07Linux实现时间同步的方法的有两种,分别是:1、使用ntpdate从时间服务器来更新时间,不需要自己做任何配置;2、使用ntp来搭建自己的时间服务器。【推荐课程:Linux系统】由于硬件的原因,机器或多或少的跟标准时间对... -
hadoop集群时间同步
2022-03-02 09:49:29生产环境:如果服务器能连接外网,不需要时间同步;如果服务器连接不了外网,需要时间同步 查看所有节点ntpd服务状态和开机自启动状态 [amelia@hadoop102 ~]$ sudo systemctl status ntpd [amelia@hadoop102 ~]$ ... -
ntp时间服务器——时间同步
2020-08-08 20:29:492、本地服务器较多,在本地自建时间同步服务器 时间同步的两个命令: ntpd : 校准时间,一点点的校准过来时间的,最终把时间慢慢的校正对。ntpd服务可以在修正时间的同时,修正cpu tick。ntpd有一个自我保护设置: ... -
Linux配置ntp时间同步
2021-09-04 15:37:46apt-get install chrony -y 修改配置文件vi /etc/chrony/chrony.conf 注释掉自带的ntp服务器,配置本机作为NTP服务器 server 本机IP地址 iburst 取消stratum所在行的注释 allow 0/0 #配置哪些机器可以同步,... -
PTP(IEEE1588),TSN时间同步方法
2021-07-16 16:31:16本文首先简要介绍主流的时间同步方式GNSS,NTP,PTP。然后通过NTP和PTP对比,解释PTP性能更优秀的原因;并对算法公式进行了推导。 -
华为悦盒主时间同步服务器地址
2021-08-11 09:24:18华为悦盒主时间同步服务器地址 内容精选换一换华为云存储容灾服务(简称SDRS)提供了虚拟机级别的容灾保护,当主站点故障的时候,虚拟机可以在备站点迅速恢复,以确保业务的联系性来自:产品边缘节点既可以是物理机,...