33

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

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

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

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

2 回答 2

41

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

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

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

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

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

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

于 2013-03-10T07:43:16.433 回答
9

Another consideration: it is far easier to debug user-space drivers. You can use gdb, valgrind, etc. Heck, you don't even have to write your driver in C.

There's a third option beyond just user space or kernel space drivers: some of both. You can do just the kernel-space-only stuff in a kernel driver and do everything else in user space. You might not even have to write the kernel space driver if you use the Linux UIO driver framework (see https://www.kernel.org/doc/html/latest/driver-api/uio-howto.html).

I've had luck writing a DMA-capable driver almost completely in user space. UIO provides the infrastructure so you can just read/select/epoll on a file to wait on an interrupt.

You should be cognizant of the security implications of programming the DMA descriptors from user space: unless you have some protection in the device itself or an IOMMU, the user space driver can cause the device to read from or write to any address in physical memory.

于 2013-06-07T17:34:52.527 回答