我有一个PCI卡,它基本上是一个时钟。它通过GPS获取时间并将当前时间保存在某个寄存器中。
我想一遍又一遍地读取有限数量的寄存器/字节(例如当前时间),并以尽可能低的延迟。 (时钟提供了很高的精度,我认为延迟越高,精度就会越低。)操作系统是RedHat。编程语言是C / C ++。我还想写入设备内存,因此延迟不是问题。
我看到了这些方式。如果您看到另一个,请告诉我:
答案 0 :(得分:1)
方法3或4应该可以正常工作。它们之间在延迟方面没有区别。延迟约为100 ns。
如果您需要初始化设备,或者控制允许哪些应用程序访问它,或者一次强制一个阅读器,等等,则需要方法4。方法3看起来有点像hack,因为它跳过了所有这个的。但是,如果您不需要这样的东西,则会更简单。
字符设备肯定有更高的延迟,因为每次读取设备时都需要内核转换。
DMA方法的延迟时间完全取决于设备将时间写入内存的频率。 CPU访问内存的延迟低于MMIO,但是如果设备仅执行一次毫秒的DMA操作,那将是您的延迟。另外,由于CPU读取值的频率远低于写入值,因此该方法会产生大量无用的DMA流量。
答案 1 :(得分:1)
添加到@prl的答案...
方法3在我看来似乎很合法。那就是它的目的。您可能需要看一下内核文档文件:https://www.kernel.org/doc/Documentation/filesystems/sysfs-pci.txt
您还可以使用/sys
文件系统查找设备。首先,记下时钟卡的供应商ID和设备ID(必要时还包括子系统供应商/设备),然后您可以轻松地遍历/sys/devices
层次结构,寻找匹配的设备(使用vendor
, device
等特殊文件)。找到文件后,大概可以从设备的数据表中知道要打开哪个resourceN
文件,然后mmap
以适当的偏移量打开文件即可。
所有这些都假定您的设备已经配置并启用。通常,系统启动时,PCI设备无法执行任何操作。一些驱动程序需要索取设备,并对其进行初始化/配置。一旦完成,如果仅通过读取一个或两个寄存器就可以访问时间,则可以使用方法3。(我不确定:PCI设备可能 自初始化,但我从未见过。我认为可能至少需要启用它的内存空间。如果设置足够小/足够简单,则可以从用户空间完成。)
方法4的主要区别在于,控制设备的驱动程序将提供支持以允许明确mmap
对该区域进行设置。对于用户空间应用程序,除了使用的设备名称之外,这两种方法之间几乎没有什么区别。对于方法4,驱动程序可能会提供一个象征性的设备名称/dev/clock0
或类似的名称,供用户空间应用程序使用(假定该应用程序然后不需要去查找该设备,它只是知道要打开的设备文件名)。
在用户空间中,您将使用两种方法中的相同方式执行mmap
操作。在方法4中,驱动程序在内部提供要映射的物理地址(可能还有偏移量),而不是通用PCI子系统这样做,但是无论哪种方式,它只是open
+ mmap
。>
Linux驱动程序编程并不十分困难,但是如果您以前没有做过,那会有很大的学习曲线,因此除非确实有必要,否则我绝对不会选择方法4。