精华内容
下载资源
问答
  • 时间同步
    千次阅读
    2022-05-20 13:35:49

    一、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 设置开机自启生效 生效

    硬件时间

    链接: 计算机时间到底是怎么来的?程序员必看的时间知识!

    链接: Linux 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:09
    PC端可用时间同步ntp,交叉编译到板子上未测试, 配置文件格式ip@132.163.4.2@ip
  • 网络时间同步机制

    千次阅读 2022-03-12 19:00:32
    android 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构造方法解析

    主要的工作内容

    1. 创建NtpTrustedTime对象,该对象用于获取网络时间。
    2. 设置更新时间的广播Intent
    3. 获取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解析

    主要的工作内容

    1. 创建sim同步运营商同步时间监听。
    2. 创建com.android.server.NetworkTimeUpdateService.action.POLL广播监听。
    3. 创建网络变化广播监听
    4. 创建带handler的子线程,用于后面获取网络时间和同步时间到系统中
    5. 发送同步时间广播,执行开机后第一次时间同步
    6. 设置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方法的主要工作内容:

    1. 判断Settings.Global.AUTO_TIME属性是否不为零,即自动同步时间开关是否打开,若没打开就停止同步流程。
    2. 调用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的主要工作内容如下:

    1. 判断是否sim同步过时间,并且同步的时间间隔不超过24h,是的话停止同步,等待24小时候再同步,防止多次同步。
    2. ntp没有同步过时间或者距离上次同步时间超过24小时,或者Settings.Global.AUTO_TIME改变,则开始时间同步,否则再等24小时同步时间。
    3. 调用NtpTrustedTime的forceRefresh方法获取ntp时间。
    4. 调用NtpTrustedTime的currentTimeMillis方法获取从ntp服务上获取的时间。
    5. 调用SystemClock.setCurrentTimeMillis将同步的时间设置到系统中。
    6. 若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方法讲起。主要做如下工作:

    1. 获取ntp服务器的地址和连接超时时间。
    2. 创建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,主要工作如下:

    1. 判断设备是否有网。
    2. 创建SntpClient对象,用于获取网络时间的。
    3. 向ntp请求网络时间。
    4. 获取网络请求的时间进行保存。
     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方法。主要内容

    1. 根据host地址创建InetAddress对象。
    2. 创建DatagramSocket对象,用于ntp服务器通讯。
    3. 创建请求对象DatagramPacket的类对象request。
    4. 调用DatagramSocket对象的send方法,将请求传递给ntp服务器。
    5. 创建接收ntp服务器信息的DatagramPacket的类对象response。
    6. 调用socket.receive方法,将ntp服务器里的信息传递给response。
    7. 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:23
    1. 时间同步的应用场景 2.时间同步协议的理解 2.1 请求应答机制同步原理 ​​​​​ 2.2 端延时机制同步原理 ​​​​ 3.基于Autosar CAN时间同步 3.1 同步流程 3.2 CAN同步消息结构 3.3 基于CAN消息的实际...

    目录

    1. 时间同步的应用场景

    2.时间同步协议的理解

    2.1 请求应答机制同步原理    ​​​​​

     2.2 端延时机制同步原理    ​​​​

    3.基于Autosar CAN时间同步

    3.1 同步流程

    3.2 CAN同步消息结构

    3.3 基于CAN消息的实际用法

     4.基于Autosar 以太网时间同步

    4.1 Autosar 以太网时间同步说明

    4.2 Autosar 以太网时间同步原理

    4.3 Autosar 以太网时间同步消息格式


    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:09
    0.时间同步技术介绍 对于自动驾驶技术的实现,涉及到感知、规划、执行三个层面。由于车辆行驶在未知动态环境中,需要事先构建出环境地图并在地图中进行自我定位,这其中涉及到各传感器数据的精确时间同步。然后根据...
  • windows 2016 域服务器时间同步

    千次阅读 2021-10-29 11:52:50
    设置NTP服务器,和外网时间同步。以下是设置步骤: 修改PDC主域控制器上同步Internet时间服务器: 1.主域控制器修改 运行gpedit.msc 打开本地策略组(Winserver2012和2016应该是一样的),路径为:计算机配置->...
  • 下面跟我一起来解决win7 Internet系统时间同步出错的这个问题吧,顺便给大家一些速度比较快的国内NTP时间同步服务器地址,以便大家成功同步系统时间。windows 7系统 Internet 系统时间同步出错...
  • centos7时间同步

    千次阅读 2021-07-02 16:05:47
    NTP 是网络时间协议(Network Time Protocol)的简称,就是通过网络协议使计算机之间的时间同步化。 时区管理 查看当前时区 timedatectl 查看当前可用时区 timedatectl list-timezones 设置时区 timedatectl...
  • debian时间同步 介绍 (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服务端...
  • WinXP系统时间总是与网络...接下来,小编就xp系统时间同步出错分享该问题的具体解决方法。电脑时间同步错误的解决方法如下:1.打开运行对话框(通常按win+R组合键打开),输入w32tm/register注册。2.接着在对话框中输...
  • 摘要:讨论面向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网络时间同步(全解)
  • centos 设置时间同步

    千次阅读 2021-01-17 14:52:51
    1、安装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:16
    1.时间同步策略 A.针对跳板机登录 Zabbix server作为时间服务器,它同步阿里云时间服务器时间,各地市跳板机作为该地市的时间服务器,它同步zabbix server时间,该地市其他服务器从该跳板机同步时间 同步网络时间...
  • 对于怎么让电脑时间和网络时间同步这个问题,小编觉得是我们要学会的,因为我们或许会经常遇到这样的问题,所以还是预防一下为好。下面小编就来和你们说说怎么让电脑时间和网络时间同步。有的时候我们会发现电脑的...
  • Win10系统的时间一般通过时间同步更加准确,毕竟系统时间是否准确是很重要的,但是一些用户反馈win10时间同步出错,那么遇到这样的问题时要如何解决呢,其实win10时间同步出错主要是由于时间同步服务器无法连接,...
  • linux实现时间同步有哪几种方法

    千次阅读 2021-05-14 15:37:07
    Linux实现时间同步的方法的有两种,分别是: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:49
    2、本地服务器较多,在本地自建时间同步服务器 时间同步的两个命令: ntpd : 校准时间,一点点的校准过来时间的,最终把时间慢慢的校正对。ntpd服务可以在修正时间的同时,修正cpu tick。ntpd有一个自我保护设置: ...
  • Linux配置ntp时间同步

    千次阅读 2021-09-04 15:37:46
    apt-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)提供了虚拟机级别的容灾保护,当主站点故障的时候,虚拟机可以在备站点迅速恢复,以确保业务的联系性来自:产品边缘节点既可以是物理机,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,502,749
精华内容 601,099
关键字:

时间同步