【时间同步】时间同步 —— 纳秒级高精度

gps时间同步 —— 纳秒级高精度

需求:ubuntu系统,写个c++代码。实现实时收毫秒数,定时检查所收毫秒数与当前时间系统差,若超过2秒,则将当前所收到的毫秒数设置为系统时间。

可参考的代码:

double seconds = pva->gps_week * SECONDS_PER_WEEK + pva->gps_seconds

详细说明:

收一个毫秒数,这个毫秒数是收一个从1980年开始到现在的一个周数,加从本周日到现在的秒数。

写一个函数嵌套到已有的大代码里,转换成当前时间,然后设置为系统时间。

每隔一段时间进行检查,检查的方式是将收到的毫秒数与当前系统时间进行对比,如果差得比较多,就执行更新系统时间。


需要做的是:

  1. 保存最近的GPS时间:每次接收到新的GPS时间时,保存最新的GPS周数和秒数。

  2. 定期检查并调整系统时间:可以在这个文件中加入一个定时任务或者循环,定期检查保存的GPS时间和系统时间的差异,如果差异超过阈值(比如2秒),则调用相应的系统调用或命令来更新系统时间。

由于老代码通常位于更复杂的项目中,你可能需要考虑以下几点:

  • 线程安全:如果老代码是多线程的,确保任何新加入的代码也遵循相同的线程安全规则。
  • 性能影响:频繁地检查和更新系统时间可能会影响程序的性能,尤其是如果更新系统时间的操作较为耗时的话。
  • 错误处理:考虑到网络延迟或其他因素,GPS时间可能偶尔会出现异常值,需要有适当的错误处理机制。
  • #include <iostream>
    #include <chrono>
    #include <ctime>
    #include <thread>
    #include <signal.h>
    #include <sys/time.h>
    
    struct GPS_Time {
        uint16_t gps_week;
        uint32_t gps_millisecs;
    };
    
    // 接收GPS时间
    void receive_gps_time(GPS_Time& pva) {
        pva.gps_week = 2000; // 测试用的定值
        pva.gps_millisecs = 123456; // 测试用的定值
    }
    
    // 将GPS时间转换为UTC时间,并保留毫秒级精度
    struct timespec gps_to_utc(const GPS_Time& pva) {
        const std::time_t gps_epoch = 315964800; 
        std::time_t gps_time = gps_epoch + static_cast<std::time_t>(pva.gps_week * 604800);
        long gps_time_millisecs = static_cast<long>(pva.gps_millisecs);
        struct timespec ts;
        ts.tv_sec = gps_time + gps_time_millisecs / 1000;
        ts.tv_nsec = (gps_time_millisecs % 1000) * 1000000; 
        return ts;
    }
    
    // 直接用clock_settime函数,设置系统时间,注意需要root权限
    void set_system_time(const struct timespec& ts) {
        if (clock_settime(CLOCK_REALTIME, &ts) == -1) {
            perror("clock_settime");
        }
    }
    
    // 检查并更新系统时间
    void check_and_set_system_time() {
        GPS_Time pva;
        receive_gps_time(pva);
        
        struct timespec utc_time = gps_to_utc(pva);
        std::time_t current_time = std::time(nullptr);
        
        // 获取当前时间的毫秒部分
        struct timespec current_timespec;
        clock_gettime(CLOCK_REALTIME, &current_timespec);
        long current_millisecs = current_timespec.tv_nsec / 1000000 + current_timespec.tv_sec * 1000L;
        
        // 将UTC时间转换为毫秒
        long utc_millisecs = utc_time.tv_nsec / 1000000 + utc_time.tv_sec * 1000;
        
        if (std::abs(utc_millisecs - current_millisecs) > 2000) { 
            std::cout << "Time difference is more than 2 seconds, setting system time." << std::endl;
            set_system_time(utc_time);
        }
    }
    
    // 退出处理
    bool should_exit = false;
    
    void signal_handler(int signal) {
        should_exit = true;
    }
    
    int main() {
        signal(SIGINT, signal_handler);
        signal(SIGTERM, signal_handler);
        
        while (!should_exit) {
            check_and_set_system_time();
            std::this_thread::sleep_for(std::chrono::seconds(60)); // 每分钟检查一次
        }
        return 0;
    }

附录1:不能用的方案

方案:新建一个gpstime.txt里存储着时间,其信息格式是2024-7-15 15:40:00,写一个名为update_time.sh的脚本,用来做时间同步:功能是每隔5秒就去gpstime.txt里获取信息,然后更新系统时间

原因:延迟性


附录2:GPS时间同步 和 ntp时间同步对比

问题:从gps获得毫秒级时间,同步到系统来做时间同步  和  ntp设置上位机ip来做时间同步,哪个比较靠谱?

同步系统时间的方式各有优劣,这主要取决于你的应用场景、可用资源以及对时间精确度的需求。下面是两种方法的一些考量:

1. 从GPS获取毫秒级时间进行同步

优点:

  • 高精度: GPS提供了高度精确的时间信息,通常误差在几十纳秒到几微秒之间,非常适合需要高时间精度的应用场景,如卫星通信、金融交易系统等。
  • 自主性: 不依赖网络连接,适用于野外作业、移动平台等网络不稳定或不可用的环境。
  • 稳定性: GPS作为外部独立时钟源,相比依赖网络的时间同步服务,更不容易受网络延迟、拥塞等因素影响。

缺点:

  • 硬件需求: 需要额外的GPS接收模块,增加了设备成本和安装复杂度。
  • 系统集成: 需要在软件层面实现GPS信号接收和时间转换逻辑,增加了软件开发的工作量。

2. 使用NTP设置上位机IP做时间同步

优点:

  • 易于部署: 大多数操作系统都内置了NTP客户端,配置简单,仅需指定NTP服务器地址即可。
  • 成本低: 不需要额外硬件设备,只要网络连通即可。
  • 广泛支持: NTP服务器遍布全球,容易找到可靠的时钟源,且适合大规模网络内的时间同步。

缺点:

  • 精度限制: NTP在互联网上的典型精度约为毫秒级,虽然对于许多应用已足够,但对于高精度需求可能不够。
  • 依赖网络: 网络状况直接影响同步效果,如延迟、丢包都会降低同步精度。
  • 安全风险: 开放的网络接口可能面临安全攻击。

结论

选择哪种方式取决于你的具体需求:

  • 如果你的应用场景对时间精度有极高要求,且可以接受额外的硬件成本和开发工作,直接从GPS获取时间并同步可能是更可靠的选择。
  • 对于大多数通用场景,尤其是那些对成本敏感、不直接接触GPS信号或对时间精度要求不高(毫秒级足够)的情况,使用NTP服务进行时间同步会是更简便、经济的选择。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DFminer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值