代码之家  ›  专栏  ›  技术社区  ›  kiigass

低延迟访问PCI内存条(Linux)

  •  0
  • kiigass  · 技术社区  · 6 年前

    背景:

    我有一个PCI卡,基本上是一个时钟。它通过GPS获取时间,并将当前时间保存在某个寄存器中。

    目标:

    我想一次又一次地读取有限数量的寄存器/字节(例如当前时间),使用 最低可能延迟 是的。(时钟提供了非常高的精度,我想我会松懈精度越高的延迟。)操作系统是redhat。编程语言是C/C++。我还想写入设备内存,因此延迟不是问题。

    可能的方法:

    我明白这些。如果你看到另一个,请告诉我:

    1. 编写Linux内核模块驱动程序,创建一个字符设备(或每个寄存器读取一个字符设备)。然后,用户空间应用程序可以对/dev/文件执行“读取”。
    2. DMA系统
    3. mmap用户空间应用程序(systemcall)将sysfs resourcex文件映射到用户空间。(就像 here 例如)
    4. 编写一个实现mmap文件操作的linux内核模块驱动程序。

    问题:

    1. 在实际读取寄存器时,哪种方式的延迟最低?我知道mmap在内核中会导致很多开销,但据我所知,这只是初始化。
    2. 三号公路是合法的吗?在我看来,这是个小把戏。如何从应用程序自动确定/sys/path?
    3. 3路和4路有区别吗?我是PCI驱动程序编程新手,我想我不太了解Way4的工作原理。我读过 this (和那本书的其他章节),但也许你可以给我一个提示或一个例子。我会很感激的。
    2 回复  |  直到 6 年前
        1
  •  1
  •   prl    6 年前

    方法3或4应该可以正常工作。就潜伏期而言,它们之间没有区别。延迟大约为100纳秒。

    如果需要初始化设备,或者控制允许哪些应用程序访问它,或者一次强制一个读卡器等,则需要方法4。方法3看起来确实有点麻烦,因为它跳过了所有这些。但如果你不需要这样的东西就简单多了。

    字符设备的延迟肯定更高,因为每次读取设备时都需要内核转换。

    dma方法的延迟完全取决于设备将时间写入内存的频率。CPU访问内存的延迟比MMIO要低,但是如果设备每毫秒只进行一次DMA,那么这就是您的延迟。而且,这种方法会产生大量无用的dma通信量,因为cpu读取该值的频率远远低于写入该值的频率。

        2
  •  1
  •   Gil Hamilton    6 年前

    正在添加@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的主要区别在于,控制设备的驱动程序将提供支持,允许该区域 甲基丙烯酸甲酯 明确地说。对于用户空间应用程序,除了使用的设备名之外,这两种方法之间几乎没有区别。对于方法4,驱动程序可能会提供一个符号设备名 /dev/clock0 或者类似的东西供用户空间应用程序使用(假设应用程序不需要找到设备,它只需要 知道 要打开的设备文件名)。

    在用户空间中,您将执行 甲基丙烯酸甲酯 两种方法的操作方式几乎相同。在方法4中,驱动程序在内部提供要映射的物理地址(可能还有偏移量),而不是一般的PCI子系统这样做,但不管怎样,它只是 open + 甲基丙烯酸甲酯 是的。

    Linux驱动程序编程并不是很困难,但是如果你以前没有做过,那会有一个很明显的学习曲线,所以我绝对不会使用方法4,除非确实需要这样做。

    推荐文章