PTP简介

在通信网络中,许多业务的正常运行都要求网络时钟同步,即整个网络各设备之间的时间或频率差保持在合理的误差水平内。网络时钟同步包括以下两个概念:

时间同步:也叫相位同步(Phase synchronization),是指信号之间的频率和相位都保持一致,即信号之间的相位差恒为零。

频率同步(Frequency synchronization):也叫时钟同步,是指信号之间在频率或相位上保持某种严格的特定关系,信号在其对应的有效瞬间以同一平均速率出现,以保证通信网络中的所有设备都以相同的速率运行,即信号之间保持恒定的相位差。

继续阅读PTP简介

网络时钟同步协议-- NTP, PTP

这篇文章介绍一下两个时钟同步的网络协议:NTP和PTP。
这里不涉及协议的原理和具体实现(想了解的可自行Google),重点是如何搭建起这两个服务。

1. NTP及PTP简介


NTP(Network Time Protocol)是用于不同计算机之间同步时钟的网络协议。
它的设计目标是使所有的互连的机器之间的时钟与UTC时间只相差若干毫秒

目前NTP协议已经是有第4版了,如果不需要了解NTP太多细节的话,看看这个wiki页面应该就足够了。需要注意的就是它有clock strata的概念。

PTP(Precision Time Protocol)看名字就知道是一个比NTP更精确的时钟同步协议了,PTP的设计目标是使机器之间的时钟偏差在sub-microsecond范围—这是wiki页面上提到的,有其他的地方说的是偏差若干微秒,本文搭建的环境中测量到的偏差也在微秒级别,没有到sub-microsecond级别。在使用PTP协议时,需要了解的主要概念点就是它的master/slave机制。

接下来我们就介绍我搭建NTP和PTP环境的过程,所用到的操作系统是CentOS6.5,内核版本是3.10。其他软件的版本会在用到时提及。

2. 搭建NTP服务


配置环境:两台服务器,一台做NTP服务器,一台做NTP的客户端。同时这两台机器都未联网。
NTP服务器地址:192.168.0.11
NTP客户端地址:192.168.0.22

A. 在192.168.0.11中启动NTP服务

B. 在192.168.0.22上启动NTP服务,选择192.168.0.11为NTP服务器

我的这两台实验机器是在同一个Rack的,结果显示差不多同步的偏差在30ms左右。
每个版本的ntpd配置文件可能有少许的差别,不过好在注释都做的不错,所以别的细节就不啰嗦了。

3. 搭建PTP服务


List of PTP implementations可以看到PTP的实现有很多很多种,可以是硬件实现的,可以是软件实现的也可以是软硬件结合实现的。本文中搭建的PTP服务是基于软件PTPd。如果没有特殊的硬件的话,这算是一种非常方便的方法了。

如果遇到任何问题,首先一定要看看help,使用-H选项的话还能看到非常详细的配置(虽然大多我可看不懂,不过不能不看,理解的越多,遇到的问题就会越少)。
如果log里面的信息看不懂,可以把代码下下来,一个grep搞定。

经测试,在我的机器上使用PTPD软件搭建的服务,时钟偏移的平均值能够达到5us左右。这个粒度基本能满足我们的需求了。

参考链接


Linux 中的时钟准确度

本文来自戴尔软件开发高级工程师Stuart Hayes

一个关于计时的问题最近引起了我的关注。 有用户在 Dell 服务器上运行 Linux,并且发现时钟时间(Linux 所报告的)每天误差五秒以上,偏差比较明显。

我们首先想到的也许是运行 NTP,定期与真实世界同步操作系统的时钟。

但是这样的误差最初是如何产生的?

在Linux运行时,Linux 系统未使用实时时钟(real time clock - RTC) 硬件来计时。 Linux 通常在启动时从RTC 读取时间,然后从该点开始,Linux 使用另一个时钟来源(系统中的另一个计时器/计数器)来计时。

自第 2.6.18 版起,Linux 的内核就使用 CPU 时间戳计数器 (TSC) 作为首选的时钟来源(假设 TSC 以恒定频率运行,以新款的 Intel 服务器 CPU为例)。 但是,尽管读取速度很快且解析度很高,TSC 却不是一个已知的频率。 当内核使启动时,它需要使用频率已知的另一个计时器,对其进行校准。 这样的校准并非天衣无缝(即使用于校准的计时器也是如此),因此把 TSC 作为时钟来源会造成时间误差。

如果减少时间误差对您非常重要,而非若干微秒的调度延迟,则最好使用频率已知的计时器,如大多数 x86 服务器上提供的 HPET(高精度事件计时器)。 借助新内核上的参数" clocksource=hpet"可实现这一目标。 HPET 计时器以已知、固定的频率运行,Linux 内核可直接从计时器读取时间。

话说回来,尽管 HPET 的精度高于 TSC,运行 NTP 以在 Linux 中实现长期的时钟精度始终是很好的想法。
上述讨论仅适用于运行于裸机的 Linux。 在虚拟机中的问题略微复杂。

原文链接


Linux 中的时钟准确度

Linux时钟精度:毫秒?微妙?纳秒?

最近被内核时钟精度弄的很是郁闷。具体情况如下:

扫盲:1秒=1000毫秒=1000000微妙=1000000000纳秒

首先:linux有一个很重要的概念——节拍,它的单位是(次/秒)。2.6内核这个值是1000,系统中用一个HZ的宏表征这个值。同时有全局的jiffies变量,表征从开机以来经过的节拍次数(这里面还有故事,后面说,先记住这个)。当然还有wall_jiffies的墙上jiffies来表示从 07-01-1970 到现在的节拍数。每个节拍里面执行一次时钟中断。就是说,它的精度是毫秒。

接着:内核中还有一个变量xtime表征系统的实际时间(墙上时间),定义如下。其中xtime.tv_sec以秒为单位,存放从Unix祖宗定的纪元时间(19700701)到现在的秒数。xtime.tv_nsec以纳秒为单位,记录从上一秒开始经过的纳秒数。就是说,它的精度是纳秒。


最后:linux提供一个gettimeofday的系统调用,它会返回一个timeval的结构体,定义如下。解释同上,tv_sec代表墙上时间的秒,tv_usec表示从上一秒到现在经过的微秒数。就是说,它的精度是微妙。

精彩的来了:
1. 内核中的xtime会在每个时钟中断的时候被更新一次,也就是每个节拍更新一次。你妹!!每毫秒更新一次怎么能冒出来纳秒的精度??而且,内核还有可能丢失节拍。怎么能是纳秒??
2. 各种书上说,gettimeofday系统调用是读取的xtime的值。日,为啥读出来之后精度丢了?变成微妙了?

寻寻觅觅终于理清了故事:
针对问题1:在linux启动的时候,一个节拍的时间长度还会以纳秒为单位初始化到tick_nsec中,初始化值为999848ns,坑爹啊!不到一毫秒!节拍大约为1000.15Hz。靠!实际的节拍竟然不是准确的1000!所以在每个时钟中断通过wall_jiffies去更新xtime的时候得到的就是一个以纳秒为最小单位的的值。所以!xtime的粒度应该是不到1毫秒,也就是精度是不到1毫秒。

针对问题2:gettimeday系统调用的读xtime代码部分如下:

while部分使用了seg锁,只看中间的就好了。加了注释之后就很清晰了。由于节拍可能会丢失,所以lost是丢失的节拍数(不会很多)。至于计时器就比较麻烦了,timer可能有下面四种情况。

a. 如果cur_timer指向timer_hpet对象,该方法使用HPET定时器——Inter与Microsoft开发的高精度定时器频率至少10MHz,也就是说此时可提供真正的微妙级精度。
b. 如果cur_timer指向timer_pmtmr对象,该方法使用ACPI PMT计时器(电源管理定时器)平率大约3.58MHz,也就是说也可以提供真正的微妙级精度。
c. 如果cur_timer指向timer_tsc对象,该方法使用时间戳计数器,内置在所有8086处理器,每个CPU时钟,计数器增加一次,频率就是CPU频率,所以timer精度最高。完全可以胜任微妙级的精度。
d. 如果cur_timer指向timer_pit对象,该方法使用PIT计数器,也即是最开始提到的节拍计数,频率大概是1000Hz,此时显然不能提供精度达到微妙的时间。所以只有这种情况是假毫秒精度!

综上:如果使用gettimeofday系统调用,只要不要使用节拍计数器就可以保证达到微妙精度的时间(刨除进程上下文时间误差)。至于网上说的可以拿到纳秒精度的时间,看起来都是错的。除非通过修改内核,使用时间戳计数器实现。Over!

最后最后说一个事情:jiffies的定义的是4字节,你可能猜想它初始值是0。实际上,事实并非如此!linux中jiffies被初始化为0xfffb6c20,它是一个32位有符号数,正好等于-300 000。因此,计数器会在系统启动5分钟内溢出。这是为了使对jiffies溢出处理有缺陷的内核代码在开发阶段被发现,避免此类问题出现在稳定版本中。

参考《深入理解linux内核》

原文链接


Linux时钟精度:毫秒?微妙?纳秒?

ubuntu 17.10 gnome 3桌面隐藏顶栏

1.安装 gnome-tweak-tool

2.安装 hidetopbar扩展

3.重启电脑

4.启动 gnome-tweak-tool

可以看到 扩展--> Hide top bar扩展,开启即可隐藏顶栏。按键盘上的 Windows图标键就会显示出来。如果还是没有隐藏,请点击设置按钮,在里面关闭 智能隐藏

继续阅读ubuntu 17.10 gnome 3桌面隐藏顶栏

Windows 7系统上安装CentOS 7后通过修改grub2添加Windows 7启动引导项

按照以往的经验,先安装 Windows 7之后,再装 CentOS 7,那么 CentOS 7应该会自动添加 Windows 7启动项。但是安装完成后,发现启动项里没有 Windows 7

我们需要手动添加 Windows 7的启动项。

我们需要修改 grub2的模版文件,然后执行 grub2-mkconfig自动重建 grub2引导列表。

至于 set root=(hd0,1),还是 set root=(hd0,msdos1),或者 set root=(hd0,msdosX),请在启动列表中按下 e键,进入 grub rescue模式,执行 ls命令列出分区,如果第一个启动不了,请逐个分区都试试。

参考链接


Centos7 + Windows7 双系统,通过修改grub2,重新添加 Win7 启动引导项

NVIDIA TX2 (Ubuntu 16.04)上安装CUDA 8.0

使用如下方式安装:

至于如何获取最新的 NVIDIA TX2上使用的 CUDA 8.0版本的下载地址,请访问Jetson Download Center,下载目前最新的JetPack 3.1。执行之后在存储目录下的 repository.json中找到最新的下载链接即可。当然也可以让JetPack 3.1自动下载完成最新的 CUDA 8.0版本到指定目录。

Ubuntu 16.04上使用crosstool-ng编译Nvidia TX2上使用的boost库

目前在 Nvidia TX2上尝试安装 ROS Kinetic的时候发现依赖 libboost-all-dev,但是自带的源http://ports.ubuntu.com下面没有合适的源,尽管在 universe源下面包含 libboost-all-dev ,但是实际安装的时候发现安装不上。

因此尝试手工编译最新的 boost安装包,建立自己的源。

首先,编译安装最新的 crosstool-ng,如下:

生成的工具链在 ~/x-tools/aarch64-rpi3-linux-gnueabi目录下,编译的时候,指定编译工具即可。

安装编译依赖

接着,下载并编译最新的代码

注意,对于 boost-1.58来说,当时的代码是没有检测 ARM64的功能的,当年也没有 ARM64的芯片。因此需要修改 {boost_root}/libs/config/checks/architecture/arm.cpp里面的代码,增加 ARM64的判断

调整为

参考链接


Linux下编辑ISO文件的方法

我们知道 Windows下有类似 UltraISO的这样的软件可以用来编辑 ISO文件,可引导 ISO也没有问题。近来在 Linux下玩的比较多,正好要改个 ISO,于是就开始找 Linux下有没有类似的软件。

Ubuntu软件中心里有一款叫 ISOMaster的软件,可以创建和修改 ISO文件。

继续阅读Linux下编辑ISO文件的方法

OpenCV使用cv::imshow在子线程中更新图片不刷新

Ubuntu 16.04上测试 OpenCV 3.2,遇到一个在子线程中更新图像,而界面不刷新的问题。

编译执行如下代码:

可以看到,上面的代码执行之后,界面并没有出现,即使出现也没有刷新。

这个问题是由于界面更新必须在主线程中执行,需要手工通知主线程。

修改后的代码如下:

也就是每次更新图片后手工调用代码

这个等候时间,只要大于 即可,比如:

参考链接


c++ opencv image not display inside the boost thread