使用adjtimex进行小时间调整

时间:2014-02-12 15:33:41

标签: c linux time kernel

我有一个Linux系统,我需要对系统时间进行小周期性调整以跟踪外部时间源,但我想避免日期/时间跳转。

我想过使用adjtimex()内核函数(参见:adjtimex(2)adjtimex(8)),但我有些疑惑:

  1. 偏移和单一拍摄模式之间的区别是什么?
  2. 可接受的参数范围是多少?我问的是因为:
    • adjtimex(8)提到--offset的论点必须在-512000 ... 512000范围内(因此它只能纠正+/- 0.5秒),并且没有提及--singleshot
    • 的任何值
    • adjtimex(2)提到范围-131071 .. + 131071,显然适用于这两种模式
    • 在我的测试中(使用adjtimex命令行实用程序)这些限制似乎都不适用
  3. 感谢任何帮助。

1 个答案:

答案 0 :(得分:6)

(请参阅Linux man-pages project for Linux手册页。它们更有可能是最新的。评论表明实施的逻辑应遵循RFC 1305。)

有关实现的详细信息,只需浏览Linux内核源代码即可。 adjtimex()系统调用在kernel/time.c中定义;寻找SYSCALL_DEFINE.*(adjtimex,

adjtimex()本身会调用kernel/time/timekeeping.c中定义的do_adjtimex()。基本范围检查在kernel/time/ntp.c中定义的ntp_validate_timex()中完成。

关于您的具体问题:

  1. 如果您使用ADJ_OFFSET_SINGLESHOT,则adjtimex()的行为为adjtime(),您只能使用.offset字段。根据调整的大小和符号,NTP时钟会加速或减速一段时间,直到达到所需的偏移;然后NTP时钟速率恢复原状。你不能使用任何其他模式标志。

    ADJ_SETOFFSET.time添加到当前时间;立刻推动时钟前进。

    ADJ_OFFSET还调整NTP时钟速率以在合理的时间内实现所需的偏移,因此效果应与单次模式中的效果相同。但是,您也可以在同一个调用中使用其他ADJ_模式标志。

    Grodriguez发表评论后编辑:

    仅当认为偏移是好的时,

    ADJ_OFFSET才有效,即时钟状态是锁相的,STA_PLL。通常,如果采样间隔很长,或者NTP守护程序的样本不正确,NTP守护程序会将状态更改为频率锁定(STA_FLL)。

    要使用ADJ_OFFSET,您的程序应该使用模式模式ADJ_OFFSET|ADJ_STATUS,并设置.status=STA_PLL。这会将当前时间设置为参考时间,以便相对于当前系统时间计算偏移量,并启用时钟偏移调整。

  2. 在内核源代码中,MAXPHASE常量(在include/linux/timex.h中)定义了偏移量限制。目前,它是以纳秒为单位,并指定半秒;较大的值(大小)静静地限制在半秒内,没有任何错误。

    在2.6.26之前的Linux内核中,限制较小(±131071μs)。新限制已添加到May 2008

    (限制的更改已传达给Linux手册维护人员Michael Kerrisk,in June 2009但显然adjtimex(2)手册页从未更新以反映此更改。我不认为建议但是措辞很清楚。)