【问题标题】:Userspace vs kernel space driver用户空间与内核空间驱动程序
【发布时间】:2013-02-23 13:42:25
【问题描述】:

我正在寻找编写一个 PWM 驱动程序。我知道有两种方法可以控制硬件驱动程序:

  1. 用户空间驱动程序。
  2. 内核空间驱动程序

如果一般情况下(不考虑 PWM 驱动程序的情况),我们必须决定是使用用户空间驱动程序还是内核空间驱动程序。那么除了这些,我们还需要考虑哪些因素呢?

  1. 用户空间驱动程序可以直接将 /dev/mem 内存映射到其虚拟地址空间,无需上下文切换。
  2. 用户空间驱动程序不能实现中断处理程序(它们必须轮询中断)。
  3. 用户空间驱动程序无法执行 DMA(因为可以从内核空间分配支持 DMA 的内存)。

【问题讨论】:

  • 安全性:设备节点的文件权限控制用户可以打开/读取/写入设备。文件操作拒绝或允许并发操作。
  • 这个决定可能在很大程度上取决于您正在使用什么 PWM 以及使用什么硬件。
  • 还要注意你的内核代码必须放在 GPL 下。

标签: linux linux-kernel linux-device-driver embedded-linux


【解决方案1】:

从您列出的这三个因素中,只有第一个实际上是正确的。至于其余的——不是真的。用户空间代码可以执行 DMA 操作——这没有问题。有许多硬件设备公司在他们的产品中采用了这种技术。也可以有一个中断驱动的用户空间应用程序,即使所有的 I/O 都是通过完整的内核旁路完成的。当然,在/dev/mem 上做一个mmap() 并不容易。

您必须在内核中包含驱动程序的最小部分——这是为您的用户空间提供内核所需的最低限度所必需的(因为如果你考虑一下——/dev/mem 是也由字符设备驱动程序备份)。

对于 DMA,它实际上太简单了——您所要做的就是处理 mmap 请求并将 DMA 缓冲区映射到用户空间。对于中断——有点棘手,无论如何,中断必须由内核处理,然而,内核可能不做任何工作,只是唤醒调用epoll_wait()的进程。另一种方法是像 DOSEMU 那样向进程传递信号,但这样做很慢,不推荐使用。

至于您的实际问题,您应该考虑的一个因素是资源共享。只要您不必在多个应用程序之间共享设备,并且在用户空间中没有什么是您不能做的,那就去用户空间吧。您可能会在开发周期中节省大量时间,因为编写用户空间代码非常容易。然而,当两个或更多应用程序需要共享设备(或其资源)时,您可能会花费大量时间来实现它——想象一下多个进程同时分叉、崩溃、映射(相同?)内存等. 毕竟,IPC 通常是通过内核完成的,所以如果应用程序需要开始相互“对话”,性能可能会大大降低。不过,对于某些性能关键的应用程序,这仍然在现实生活中完成,但我不想深入了解这些细节。

另一个因素是内核基础设施。假设您要编写网络设备驱动程序。在用户空间中这样做不是问题。但是,如果您这样做,那么您也需要编写一个完整的网络堆栈,因为无法使用 Linux 内核中的默认堆栈。

如果可能的话,我会说去用户空间,让事情工作的努力比编写内核驱动程序要少,并记住有一天可能需要将代码移动到内核中。事实上,根据是否定义了某些宏,为用户空间和内核空间编译相同的代码是一种常见的做法,因为在用户空间进行测试要愉快得多。

【讨论】:

  • 然而epoll最终有一个快速的机制,它是一个轮询结构而不是一个中断处理程序。它可能会导致时间紧迫的操作出现问题。
  • @obayhan 您能否详细说明时间关键操作的投票问题?我使用这个“技巧”,我想知道更多。
【解决方案2】:

另一个考虑因素:调试用户空间驱动程序要容易得多。您可以使用 gdb、valgrind 等。哎呀,您甚至不必用 C 编写驱动程序。

除了用户空间或内核空间驱动程序之外,还有第三种选择:两者兼而有之。您可以在内核驱动程序中只做内核空间的事情,而在用户空间中做其他所有事情。如果您使用 Linux UIO 驱动程序框架,您甚至可能不必编写内核空间驱动程序(请参阅https://www.kernel.org/doc/html/latest/driver-api/uio-howto.html)。

我很幸运几乎完全在用户空间中编写了支持 DMA 的驱动程序。 UIO 提供了基础架构,因此您只需读取/选择/epoll 文件即可等待中断。

您应该认识到从用户空间对 DMA 描述符进行编程的安全隐患:除非您在设备本身或 IOMMU 中有一些保护,否则用户空间驱动程序可能会导致设备读取或写入任何地址物理内存。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 2014-04-28
相关资源
最近更新 更多