我正在寻找一个PWM驱动程序。我知道有两种方法可以控制硬件驱动程序:
如果一般(不考虑PWM驱动程序的情况),我们必须决定是去用户空间还是内核空间驱动程序。那么我们必须考虑哪些因素呢?
答案 0 :(得分:35)
从您列出的这三个因素中,只有第一个实际上是正确的。至于其余的 - 不是真的。用户空间代码可以执行DMA操作 - 没有问题。有许多硬件设备公司在他们的产品中使用这种技术。即使所有I / O都使用完全内核旁路,也可以使用中断驱动的用户空间应用程序。当然,简单地在mmap()
上执行/dev/mem
并不容易。
你必须在内核中拥有驱动程序的最小部分 - 这是为了为你的用户空间提供内核所需的最小部分(因为如果你考虑它 - {{1} }也由字符设备驱动程序备份。
对于DMA,它实际上太简单了 - 您所要做的就是处理/dev/mem
请求并将DMA缓冲区映射到用户空间。对于中断 - 它有点棘手,内核必须由内核处理,无论如何,内核可能不会做任何工作,只是唤醒调用的进程,比如mmap
。另一种方法是通过DOSEMU向过程发送信号,但这非常慢,不推荐使用。
至于你的实际问题,你应该考虑的一个因素是资源共享。只要您不必跨多个应用程序共享设备,并且在用户空间中无法做任何事情 - 请转到用户空间。您可能会在开发周期中节省大量时间,因为编写用户空间代码非常容易。但是,当两个或多个应用程序需要共享设备(或其资源)时,您可能会花费大量时间使其成为可能 - 只要想象多个进程同时分叉,崩溃,映射(相同?)内存等等毕竟,IPC通常是通过内核完成的,因此如果应用程序需要开始相互“交谈”,性能可能会大大降低。不过,对于某些性能关键型应用程序,这仍然是在现实生活中完成的,但我不想深入研究这些细节。
另一个因素是内核基础架构。假设您要编写网络设备驱动程序。在用户空间中这不是问题。但是,如果你这样做,那么你也需要编写一个完整的网络堆栈,因为无法使用Linux内存中的默认堆栈。
如果可能的话,我会说用户空间,并且努力工作的努力量少于编写内核驱动程序,并记住有一天可能需要将代码移入内核。实际上,根据是否定义了一些宏,这是为用户空间和内核空间编译相同代码的常见做法,因为在用户空间中进行测试更加愉快。
答案 1 :(得分:8)
另一个考虑因素:调试用户空间驱动程序要容易得多。你可以使用gdb,valgrind等等。哎呀,你甚至不用C编写你的驱动程序。
除了用户空间或内核空间驱动程序之外,还有第三种选择:两者都有。您可以只在内核驱动程序中执行仅内核空间的操作,并在用户空间中执行其他所有操作。如果使用Linux UIO驱动程序框架,甚至可能不必编写内核空间驱动程序(请参阅https://www.kernel.org/doc/html/latest/driver-api/uio-howto.html)。
我很幸运地在用户空间中编写了一个支持DMA的驱动程序。 UIO提供基础设施,因此您只需读取/选择/ epoll文件即可等待中断。
您应该了解从用户空间编程DMA描述符的安全隐患:除非您在设备本身或IOMMU中有某些保护,否则用户空间驱动程序可能导致设备读取或写入任何地址物理记忆。