正常的phc2sys结果: (offset非常小)
root@dell:/home/ppl/sbs# phc2sys -s eno1 -c CLOCK_REALTIME -w -m --transportSpecific=1
phc2sys[1965191.688]: CLOCK_REALTIME phc offset -647234 s0 freq +14768 delay 0
phc2sys[1965192.689]: CLOCK_REALTIME phc offset -647599 s1 freq +14403 delay 0
phc2sys[1965193.689]: CLOCK_REALTIME phc offset -172 s2 freq +14231 delay 0
phc2sys[1965194.690]: CLOCK_REALTIME phc offset -36 s2 freq +14316 delay 0
phc2sys[1965195.690]: CLOCK_REALTIME phc offset -41 s2 freq +14300 delay 0
phc2sys[1965196.691]: CLOCK_REALTIME phc offset -21 s2 freq +14308 delay 0
phc2sys[1965197.691]: CLOCK_REALTIME phc offset -81 s2 freq +14241 delay 0
phc2sys[1965198.692]: CLOCK_REALTIME phc offset 135 s2 freq +14433 delay 0
phc2sys[1965199.692]: CLOCK_REALTIME phc offset -68 s2 freq +14270 delay 0
phc2sys[1965200.693]: CLOCK_REALTIME phc offset 113 s2 freq +14431 delay 0
phc2sys[1965201.693]: CLOCK_REALTIME phc offset 40 s2 freq +14392 delay 0
phc2sys[1965202.694]: CLOCK_REALTIME phc offset -146 s2 freq +14218 delay 0
phc2sys[1965203.694]: CLOCK_REALTIME phc offset 46 s2 freq +14366 delay 0
phc2sys[1965204.695]: CLOCK_REALTIME phc offset -41 s2 freq +14293 delay 0
phc2sys[1965205.696]: CLOCK_REALTIME phc offset 62 s2 freq +14384 delay 0
phc2sys[1965206.696]: CLOCK_REALTIME phc offset -11 s2 freq +14329 delay 0
phc2sys[1965207.696]: CLOCK_REALTIME phc offset -29 s2 freq +14308 delay 0
phc2sys[1965208.697]: CLOCK_REALTIME phc offset 58 s2 freq +14386 delay 0
phc2sys[1965209.300]: CLOCK_REALTIME phc offset 31 s2 freq +14377 delay 0
phc2sys -s eno1 -c CLOCK_REALTIME -w -m --transportSpecific=1
phc2sys -a -r -m --transportSpecific=1
#--transportSpecific 说明采用的是802.1AS协议而不是 1588
使用phc2sys进行时间同步时可能会遇到failed to step clock: Invalid argument的问题,
此时运行结果显示的offset是一个非常大的值。像这样:
root@ubuntu:~# phc2sys -s enp3s0 -c CLOCK_REALTIME --transportSpecific=1 -w -m
phc2sys[1824434.875]: CLOCK_REALTIME phc offset 1671096880712206474 s0 freq +100000000 delay 11664
phc2sys[1824435.879]: failed to step clock: Invalid argument
phc2sys[1824435.879]: CLOCK_REALTIME phc offset 1671096880600630614 s1 freq -78202 delay 11405
phc2sys[1824436.879]: CLOCK_REALTIME phc offset 1671096880600131458 s2 freq +100000000 delay 13201
phc2sys[1824437.880]: CLOCK_REALTIME phc offset 1671096880488856578 s2 freq +100000000 delay 11836
phc2sys[1824438.880]: CLOCK_REALTIME phc offset 1671096880377616030 s2 freq +100000000 delay 11923
phc2sys[1824439.881]: CLOCK_REALTIME phc offset 1671096880266370980 s2 freq +100000000 delay 11394
phc2sys[1824440.881]: CLOCK_REALTIME phc offset 1671096880155136990 s2 freq +100000000 delay 11631
phc2sys[1824441.881]: CLOCK_REALTIME phc offset 1671096880043896534 s2 freq +100000000 delay 11631
phc2sys[1824442.882]: CLOCK_REALTIME phc offset 1671096879932658474 s2 freq +100000000 delay 11869
查看源代码可以看到是在进行系统时间设置时,报错。
//clockadj.c
void clockadj_step(clockid_t clkid, int64_t step)
{
struct timex tx;
int sign = 1;
if (step < 0) {
sign = -1;
step *= -1;
}
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_SETOFFSET | ADJ_NANO;
tx.time.tv_sec = sign * (step / NS_PER_SEC);
tx.time.tv_usec = sign * (step % NS_PER_SEC);
/*
* The value of a timeval is the sum of its fields, but the
* field tv_usec must always be non-negative.
*/
if (tx.time.tv_usec < 0) {
tx.time.tv_sec -= 1;
tx.time.tv_usec += 1000000000;
}
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to step clock: %m"); //这一行报错
}
//missing.h
#ifndef HAVE_CLOCK_ADJTIME
static inline int clock_adjtime(clockid_t id, struct timex *tx)
{
return syscall(__NR_clock_adjtime, id, tx);//这里失败
}
#endif
> sudo phc2sys -s eth0 -c CLOCK_REALTIME -w -m -O 0
> phc2sys[1034.500]: CLOCK_REALTIME phc offset 1613412696595700703 s0 freq
> -80545 delay 770
> phc2sys[1035.500]: failed to step clock: Invalid argument
CLOCK_REALTIME's offset from the PHC (eth0) is ~1613412696.6 seconds.
linuxptp作者的解释是: 误差太大超过了32位int 能表示的范围。
意思是时钟源的时钟可能有问题,或当前操作系统的时钟有问题(大概率是时钟源有问题,因为时钟源上的时钟很难查看),比如我遇到的情况是1970-1-1,还在1970年,肯定是不对的。
CLOCK_REALTIME's offset from the PHC (eth0) is ~1613412696.6 seconds. The whole seconds part needs 31 bits... I think your kernel/libc is rejecting such a large offset correction.
解决方法就是要修改时钟源,让它与现在真实的时间更接近,减小offset。 暂时还没见到其他解决办法。
timex定义位于 /usr/include/x86_64-linux-gnu/bits/timex.h
/* These definitions from linux/timex.h as of 3.18. */
struct timex
{
unsigned int modes; /* mode selector */
__syscall_slong_t offset; /* time offset (usec) */
__syscall_slong_t freq; /* frequency offset (scaled ppm) */
__syscall_slong_t maxerror; /* maximum error (usec) */
__syscall_slong_t esterror; /* estimated error (usec) */
int status; /* clock command/status */
__syscall_slong_t constant; /* pll time constant */
__syscall_slong_t precision; /* clock precision (usec) (ro) */
__syscall_slong_t tolerance; /* clock frequency tolerance (ppm) (ro) */
struct timeval time; /* (read only, except for ADJ_SETOFFSET) */
__syscall_slong_t tick; /* (modified) usecs between clock ticks */
__syscall_slong_t ppsfreq; /* pps frequency (scaled ppm) (ro) */
__syscall_slong_t jitter; /* pps jitter (us) (ro) */
int shift; /* interval duration (s) (shift) (ro) */
__syscall_slong_t stabil; /* pps stability (scaled ppm) (ro) */
__syscall_slong_t jitcnt; /* jitter limit exceeded (ro) */
__syscall_slong_t calcnt; /* calibration intervals (ro) */
__syscall_slong_t errcnt; /* calibration errors (ro) */
__syscall_slong_t stbcnt; /* stability limit exceeded (ro) */
int tai; /* TAI offset (ro) */
/* ??? */
int :32; int :32; int :32; int :32;
int :32; int :32; int :32; int :32;
int :32; int :32; int :32;
};
偏移量是用32位的整型表示的:
__syscall_slong_t offset
可能是这个问题引起的?
最新的linuxptp 3.1.1看起来已经修复了这个问题。
reference:
Re: [Linuxptp-users] ptp4l error: failed to step clock
Synchronizing Time with Linux* PTP — TSN Documentation Project for Linux* 0.1 documentation