我有一个Linux系统,我需要对系统时间进行小周期性调整以跟踪外部时间源,但我想避免日期/时间跳转。
我想过使用adjtimex()
内核函数(参见:adjtimex(2),adjtimex(8)),但我有些疑惑:
--offset
的论点必须在-512000 ... 512000范围内(因此它只能纠正+/- 0.5秒),并且没有提及--singleshot
adjtimex
命令行实用程序)这些限制似乎都不适用感谢任何帮助。
答案 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()
中完成。
关于您的具体问题:
如果您使用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
。这会将当前时间设置为参考时间,以便相对于当前系统时间计算偏移量,并启用时钟偏移调整。
在内核源代码中,MAXPHASE
常量(在include/linux/timex.h中)定义了偏移量限制。目前,它是以纳秒为单位,并指定半秒;较大的值(大小)静静地限制在半秒内,没有任何错误。
在2.6.26之前的Linux内核中,限制较小(±131071μs)。新限制已添加到May 2008。
(限制的更改已传达给Linux手册维护人员Michael Kerrisk,in June 2009但显然adjtimex(2)手册页从未更新以反映此更改。我不认为建议但是措辞很清楚。)