2013-03-08 167 views
24

我正在寻找一个PWM驱动程序。我知道有两种方法可以控制硬件驱动程序:用户空间vs内核空间驱动程序

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

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

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

安全性:用户可以打开/读取/写入设备的设备节点控制的文件权限。文件操作拒绝或允许并发操作。 – sawdust 2013-03-08 06:47:41

+1

这个决定可能很大程度上取决于你在PWM中是什么,并且使用什么硬件。 – 2013-03-12 16:55:07

回答

31

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

您必须在内核中拥有驱动程序的最小部分 - 这是为了为您的用户空间提供内核所需的最低限度所需的内存所需的(因为如果您仔细考虑它 - /dev/mem也是由字符设备驱动程序备份)。

对于DMA,实际上它太容易了 - 您只需处理mmap请求并将DMA缓冲区映射到用户空间。对于中断 - 这有点棘手,中断必须由内核来处理,不管怎样,内核可能不会做任何工作,只需唤醒调用进程即epoll_wait()即可。另一种方法是像DOSEMU一样向流程发送信号,但这非常缓慢并且不被推荐。

至于你的实际问题,你应该考虑的一个因素是资源共享。只要您不必在多个应用程序之间共享设备,并且您在用户空间中无法做到的任何事情 - 请进入用户空间。由于编写用户空间代码非常简单,您可能会在开发周期中节省大量时间。但是,当两个或更多的应用程序需要共享设备(或其资源)时,那么您可能会花费大量时间使其成为可能 - 只需设想多个进程分叉,崩溃,同时映射(相同)内存等等毕竟,IPC通常是通过内核完成的,所以如果应用程序需要开始相互“交谈”,性能可能会大大降低。尽管如此,对于某些性能至关重要的应用,这仍然是在现实生活中完成的,但我不想详细说明这些细节。

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

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

+0

很好的回答。我正在寻找这些信息,你的回答非常有帮助。 – 2013-09-12 16:47:10

+0

然而,epoll有一个快速的机制,最后它是一个轮询结构而不是中断处理程序。它可能会导致时间关键型操作问题。 – obayhan 2016-11-30 09:24:17

6

另一个考虑:调试用户空间驱动程序要容易得多。您可以使用GDB,Valgrind的,等等哎呀,你甚至不用写你的驱动器C.

有不仅仅是用户空间或内核空间的驱动程序第三种选择:一些两者。你可以在内核驱动程序中只执行内核空间的东西,并在用户空间中执行其他任何操作。如果您使用Linux UIO驱动程序框架,则可能甚至不必编写内核空间驱动程序(请参阅https://www.kernel.org/doc/html/latest/driver-api/uio-howto.html)。

我已经有幸在用户空间中几乎完全写了一个支持DMA的驱动程序。 UIO提供基础设施,因此您可以在文件上读取/选择/ epoll以等待中断。

您应该认识到从用户空间编程DMA描述符所带来的安全隐患:除非您在设备本身或IOMMU中拥有某种保护,否则用户空间驱动程序可以使设备读取或写入任何地址在物理内存中。

相关问题