【问题标题】:Kernel to user space communication with low latency内核到用户空间的低延迟通信
【发布时间】:2018-05-07 09:09:49
【问题描述】:
  • 我的内核模块接收来自外部 GPIO 引脚更改的中断(上半部分)。
  • 收到中断后,内核模块应该唤醒或以某种方式调用用户空间中将开始处理的函数/线程。时间非常有限。
  • 无需发送数据,只需发送信号即可。
  • CPU 是多核的,用户空间应用程序将与一个核关联。

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

旁注:是的,我可以对它们进行基准测试,我问这个问题的原因是因为我可能不知道所有可能的解决方案

【问题讨论】:

    标签: c linux unix linux-kernel kernel-module


    【解决方案1】:

    中断处理程序可以直接写入进程提供的映射内存范围,而进程正忙于等待该内存位置更改。这甚至可以在上半部分执行,并且应该为您提供尽可能低的延迟。确保提供的内存位置被锁定在物理内存中,因为它在 isr 期间无法被分页。

    可以使用数据包套接字和 PACKET_MMAP 找到类似的方法,其中内核和用户空间之间的通信通过共享内存空间进行(请参阅Kernel Documentation)。

    如果您不关心通过操作系统进行资源管理(因为您只有一个应用程序等待外部输入),您也可以选择直接从用户空间访问硬件(使用 iopl/inb/outb 和朋友)。

    【讨论】:

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

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

    您的 4 个项目符号中列出的最长延迟操作是唤醒应用程序线程,因此如果您需要更短的延迟,您需要线程处于唤醒状态但等待事件。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-02
      相关资源
      最近更新 更多