1

我打算为一些内存映射硬件编写一个linux驱动程序(它在一个FPGA中,所以如果需要我可以在两端调整这个内存映射接口)。

该 FPGA 逻辑生成一系列数据报,我必须对其进行处理,然后通过以太网链路进行传输。处理或网络代码都没有理由在内核中,所以我询问将数据块从硬件移动到用户空间的“最佳”机制。最大的复杂性是用户空间处理应该分布在多个进程之间。

数据速率不是很高(高达 1Mbps),mmio 接口由一个相当深的 FIFO(目前 2KB,可以增加到 8KB)提供,所以我认为高优先级的用户模式进程可以跟上。

我真正想要的是一个指向具有现有多播用户空间接口的现有驱动程序的指针(并且并不复杂)。但是,必须做的事情的大纲将是一个合理的替代品。

到目前为止,我收集了以下想法:

  • AF_NETLINK:支持多播,为我负责缓冲。但是API不稳定,我必须定义一个新的socket id,这可能与其他in-tree驱动程序冲突,而且用户模式接口非常专业,我不能使用标准工具socat来测试数据流。

  • 从用户空间传递一个数据报模式套接字或 FIFO 文件描述符,并写入它(如何?)。有一个我可以应用的 unix 域数据报套接字多播补丁。

  • 将字符模式设备暴露给单个高优先级用户模式应用程序,该应用程序充当 unix 域数据报套接字服务器并将数据报复制到每个连接的节点。是否为字符模式设备保留了数据报边界(即,如果我的驱动程序read函数返回的字节数少于fread缓冲区大小,将把fread该数据块作为一个单元返回,或者它可以分段和重新组装块吗?如果我使用read (2)而不是它有帮助fread (3)吗?是否有类似EMSGSIZE的驱动程序的读取函数可以用来指示数据报被截断,或者仅适用于套接字?)

  • 暴露一个可以被多个用户模式应用程序同时打开的字符模式设备,并将数据缓冲到每个内核中。

我倾向于使用具有重新路由传入数据包的 unix 域服务器的字符模式设备。这使我不必在内核驱动程序中实现缓冲逻辑。那么问题就变成了如何在select中断发生时从调用或阻塞读取中唤醒用户进程。如果数据已经可用,我的函数似乎poll可以读取控制寄存器并返回,如果没有,则取消屏蔽中断。POLLIN|POLLRDNORM然后中断处理程序将使用wake_up标记wait_queue为准备就绪。 read总是会屏蔽中断。

4

3 回答 3

2

我认为netlink是你最好的选择。顺便说一句,您可以将 netlink 套接字视为常规套接字并使用 POLL,EPOLL,选择它。

另外,“API 不稳定”是什么意思?Netlink 被大量使用,它有一个相当不错的 API。

您只需要使用通用网络链接来发送(并可能接收)消息。如果存在单向通信,即从内核 -> 用户空间,您的任务将变得更加容易。

编辑:如果您有访问权限,请参阅 pg。Wrox 出版的 Professional Linux Kernel Architecture 一书的 810 起(第 12 章)。据我所知,它(相对)很好地描述了如何使用 netlink 与用户空间进行通信。

netlink 的唯一不足是缺乏文档。否则,我认为没关系。

于 2011-04-27T20:46:31.017 回答
1

我认为 char 驱动程序是一个更好的选择,因为您会找到更多的文档,并且内核部分更简单。该 API 是众所周知的,你会发现更多有 char 驱动经验的人。

从小处着手,即使用基于工作中断的阻塞读取:

  • 如果没有可用数据,则在队列中休眠
  • 否则将可用数据返回到用户空间。

如果数据可用,中断例程最终会唤醒队列。

一旦它工作,实施民意调查。

于 2011-04-28T10:58:01.537 回答
1

使用字符设备选项,read(2)来自用户空间的最终将调用您的驱动程序read()函数(在struct file_operations您注册设备时指定)。因此,是否维护数据报边界以及在各种失败情况下要返回哪些错误取决于您的实现。

于 2011-05-04T03:06:51.617 回答