内核到用户空间的低延迟通信

4
  • 我有一个内核模块,可以从外部GPIO引脚变化接收中断(上半部分)。
  • 在接收到中断后,内核模块应唤醒或以某种方式调用用户空间中的函数/线程来启动处理。时间非常有限。
  • 不需要发送任何数据,只需发送信号。
  • CPU是多核的,用户空间应用程序将与一个核心相关联。

有很多种方法可以进行内核-用户空间通信。哪一种具有最低的延迟?(即ISR和唤醒函数之间的时间)。

(附注:是的,我可以对它们进行基准测试,我提问的原因是因为我可能不知道每种可能的解决方案)

2个回答

4
中断处理程序可以直接写入由进程提供的映射内存范围,而进程正在忙等待该内存位置的更改。这甚至可以在顶半部执行,并应为您提供最低的延迟时间。请确保所提供的内存位置已锁定到物理内存中,因为它不能在isr期间分页。
类似的方法也可以在数据包套接字和PACKET_MMAP中找到,在其中内核和用户空间之间的通信通过共享内存空间进行(请参见内核文档)。
如果您不关心通过操作系统进行资源管理(因为您只有一个等待外部输入的应用程序),则还可以选择从用户空间直接访问硬件(使用iopl/inb/outb等命令)。

我其实也在考虑使用轮询的方式,但不确定是否是个好主意。既然你也这么说了,那我就试一试。例如:在内核模块中创建一个缓冲区,并将其物理地址传递给用户应用程序。然后用户应用程序可以通过 mmap 到 /dev/mem 来以轮询模式访问这个物理内存。这是你想要的吗? - zupazt3
关于从用户空间直接访问硬件,您的意思是不使用中断,而是通过直接检查GPIO引脚的状态来进行轮询?我理解得对吗?这是一个有趣的方法,我之前并没有考虑过。 - zupazt3
1
@zupazt3 是的,如果直接从用户空间操作,则不可能使用中断。有几种可能性可以共享内存页面,你提出的是一种有效的方式。也可以在用户空间映射页面,并通过“ioctl()”或类似方法向驱动程序提供虚拟地址,但您必须关注虚拟地址的转换。 - Ctx

0

进程等待内核唤醒的标准方法是使用poll()系统调用,并让设备驱动程序的中断处理程序唤醒任何等待它的线程。

在你列出的4个操作中,唤醒应用程序线程的延迟时间最长,因此如果你需要更短的延迟时间,你需要让线程保持唤醒状态但等待事件发生。

我使用过的最低延迟机制是让中断在应用程序进程中写入一个单词,并让一个线程读取该单词并在值改变时继续执行。实际上,这是用户空间和内核空间之间的自旋锁。当你可以将CPU核心专用于自旋锁或者期望等待时间非常短时,请使用此机制。

你可以使用ioctl()传递一个用户空间指针给驱动程序,以便它知道要更新哪个单词。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接