我计划为一些内存映射硬件编写一个linux驱动程序(它在一个fpga中,因此如果需要,我可以在两端调整这个内存映射接口)。
这个fpga逻辑生成一系列数据报,我必须处理这些数据报,然后通过以太网链路进行传输。内核中没有处理或网络代码的原因,所以我要问的是将数据块从硬件移动到用户空间的“最佳”机制。最大的复杂性是用户空间处理应该分布在多个进程之间。
数据速率不是很高(高达1Mbps),MMIO接口是由一个相当深的FIFO(目前2KB,可以增加到8KB),所以我认为高优先级的用户模式进程可以跟上。
我真正喜欢的是一个指针,指向一个现有的多播用户空间接口的驱动程序(并且不太复杂)。但是,一个必须做什么的提纲将是一个合理的替代品。
到目前为止,我已经收集了以下想法:
af_netlink:支持多播,为我负责缓冲。但是api是不稳定的,我必须定义一个新的socket id,这个id可能与其他树内驱动程序冲突,而且用户模式界面非常特殊,我不能使用标准工具如socat来测试数据流。
从用户空间传入一个数据报模式套接字或fifo文件描述符,并写入(如何?)。我可以应用一个Unix域数据报套接字多播修补程序。
向单个高优先级用户模式应用程序公开字符模式设备,该应用程序充当Unix域数据报套接字服务器,并将数据报复制到每个连接的节点。是否为字符模式设备保留了数据报边界(即,如果我的驱动程序read函数返回的字节数小于fread缓冲区大小,则fread是否将返回的数据块作为一个单元,或者它是否可以分割和重新组合块?如果我使用read (2)而不是fread (3),会有帮助吗?驱动程序的read函数是否可以使用类似于EMSGSIZE的内容来指示数据报被截断,或者这是否仅适用于套接字?)
公开一个可由多个用户模式应用程序同时打开的字符模式设备,并将数据缓冲到内核中的每个应用程序。
我倾向于使用unix域服务器的字符模式设备来重新路由传入的数据包。这使我不必在内核驱动程序中实现缓冲逻辑。接下来的问题是,当中断发生时,如何从select调用或阻塞读取中唤醒用户进程。似乎我的poll函数可以读取控制寄存器,如果数据已经可用,则返回POLLIN|POLLRDNORM,如果不可用,则取消中断屏蔽。然后中断处理程序将使用wake_upwait_queue标记为就绪。read总是掩盖中断。

最佳答案

我认为char驱动程序是一个更好的选择,因为你会发现更多
它的文档,内核部分更简单。这个api是众所周知的,你会发现更多有char驱动经验的人。
从小处开始,即以工作中断为基础的阻塞读取:
如果没有可用的数据,则在队列上休眠
否则将可用数据返回到用户空间。
如果数据可用,中断程序最终会唤醒队列。
一旦成功,就执行poll。

08-06 02:12