原文链接: http://www.aosabook.org/en/gpsd.html
作者:Eric Raymond
译者:Liuli Chen(陈旒俐)
GPSD是一系列管理GPS设备和其他用于导航与精确计时的传感器的工具,包括航海自动识别系统(marine AIS (Automatic Identification System))的无线电广播设备和电子罗盘。其中最主要的程序是一个叫做gpsd
的服务守护进程,它管理这这些传感器,并且在TCP/IP端口生成JSON流报告。其他的程序包括用来展示代码模型和各种诊断工具的客户端。
GPSD被广泛地部署在笔记本、智能手机以及包括自动驾驶汽车和自动潜艇在内的自动交通工具上。它在嵌入式系统中被用来导航、精确耕作、位置敏感的科学遥测、网络时间服务等,起着不容忽视的作用。它甚至被用在装甲车的敌友识别系统(Identification-Friend-or-Foe)中,例如M1“艾布拉姆斯(Abrams)”主战坦克。
GPSD是一个中型项目,大约43千行代码,主要用C和Python写成,最早的历史可以追溯到1997年,现行版本从从2005年开始写的。核心成员稳定在3人,其他大约24人作出了半正规的贡献,另外还有上百人做了一次性的修补。
GPSD不管是在像splint
,valgrind
和Coverity这样的审查工具还是在突发错误记录上向来有着极低的错误率。这并不是一个巧合,这个项目做了大量的自动测试,而这一切努力都很好地得到了回报。
由于排除了所有前任的不确定性,GPSD在它做的事情上相当优秀。2010年,GPSD在Allience for Code Excellence赢得了Good Code Grant的第一名。等你看完这一章你就会明白为什么。
7.1. GPSD存在的原因
GPSD存在的原因是那些GPS和其他导航传感器上装载的应用层协议设计和文档都很差,并且不同传感器类型和模型之间存在这巨大的差异。你可以在[Ray]看到详细的讨论。尤其是,你会在哪里发现NMEA 0183(一类GPS报告包标准)的怪诞和一堆文档书写极差的供应商协议。
如果应用不得不自己处理所有的这些复杂性,必将导致大量脆弱冗余的代码。由于底层硬件的逐渐改变,这将进而造成高度的用户可视化不足以及持续的问题。
GPSD通过自己知道所有的协议(截至写这篇文章的时候我们支持大约20种不同的协议)、管理串行和USB接口、用一种简单的设备无关的JSON格式报告传感器有效载荷,来把位置感知的应用和具体的硬件接口个离开来。GPSD通过提供客户端库使得客户端应用不用知道报告格式,从而进一步简化了生活。相反,得到传感器信息成为了一个简单的进程调用。
同时,GPSD也支持精确计时:只要它附属的某个传感器有PPS (pulse-per-second)能力,它就能作为一个网络时间协议守护进程ntpd
(the Network Time Protocal Daemon)的时间源工作。GPSD的开发者与ntpd
项目的开发者紧密合作来改善网络时间服务。
目前(2011年年中),我们正在完成对航海导航接收器的AIS网络支持。将来,一旦出现新的位置干吃传感器的协议文档和测试设备,我们期望可以支持它们,比如二代飞机异频雷达接收器。
总的来说,GPSD设计中最终要的主题就是把所有设备相关隐藏在一个简单的与无需配置的服务器交互的客户端接口之后。
7.2. 外部视图
GPSD套件中最主要的程序是gpsd
服务守护进程。它能够通过RS232、USB、蓝牙、TCP/IP和UDP连接从一系列附属传感器设备收集捕获量。报告一般来说会被传送到TCP/IP端口2947,但也能通过一个共享内存或者D-BUS接口出去。
GPSD分布装载着C、C++和Python的客户端库,包含了C、C++、Python和PHP的示例客户端,Perl客户端绑定可以通过CPAN实现。这些客户端库把应用和JSON报告协议分离,不仅仅方便了应用开发者,也解决了GPSD开发者们头痛的问题。因此,即使这个协议为新的传感器类型产生了新的特性,其暴露给客户端的API依然可以保持不变。
套件中的其他程序包括一个低层设备监视器的公共程序(gpsd
),一个为错误统计和设备超时产生报告的分析器(gpsprof
),一个调整设备设置的公共程序(gpsctl
),和一个把传感器日志批量转换成可读的JSON的程序(gpsdecode
)。它们共同帮助那些技术用户深入观察附属传感器的运作。
当然了,这些工具也帮助GPSD自己的开发者检查gpsd
的正确运作。其中最重要的测试工具就是gpsfake
,一个能够连接任意数目的活动传感器日志的测试套件。通过gpsfake
,我们可以重复运行有错误报告的传感器日志来重新产生特定的问题。gpsfake
也是我们大量回归测试套件的引擎,它通过简化发现破坏性变化的过程来减少修改软件的开销。
我们从中学到的最重要的教训之一就是:对一个软件套件来说,光有正确性是不够,它还要能够证明自己的正确性。我们发现适度追求这个目标不仅不是过于敏感,而且还是一双翅膀——我们花在写测试套件和回归测试上的时间多次得到了回报,因为这给了我们充分的自由,在修改代码的时候不用担心对现有函数造成大的破坏。
7.3. 软件层次
GPSD内部运行是非常复杂的,而不仅仅是人们想像的那样“加入一个传感器使之工作”。gpsd
的内部构造分成四个部分:驱动(drivers)、包嗅探器(packet sniffer)、核心库(core library)和多路复用器(multiplexer)。我们将自底向上地介绍它们。
jQuery 杂项 data() 方法jQuery 杂项方法实例 向 div 元素附加数据,然后取回该数据:$(#btn1).click(function(){ $(div).data(g...
jQuery event.stopImmediatePropagation() 方法jQuery 事件方法实例 执行第一个事件处理程序,并阻止剩下的事件处理程序被执行:...
jQuery event.which 属性jQuery 事件方法实例 返回哪个键盘键被按下:$(input).keydown(function(event){$(div).html(Key:+ even...
jQuery wrapInner() 方法jQuery HTML/CSS 方法实例 在每个 p 元素的内容上包裹 b 元素:$(button).click(function(){ $(p).wrapI...
jQuery 文档操作参考手册实例设置所有 p 元素的内容:$(.btn1).click(function(){$(p).text(Hello bworld/b!);});亲自试一试定义...