linux - 以低延迟访问 PCI 内存条 (Linux)
问题描述
背景:
我有一个 PCI 卡,它基本上是一个时钟。它通过 GPS 获取时间并将当前时间保存在某个寄存器中。
目标:
我想以尽可能低的延迟一次又一次地读取有限数量的寄存器/字节(例如当前时间)。(时钟提供了非常高的精度,我认为延迟越高,精度就越低。)。操作系统是红帽。编程语言是 C/C++。我还想写入设备内存,因此延迟不是问题。
可能的途径:
我看到了这些方式。如果你看到另一个,请告诉我:
- 编写 Linux 内核模块驱动程序,该驱动程序创建一个字符设备(或每个寄存器读取一个字符设备)。然后用户空间应用程序可以对 /dev/ 文件进行“读取”。
- DMA
- 通过用户空间应用程序(系统调用)将 sysfs resourceX 文件映射到用户空间。(例如这里)
- 编写实现 mmap 文件操作的 Linux 内核模块驱动程序。
问题:
- 在实际读取寄存器时,哪种方式延迟最低?我知道 mmap 在内核中会导致很多开销,但据我所知,这仅用于初始化。
- 方式3是合法的方式吗?对我来说,这看起来像是一个黑客。如何从应用程序中自动确定 /sys/ 路径?
- 方式3和4有区别吗?我是 PCI 驱动程序编程的新手,我想我并不真正了解 4 的工作方式。我读过这个(和那本书的其他章节),但也许你可以给我一个提示或一个例子。我会很感激的。
解决方案
方法 3 或 4 应该可以正常工作。它们之间在延迟方面没有区别。延迟大约为 100 ns。
如果您需要初始化设备,或者控制允许哪些应用程序访问它,或者一次强制一个阅读器等,则需要方法 4。方法 3 看起来有点像黑客,因为它跳过了所有这些。但如果你不需要这些东西,它会更简单。
字符设备的延迟肯定更高,因为每次读取设备时都需要内核转换。
DMA 方法的延迟完全取决于设备将时间写入内存的频率。CPU 访问内存的延迟比 MMIO 低,但如果设备每毫秒只执行一次 DMA,那么这就是您的延迟。此外,该方法会产生大量无用的 DMA 流量,因为 CPU 读取值的频率远低于写入值。
推荐阅读
- docker - 有没有办法让 docker 管道文件确定它运行的子节点的映像?
- c# - Linq 更新 - 无法对空引用执行运行时绑定
- javascript - dc.js,无法在复合图表上呈现线条?
- php - php的猫头鹰轮播克隆问题
- android - 未解决的参考 R 但应用程序构建和运行,Android Studio 3.2.1
- python - 如果 name 由 except...as 绑定,为什么 Python 3 会引发 NameError?
- android - Android:需要在 ARCore SDK 中节点旁边的平面中以相同的缩放比例缩放其大小后复制或复制/粘贴添加的对象
- c - 执行精英 el exe 失败
- sum - 具有重复记录 SUM 的查找集不起作用 SSRS 2008
- java - TestNG - 为类级别测试提供参数