首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数据采集设备的Linux驱动程序和API体系结构

数据采集设备的Linux驱动程序和API体系结构
EN

Stack Overflow用户
提问于 2015-08-07 11:09:57
回答 1查看 326关注 0票数 1

我们试图为一个自定义数据采集设备编写一个驱动程序/API,它捕获了几个“通道”的数据。为了便于讨论,让我们假设这是一个多通道的视频捕获设备。该设备通过8xPCIe Gen-1链路连接到系统,理论吞吐量为16 16Gbps。我们的实际数据速率将在2.8Gbps (~350 be /秒)左右。

由于数据速率需求,我们认为我们必须小心驱动程序/API体系结构。我们已经实现了基于描述符的DMA机制和相关的驱动程序。例如,我们可以从设备中启动256 it的DMA事务,并成功完成。然而,在这个实现中,我们只捕获内核驱动程序中的数据,然后删除它,我们根本没有将数据流到用户空间。本质上,这只是一个小的DMA测试实现。

我们认为我们必须将问题分为三个部分: 1.内核驱动程序2.用户空间API 3.用户代码

获取设备在PCIe地址空间中具有寄存器,该寄存器指示是否有从该设备读取的任何信道的数据。因此,我们的内核驱动程序必须轮询这个位向量。当内核驱动程序看到这个位集时,它会启动一个DMA事务。然而,用户应用程序不需要知道所有这些DMA事务和数据,直到整个数据块准备就绪(例如,假设设备为我们提供了每个事务的16行视频数据,但我们只需要在整个视频帧准备就绪时才通知用户)。我们只需要将整个帧传输到用户应用程序。

这是我们的第一次尝试:

  1. 我们的用户端API允许用户应用程序为“通道”注册一个函数回调。
  2. 用户端API有一个" start“函数,用户应用程序可以调用它,它使用ioctl向内核驱动程序发送启动消息。
  3. 在内核驱动程序中,在收到开始消息后,我们启动了一个内核线程,该线程持续监视“数据就绪”位向量,当它看到新数据时,将其复制到一个驱动程序分配(kmalloc)缓冲区中。它一直这样做,直到收集到的数据大小达到“帧大小”。
  4. 此时,自定义linux信号(类似于SIGINT、SIGHUP等)被发送到正在运行驱动程序的进程。我们的API捕获这个信号,然后调用适当的用户回调函数。
  5. 用户回调函数调用API (transfer_data)中的函数,该函数使用ioctl调用向内核发送用户空间缓冲区地址,内核通过向用户空间执行通道帧数据的copy_to_user来完成数据传输。

以上所有内容都正常工作,只是性能很差。我们只能达到2MB/秒的传输速率。我们需要完全重写这一点,我们对任何建议或例子的指针都是开放的。

其他说明:

  • 不幸的是,我们无法改变硬件设备中的任何东西。因此,我们必须轮询“数据就绪”位,并根据该位启动DMA。
  • 有些人建议将Infiniband驱动程序作为参考,但我们完全迷上了这段代码。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-15 20:13:43

你现在可能已经过去了,但如果不是的话,这是我的2p。

  1. 很难相信您的卡在传输数据时不会产生中断。它有一个DMA引擎,它可以处理‘描述符’,这大概是一个分散收集列表的元素。我假设它可以生成PCIe‘中断’;YMMV。
  2. 不要费心在内核中搜索现有的类似驱动程序。你可能会很幸运,但我怀疑不是。

您需要编写一个阻塞读,为其提供一个大内存缓冲区。驱动程序读取op (a)获取用户缓冲区的用户页列表,并将它们锁定在内存(get_user_pages)中;(b)使用pci_map_sg创建分散列表;(c)遍历列表(for_each_sg);(d)为每个条目写入相应的物理总线地址和数据长度,作为我假定的“描述符”。

该卡现在有一个描述符列表,这些描述符对应于大型用户缓冲区的物理总线地址。当数据到达卡时,它直接将其写入用户空间,写入用户缓冲区,而用户级读取仍被阻塞。当它完成描述符列表时,卡片必须能够中断,否则就没用了。驱动程序响应中断,并解除对用户级读取的阻塞。

就是这样。当然,细节是令人讨厌的,而且文档也不完整,但这应该是基本的架构。如果您真的没有中断,您可以在内核中设置一个计时器来投票以完成传输,但是如果它真的是一张自定义卡,您应该拿回您的钱。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31876296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档