linuxptp分析

linuxptp是Precision Time Protocol (PTP)的实现,以linuxptp命名ptp协议栈一定程度上有点片面,详细分析linuxptp会发现该开源软件包含的内容相当丰富,大致可以分为4个部分:

  1. 将GPS时间同步到PHC,这是一种使用1pps + TOD的时间同步技术,主要由ptp协议栈中的ts2phc进行实现。
  2. 对ptp协议的Ordinary clock, Boundary clock等时钟“角色”的实现,是对1588协议的实体化,主要由ptp协议栈中的ptp4l实现。(没有找到1588协议原文,可从各硬件厂商的1588资料中窥探一二)
  3. 实现PHC时间同步到系统时间,由ptp协议栈中phc2sys实现。
  4. 其他就是一些调试和维测工具,如phc_ctl。
    本文对阅读了linuxptp源码基础上对理解原理有所帮助,有误之处欢迎交流。

一、1pps + TOD的时间同步技术

服务器可以通过接收GPS的1pps和TOD进行处理,获取高精度时间。
原理是GPS发送来的1pps是高精度的,即每整秒一个脉冲,偏移很小,但是PPS不携带时间信息,TOD中包含UTC时间,将TOD和1pps结合就能够获取到UTC时间,且UTC时间以高精度的频率抵达。
linuxptp分析_第1张图片
linuxptp分析_第2张图片
计算UTC时间和pps到来时的系统时间偏差,调整到系统时间,并将调整后的系统时间设置到PHC。

参考文档
https://blog.csdn.net/hltt3838/article/details/109118949
参考文档:
https://www.cnblogs.com/shaohef/p/15808900.html

有些时间服务器就是实现了GPS时间同步到PHC这部分功能,并能输出1588报文。

二、ptp4l

对1588协议的实现,内容很多,包含主从时钟选择,主从时钟状态机,主从间消息交互等,有空再另开一篇细说。
参考文档
http://www.butlergroup.ie/wp-content/uploads/wpsc/product-files/880_Calnex_Technical_Brief___IEEE_1588v2_PTP_Mar10.pdf

三、phc2sys

phc2sys的同步有三种方式:

没有指定pps设备,指定了PHC设备

命令:phc2sys -c CLOCK_REALTIME -s eth0 -O 0

这种方式的原理是:通过clock_gettime()获取phc时间,并计算系统时间和phc时间的差值,从而对phc时间进行调整。
linuxptp分析_第3张图片
read_phc()获取到的ts是tdst2,是系统时间,这种算法计算出来的偏差是
offset = (tdst2 - tdst1)/2 + (tdst1 - tsrc) 。对系统时间ts进行offset的调整就能使得系统时间接近phc时间。
官方推荐不推荐使用这种方式,具体原因可以参考这篇文献:https://www.researchgate.net/publication/260434305_Synchronizing_the_Linux_system_time_to_a_PTP_hardware_clock
在另外一篇文章中有这篇文献的简陋翻译版。

指定PPS设备,没有指定PHC设备

phc2sys -d /dev/pps0 -O 0 -m 这样执行没有用-s指定phc设备
这种方式的时间源是pps产生的整秒值,偏差是系统时间相对于整秒值的偏差。 这样执行没有用-s指定phc设备,read_pps读取到pps的整秒数,以及相对于整秒数的偏差。
read_pps()
通过ioctl获取pps时间,这个pps时间是pps产生当时的系统时间,pps是整秒产生的,但是系统时间可能是飘的,所以获取到的这个时间值是有小数点的,比如pps产生的时间点是166663313s,但是获取出来的值可能是166663313.1245s, 将这个值转换为ns,然后取余得到的offset就是小数点后面的秒数。将这个offset来对系统时间进行校正。
这样对系统时间进行调整,让偏差越来越小,这种“自我矫正”方式缺少绝对时间,比如当前系统时间是1988年,那使用这种方式就一直是在1988年对每秒进行矫正,没有同步到当前时间。
linuxptp分析_第4张图片
代码分析:

src_name变量就是NULL
clock_add(&priv, src_name) // phc2sys.c
	c->clkid = CLOCK_INVAILD
do_pps_loop()
	priv->sync_offset = 0;
	read_pps()//获得pps时间
	update_clock()//将pps时间更新到pps时间

指定了PPS设备以及PHC设备

命令:phc2sys -d /dev/pps0 -s eth0 -O 0 -m 这样执行,使用了-s指定了phc设备
这种方式与上面那种方式基本原理相同,但是多了一个read_phc的过程,为的是获取当前的绝对时间。

do_pps_loop()
	priv->sync_offset = 0;
		read_pps()//获得pps时间
		read_phc(&phc_offset, &phc_ts, &phc_delay)//返回的phc_ts实际上是系统时间,但是认为这个系统时间是不准的,所以计算了一个校正值phc_offset,然后将phc_ts -= phc_offset对phc_ts(系统时间)进行修正,然后
		phc_ts = phc_ts / NS_PER_SEC *  NS_PER_SEC获取整秒值,这就是通过系统时间并校正后得到绝对时间的整秒值
		pps_offset = pps_ts - phc_ts就是pps时间相对于绝对时间整秒值的偏差。
		update_clock()//将pps时间更新到pps时间

linuxptp分析_第5张图片

参考资料:
这篇文章罗列了一些很好的资料
https://www.cnblogs.com/shaohef/p/15808900.html
https://blog.csdn.net/yaojiawan/article/details/124601694
上面这篇中文博客的图都来自于下面两篇文章。
https://www.researchgate.net/publication/260434305_Synchronizing_the_Linux_system_time_to_a_PTP_hardware_clock
https://www2.renesas.cn/us/en/document/whp/linux-phc-infrastructure-5g
linuxptp guthub
https://github.com/vladimiroltean/linuxptp

你可能感兴趣的:(linux,网络)