Linux下GDB调试NTP时间同步问题

简介: 最近有遇到一例比较有趣的Linux下NTP时间同步问题,尝试了使用GDB调试的方法解决,在这里分享一些个人的心得,希望对大家有些帮助。 问题现象:ECS Linux CentOS实例中时间经常出现偏差,客户已经根据官方文档配置了NTP时间同步,同步源为文档中指定的公网NTP服务器:https://help.aliyun.com/knowledge_detail/40583.html 尝试调整一些同步频率的参数,并没有实际效果。

最近有遇到一例比较有趣的Linux下NTP时间同步问题,尝试了使用GDB调试的方法解决,在这里分享一些个人的心得,希望对大家有些帮助。

问题现象:
ECS Linux CentOS实例中时间经常出现偏差,客户已经根据官方文档配置了NTP时间同步,同步源为文档中指定的公网NTP服务器:
https://help.aliyun.com/knowledge_detail/40583.html

尝试调整一些同步频率的参数,并没有实际效果。其中注意到一个现象,如果我们列出NTP日志中信息,会发现一旦出现 "no servers reachable" 之后,ntpd就会停止同步。

image

而如果重启ntpd同步问题就会暂时得到解决,过了一天左右问题又会复现。

调试过程:
由于通过普通的ntpd的调整一些参数无法解决问题,决定采用GDB现场调试的方式来看看问题发生时为什么ntpd不再同步。

调试之前我们首先要确认ntpd更新系统时间是具体在哪个函数中实现的。因此首先采用阅读Linux NTP代码的方式将范围缩小,确认具体代码段如下:

void
clock_select(void)
{
...
clock_update(); <----------- 更新系统时间

因此我首先将断点设在clock_select,结果是可以中到,得到的堆栈如下:

image

因此我进一步可以设置断点到clock_update附近:

image

但是这次没有中,因此可以判定是在之前的逻辑判断中跳出了。进一步跟踪后发现:

for (n = 0; n < NTP_HASH_SIZE; n++) {

for (peer = peer_hash[n]; peer != NULL; peer =
    peer->next) {
    peer->flags &= ~FLAG_SYSPEER;
    peer->status = CTL_PST_SEL_REJECT;

    /*
     * Leave the island immediately if the peer is
     * unfit to synchronize.
     */
    if (peer_unfit(peer))
        continue;

如上代码我们对每一个时间同步源会调用peer_unfit来判断他是否“适合”做时间同步。如果所有同步源都不适合做同步的话,自然就会跳出。因此接下去我们可以考虑设置断点在peer_unfit,并且查看其返回值:

image

注意上图是在本地正常的测试机上截取的,而在用户机器上返回值寄存器rax为1,因此可以判断所有配置的同步源被peer_unfit中的逻辑判断为不适合做同步。

因此我们接下去就可以使用相同的方法对peer_unfit做进一步跟踪:

我们发现失败在如下的检查:

if (root_distance(peer) >= sys_maxdist + clock_phi *

ULOGTOD(sys_poll))
rval |= TEST11;     /* distance exceeded */

汇编代码如下:

image

这表明计算下来本地时钟和远端NTP服务器的distance过大。clock_phi 是晶振的频率为0.000015,而sys_poll是同步的询问时间,两者相乘是非常小的。所以主要比较的是当前的distance和sys_maxdist,后者默认为1。

root_distance是一个相对复杂的计算:

dist += max(sys_mindisp, dist + peer->delay) / 2 +

peer->rootdispersion + peer->disp + clock_phi *
(current_time - peer->update) + peer->jitter;

其中可以发现他和当前时钟和NTP服务上次成功的时间,两者的差值有关。因此如果时钟走的比较快,而有一次甚至几次同步失败,整个NTP服务就有可能不会再进行同步了。

寻找解决方案:
以上比较的几个参数中唯一可调的就是sys_maxdist,我们可以继续阅读Linux代码来了解怎么调整他:

        case CONF_TOS_MAXDIST:
        proto_config(PROTO_MAXDIST, 0, ftemp, NULL);

因此我们可以通过在ntp.conf中添加"tos maxdist"可以增大,从而容忍本地时钟过快。

以上一例是采用GDB调试的方法来解决一些服务产生的问题,希望给大家提供解决问题的另一种思路。

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
15天前
|
缓存 NoSQL Linux
Linux调试
本文介绍了Linux调试、性能分析和追踪的培训资料,涵盖调试、性能分析和追踪的基础知识及常用工具。
205 6
Linux调试
|
3月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
65 10
|
3月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
102 3
|
3月前
|
Ubuntu Linux
内核实验(四):Qemu调试Linux内核,实现NFS挂载
本文介绍了在Qemu虚拟机中配置NFS挂载的过程,包括服务端的NFS服务器安装、配置和启动,客户端的DHCP脚本添加和开机脚本修改,以及在Qemu中挂载NFS、测试连通性和解决挂载失败的方法。
207 0
内核实验(四):Qemu调试Linux内核,实现NFS挂载
|
3月前
|
NoSQL Linux 编译器
内核实验(一):使用QEMU+GDB断点调试Linux内核代码
如何配置环境并使用QEMU虚拟机结合GDB进行Linux内核代码的断点调试,包括安装QEMU、交叉编译工具链,编译内核以及通过GDB远程连接进行调试的详细步骤。
160 0
内核实验(一):使用QEMU+GDB断点调试Linux内核代码
|
3月前
|
NoSQL
技术分享:如何使用GDB调试不带调试信息的可执行程序
【8月更文挑战第27天】在软件开发和调试过程中,我们有时会遇到需要调试没有调试信息的可执行程序的情况。这可能是由于程序在编译时没有加入调试信息,或者调试信息被剥离了。然而,即使面对这样的挑战,GDB(GNU Debugger)仍然提供了一些方法和技术来帮助我们进行调试。以下将详细介绍如何使用GDB调试不带调试信息的可执行程序。
108 0
|
程序员 编译器 Linux
linux gdb-多线程调试
相信使用C/C++语言开发软件的程序猿们都经历过‘栈溢出’的问题。‘栈溢出’问题通常十分的隐蔽,有的时候问题复现也十分的困难。每当软件出现莫名其妙的问题时,总是有人怀疑是不是栈溢出了,但是问题的排查又十分的困难,所以,‘栈溢出’就是广大C/C++开发者的噩梦。
154 0
|
NoSQL IDE Linux
linux gdb-多线程调试
linux下应用程序的调试工具主要就是gdb,可能你已经习惯了IDE形式的调试工具。也许刚开始使用gdb作为调试工具,会有诸多的不变,但是一旦你学会了如何使用gdb你就会被其富有魔力的功能所吸引的,下面开始逐步的学习linux下gdb的使用方式。
431 0
|
10天前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
92 6
|
11天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
47 3
下一篇
无影云桌面