Linux 在轨道上

作者:Harald Kirsch

Fraunhofer Gesellschaft 是一个非营利性研究组织,专门从事应用研究,并充当基础研究和工业之间技术转移的倡导者。在德国拥有近 50 个研究所,几乎涵盖了科学的所有方面。IITB(Institut für Informations- und Datenverarbeitung)的一部分专门从事计算机化监控、控制和诊断工业过程和设备的信号和图像分析应用。因此,我们的小组参与了两个项目,需要在德国高速列车城际特快列车 (ICE) 中进行数据采集和分析。本文介绍了如何使用 Linux 实现数据采集。

项目:UNRA 和 ICE-D

UNRA 项目(unrunde Räder,非圆形车轮)试图发现高速列车车轮比预期更早变得不圆的原因。正如铁路专家所知,火车和客车车轮会变得不圆,即车轮的最小半径和最大半径之间的差异变得不可忽略。对于 ICE 车轮,DB-AG 使用 0.6 毫米作为必须更换车轮的阈值。尽管仅占车轮半径的 0.1%,但这种差异会在客车结构中引起低频振动。它们不仅给结构材料带来额外的应力,还会给乘客带来不舒适的乘坐体验。

Linux on Track

ICE 高速列车

作为该项目的一部分,由 Forschungs- und Technologiezentrum der DB-AG(德国明登)开发并获得专利的测量轴安装在正常运行的 ICE 中,以测量车轮站立点的三轴力。此外,还安装了四个加速度计,三个安装在轴承处的轴上,一个安装在客车中,用于测量垂直加速度。此外,旋转编码器连接到车轴。它为车轮的每一次转动提供 1440 个 TTL 边沿。这些边沿用于为车轮的每一次转动计时 90 次模数转换,从而产生一个取决于车轮转速但与其旋转同步的采样率。

加上上面未提及的额外通道,总共需要测量 17 个通道。由于 ICE 车轮的半径为 460 毫米,因此 1 公里相当于

Linux on Track

个样本,每天产生

Linux on Track

的数据。

第二个项目称为 ICE-D,对带宽的需求没有那么大,但它需要一些数据分析在线计算。由于该系统与 UNRA 项目中使用的系统非常相似,因此本项目将不再详细描述。只需说明,另一台 Linux 计算机将在配备新型转向架(客车 resting 的四个车轮组件)的客车车厢中运行两年,以采集和分析 50 个数据通道。

硬件

这两个项目中使用的计算机硬件并不完全相同,但在任何一种情况下都不是非常令人兴奋。在 UNRA 中,我们使用普通的奔腾 90 系统,配备 Adaptec 2940 SCSI 控制器、足够大的 Quantum 磁盘(似乎已解决了与 SCSI 控制器的分歧)和 HP DAT 流媒体。对于 ICE-D 项目,使用了非常相似的硬件。相对昂贵的是 19 英寸的机箱,这是将计算机安装在火车机架中所必需的。

更令人感兴趣的可能是测量硬件。在 UNRA 中,有一个 Analog Devices RTI-860,它是一个 16 通道、12 位模数(模拟/数字)转换板。使其特别适合与 Linux 一起使用的是其 256K 样本的板载内存,从而使我们摆脱了硬实时约束。

另一块板卡称为 ADCO,是按照 IITB 的 CMS 规范开发的。它基本上是一种使用 40 MHz 时钟驱动 16 位计数器来测量时间的设备。在外部事件发生时,计数器被读入一个字长为一公里的 FIFO,然后重置以从零重新开始。因此,FIFO 收集表示序列的计数器值

Linux on Track

事件之间的时间。事件由安装在车轴上的旋转编码器生成,每旋转四度车轮发生一次。了解车轮旋转四度需要多少时间,我们可以高精度地计算车轮的转速。与 RTI-860 上的缓冲区相比,ADCO 上的 1 公里样本 FIFO 很小,并且实际上证明对于开发的第一个驱动程序来说太小了(见下文)。

ICE-D 项目需要另一种测量硬件,因为任务不是高速采集数据,而是测量多达 64 个通道。我们决定采用 Analog Devices 的 RTI-834,因为它最多可以测量 32 个通道,并且可能是市面上唯一一块带有有用的程序员手册的板卡。该手册不是免费的(大约 250 德国马克),但信不信由你,它包含了几乎所有关于硬件编程的细节,包括示例,这使得编写设备驱动程序相对容易。

除了这些设备外,客车上还安装了 GPS(全球定位系统)设备。位置信息与数据一起记录,以便稍后将其与轨道上的实际位置相关联。

软件

该软件包含几个主要组件:数据采集程序、看门狗和磁带机、GPS 监视器和设备驱动程序。这些组件将在以下小节中描述。

数据采集

除了凌晨两点到四点之间的时间外,数据采集是活动的并数字化数据。由于数据采集与车轮旋转同步,因此数据速率取决于列车的速度。在 300 公里/小时的速度下,车轮以约 29 赫兹的频率旋转,从而产生

Linux on Track

的数据速率,必须无损地流式传输到磁盘。

每旋转 345 圈车轮(约一公里),硬件都会重置以在旋转编码器的下一个零度标记处再次触发。届时,数据采集程序将从 GPS 获取最新信息,将其写入文件,关闭文件并打开一个新文件。每个文件覆盖一公里的轨道,大小接近一兆字节。选择这种方法有几个原因

  1. 一兆字节和一公里是数据分析软件处理的方便大小。

  2. 每公里同步一次可确保由于噪声而从旋转编码器丢失的个别事件不会破坏当天剩余的所有数据。

  3. 一公里被确定为记录 GPS 信息的有用检查点。

  4. 这些文件不是每天重新创建,而是出于效率原因被覆盖。如果发生电源故障,几乎不可能找出文件的多少是新的,多少是前一天的;因此,必须丢弃部分写入的文件。丢弃最多一公里的数据是在文件数量和数据丢失量之间合理的权衡。

当然,一公里没有什么神奇之处。两公里或半公里可能也同样有效。

在从设备读取数据的同时,数据采集程序还会监视车轮的转速,以检查列车的速度是否高于 60 公里/小时。低于该阈值,数据被认为没有意义并被丢弃。特别是,当前正在写入的文件将被重置并在速度升至阈值以上后立即重新使用。当然,高达一公里的以高于 60 公里/小时的速度记录的数据将被丢弃,但实际上,60 公里/小时的阈值无论如何都只是一个粗略的猜测,因此丢弃一些以略高于 60 公里/小时的速度记录的数据不会造成任何损害。ICE 的典型行驶速度取决于轨道类型,分别为 100 公里/小时、160 公里/小时、250 公里/小时和 280 公里/小时,只有这些速度是该项目的主要关注点。

数据采集程序相当简单,其中大部分用于处理读取或写入错误的情况。由于为 RTI-860 和 ADCO 都实现了设备驱动程序,因此数字化就像打开文件并从中读取一样容易。唯一需要稍微思考的是,两个驱动程序的数据速率不完全相同。在主循环的每个过程中从两个设备读取相同数量的数据很快就会填满其中一个驱动程序的缓冲区。在这种情况下,通用的解决方案是使用 select() 系统调用;但是,在给定的情况下,两个数据速率之间的确切比率是已知的,并且每次读取调用中从每个驱动程序读取的数据量都相应地选择。

cron 任务

凌晨两点,数据采集过程停止记录数据,以免干扰此时完成的其他工作。首先,cron 任务重新启动系统,作为预防内存泄漏的措施。尽管没有观察到任何内存泄漏,但重新启动没有任何成本,也不会造成任何损害。启动后,采集的数据通过作为 cron 任务启动的脚本写入磁带,该脚本最终调用 tar。

一个小小的麻烦是,如果启用了 DAT 驱动器的内部压缩,则几乎不可能找出磁带上使用了多少空间。假设每天的压缩率大致相同,则可能可以将两天的数据量或 1.5GB 的未压缩数据放到 2GB 的磁带上。由于模数转换器仅提供 12 位,这些位存储为 16 位值,因此压缩到 1.125GB 应该是微不足道的。可能还可以再减少 12%,因为大多数时候数字化信号不覆盖完整的 12 位。

在一天中的剩余时间,即不是在凌晨两点到四点之间,另一个 cron 任务每十分钟启动一次。作为针对数据采集程序中可能导致其崩溃的未知错误的措施,看门狗程序检查数据采集进程是否仍在进程表中,如果在表中,则假设它正在做一些有用的事情。如果它不在表中,则系统将重新启动。截至本文撰写之时,看门狗尚未证明其效用,因为在日志文件中未发现此类事件。

GPS 监视器

GPS 设备是一个可爱的小玩意,看起来像一个没有按钮的电脑鼠标。它的大小、形状和颜色与鼠标大致相同,安装在客车的顶部,以便清晰地看到天空。它通过串行线连接到计算机,串行线也为设备供电。GPS 一旦连接,它就开始发送几种类型的信息,可以使用像

cat /dev/ttyS1

一样简单的命令读取,只要 /dev/ttyS1 设置为正确的波特率即可。通过写入设备,可以对其进行编程以仅传递某些类型的信息。

高速数据采集有一个小缺点——它每秒只传递一个数据集。如上所述,定位信息被输入到每个大小为一公里的数据文件中。现在假设数据采集过程在采集到最后一个一公里样本后开始从 GPS 读取。读取可能需要长达一秒的时间,而车轮每秒最多旋转 28 次,从而丢失约 80 米的数据。

由于丢失数据被认为效率不高,因此引入了 gpsmonitor 程序,与数据采集过程并行运行。它以给定的每秒一次的速率读取位置信息,并将其存储在一个文件中,数据采集过程始终可以在该文件中获得最新信息。

为了确保数据采集过程不读取部分写入的数据集,通常有必要使用文件锁定机制来阻止采集过程在 gpsmonitor 写入数据时进行读取。但是,一个数据集只有 80 个字符长,并且在一个写入操作中发送到文件。检查 Linux 内核源代码可能会表明这并非完全是原子操作,但以最高可能的频率重新读取信息的进程的实验表明,80 个字符的写入被另一个进程中断的可能性实际上为零,即未观察到。因此,文件锁定被认为是不必要的开销。

设备驱动程序

对于 Linux 黑客来说,该项目最有趣的部分肯定是设备驱动程序部分。与往常一样,无法从要使用的板卡制造商处获得设备驱动程序。令人遗憾的是,没有测量硬件制造商认识到 Linux 作为测量平台的潜力。当然不是实时系统,但凭借当今快速的处理器和一些预防措施,Linux 能够以高速率且不丢弃数据的方式将数据流式传输到磁盘。

编写设备驱动程序似乎是一项艰巨的任务,事实证明确实如此,但原因与预期的不同。由于不太熟悉 Linux 的内部结构,因此首先似乎学习内核和驱动程序之间的接口可能是一个复杂的问题。事实证明,这几乎太微不足道了,不值得一提。借助早期版本的内核黑客指南、周围其他驱动程序的代码以及乐于助人的网络社区,内核和驱动程序之间的通信很容易建立。

糟糕的部分是硬件,主要是由于缺乏像样的文档。即使对于模拟设备,也几乎没有联系到德国经销商。Linux 仍然是闻所未闻的,所有可以获得的是 MS-DOS 的源代码和 RTI-860 的用户指南,其中包含完整的原理图。对于 ADCO,情况几乎相同。尽管如此,还是编写了驱动程序,并且今天的工作几乎是完美的。只有 RTI-860 驱动程序仍然包含一个讨厌的错误,可能是由于时序问题:清除板载内存和启用触发器不能以正确的顺序完成。无论先执行哪个操作,有时都会丢弃一些样本,大概只有在触发线在启用触发器后不久变为活动状态时才会发生这种情况。

另一个问题是内核本身。在 1.x 内核中观察到此问题,并且似乎在 2.0.x 内核中仍然存在。由于 ADCO 板只有一个 1 公里的样本 FIFO,并且必须在溢出之前清空,因此在 50KHz 采样率下,驱动程序必须以 50Hz 的速率读取数据。换句话说,驱动程序必须至少每 20 毫秒查看一次板卡。在典型的 Linux 内核中,时间片为 10 毫秒,这必须每隔一个节拍发生一次。对于那些不熟悉内核代码的人来说,应该注意的是,内核中有一个名为节拍的变量,该变量由定时器中断递增。在 Linux 内核中,节拍被非常精确地定义为 10 毫秒。特别是对于最近内核中可用的 POSIX 调度器,这不应该构成问题。与不断更改进程优先级以公平方式分配处理器时间的普通 Linux 调度器相比,POSIX 调度器允许将固定优先级附加到进程。有了正确的优先级,至少可以保证一个进程在发出请求后的下一个调度事件中获得处理器。这应该在下一个时钟节拍时,最多 10 毫秒。

在实践中,发现有时在 40、50 甚至 100 毫秒内没有发生调度,这甚至更令人恼火,因为当时没有其他进程处于活动状态。它看起来很像负责分页和/或交换的机制是造成这种情况的原因,但由于资源有限,无法进一步调查该问题。

作为一种权宜之计,利用了内核中的一种机制,该机制允许小段代码在两个节拍之间运行。尽管长达 100 毫秒内没有执行调度,但定时器中断没有被阻止,并且每 10 毫秒正常滴答作响。它的任务之一是运行由内核的其他部分在特定队列上注册的代码。通过注册一个将 ADCO 的 FIFO 读取到驱动程序内部缓冲区的功能,可以规避调度事件丢失的问题。事实上,甚至没有必要使用 POSIX 调度器。

结论、未解决的问题和经验教训

Linux 被证明是一个绝对稳定的软件开发和自主数据采集平台。在某些广泛使用的桌面程序启动器上众所周知的三指礼(ctrl-alt-del)在 Linux 上永远不需要。

使用带有板载内存的模数转换板可以排除所有实时约束。内存太小的板卡不容易支持。调度有时被抑制超过 100 毫秒的事实被认为是一个错误,并且首先导致与 Ingo Molnar (维也纳) 合作进行了一些忙碌而积极的内核调试。事实证明,问题似乎有不止一个原因,并且莫尔纳先生已将其报告给内核开发人员。但是,由于我们无法等待问题得到纠正(一个简单的补丁似乎不足以解决问题),因此选择了上述解决方案。

编程功能丰富的模数转换板被证明比预期的要复杂。即使是文档齐全的 RTI-834 的驱动程序也不容易,因为板卡子组件之间存在许多时间和逻辑依赖关系。模数转换板似乎普遍存在一个问题,即设计人员在一个板卡上放置了太多功能,从而引入了只有他们才能正确处理的依赖性和副作用。这可能是通常无法获得良好文档的原因——它根本不存在,因为没有人能够编写它。

测量设备的一个新的、非常有趣的趋势最近由 Intelligent Instrumentation(一家 Burr Brown 公司)发起。他们的 EDAS(以太网数据采集系统)是一个 16 通道、12 位、100KHz 的模数转换设备,可以连接到以太网。对于 UNIX,他们提供源代码库来与设备通信,即对其进行编程并读取数据。无需编写新的设备驱动程序。该设备可以连接到本地网络,或者,如果需要连续高速传输,则可以连接到其自己的“网络”——设备和计算机中专用以太网板之间的直接线路。然而,虽然这个想法非常好,并且类似于那些流行的网络摄像头,但 EDAS 在两个方面有点问题:一个小小的烦恼是它不理解 RARP(反向地址解析协议)。要设置其 IP 地址,必须通过串行线将其连接到计算机。一个更大的问题是该设备无法连续地将其采样的 100KHz 数据泵送到网络上。在最初的热情之后,当我们德国经销商告诉我们 EDAS 的微控制器可以以 100KHz 的频率填充内部 32 公里样本的内存,但流式传输数据到以太网的速度太慢时,我们感到非常失望。

考虑到 2500 德国马克(约 1400 美元)的价格,将单板 PC(1000 德国马克)与模数转换板(1000 德国马克)结合起来,并假设使用一些闪存 RAM 作为磁盘的替代品放入小机箱中会更便宜。安装一个最简化的 Linux 和一个合适的守护进程作为 IP 和模数转换板的设备驱动程序之间的接口,您就拥有了一个 iDAB(互联网数据采集盒)。根据应用程序的不同,您甚至可以安装软件来预处理数据,然后再将其传递到网络。

Linux on Track
Harald Kirsch 目前在 IITB 工作,在那里他成功地将他的团队从基于 DOS 的系统转换为基于 Linux 的系统。在他的空闲时间,他攻读学位。如果他在工作和学习之后有空闲时间,Harald 喜欢游泳、骑自行车和打排球和羽毛球。可以通过 kir@iitb.fhg.de 联系到他。
加载 Disqus 评论