我打算为一些内存映射硬件编写一个linux驱动程序(它在FPGA中,所以如果需要,我可以在两端调整这个内存映射接口)。
这个FPGA逻辑生成一系列数据报,我必须处理这些数据报,然后通过以太网链路进行传输。没有理由将处理或网络代码放在内核中,所以我要问的是将数据块从硬件移动到用户空间的“最佳”机制。最大的复杂因素是用户空间处理应该分布在多个进程中。
数据速率不是很高(高达1Mbps),mmio接口由相当深的FIFO(当前2KB,可能高达8KB)提供,因此我认为高优先级用户模式进程可以保持起来。
我真正喜欢的是指向具有现有多播用户空间接口的现有驱动程序的指针(并没有太多其他内容)。但是,必须做的事情的概要将是一个合理的替代品。
到目前为止,我收集了以下想法:
AF_NETLINK:支持多播,为我负责缓冲。但API不稳定,我必须定义一个新的套接字ID,可能与其他树内驱动程序冲突,用户模式界面非常专业,我不能使用像socat
这样的标准工具来测试数据流。
从用户空间传递数据报模式套接字或FIFO文件描述符,并写入(如何?)。我可以应用一个unix-domain数据报套接字组播补丁。
将字符模式设备暴露给单个高优先级用户模式应用程序,该应用程序充当unix域数据报套接字服务器并将数据报复制到每个连接节点。是否为字符模式设备保留了数据报边界(即,如果我的驱动程序read
函数返回的字节数少于fread
缓冲区大小,则fread
将该数据块作为一个单元返回,或者可以它是否碎片并重新组合块?如果我使用read (2)
而不是fread (3)
会有帮助吗?驱动程序的读取函数是否可以用EMSGSIZE
来表示数据报被截断,或者是仅适用于套接字?)
公开可以同时由多个用户模式应用程序打开的字符模式设备,并将数据缓冲到每个内核中。
我倾向于带有unix域服务器的字符模式设备,该服务器重新路由传入的数据包。这使我不必在内核驱动程序中实现缓冲逻辑。那么问题就变成了如何在发生中断时从select
调用唤醒用户进程或阻塞读取。似乎我的poll
函数可以读取控制寄存器并在数据已经可用时返回POLLIN|POLLRDNORM
,如果没有则取消屏蔽中断。然后中断处理程序将使用wake_up
将wait_queue
标记为就绪。 read
总是掩盖中断。
答案 0 :(得分:2)
我认为netlink是您的最佳选择。顺便说一下,你可以将netlink套接字视为普通套接字并使用POLL,EPOLL,选择它。
另外,'API不稳定'是什么意思? Netlink使用很多,它有一个相当不错的API。
您只需使用通用netlink发送(并可能接收)消息。如果存在单向通信,那么您的任务变得更加容易,即来自内核 - >用户空间。
编辑: 如果您有权访问,请参阅第9页。由Wrox撰写的专业Linux内核架构一书810(第12章)。据我所知,它有一个(相对)很好的描述,你可以如何使用netlink与userland进行通信。
netlink唯一的缺点是文档很少。否则,我认为没问题。
答案 1 :(得分:1)
我认为char驱动程序是更好的选择,因为你会发现更多 它的文档,内核部分更简单。 API是众所周知的,你会发现更多有char驱动程序经验的人。
从小开始,即使用基于阻塞读取的工作中断:
如果数据可用,则使用中断例程最终唤醒队列。
一旦有效,就实施民意调查。
答案 2 :(得分:1)
使用字符设备选项,来自用户空间的read(2)
将最终调用您的驱动程序的read()
功能(在您注册设备的struct file_operations
中指定)。因此,无论您是维护数据报边界,还是在各种故障情况下要返回的错误,都取决于您的实现。