我读到 Linux 中的设备驱动程序可以在用户模式或内核模式下运行。
我还知道 IO 设备可以通过以下两种方式之一访问:使用端口映射 IO,或使用内存映射 IO。
在端口映射 IO 中,我们使用指令IN
和来访问 IO 设备OUT
,而在内存映射 IO 中,IO 设备的寄存器被映射到内核空间内存(因此我们可以使用访问内存的常规 CPU 指令来访问它们,喜欢mov
)。
现在我想如果设备驱动程序不直接访问 IO 设备,而是通过与 IO 设备插入的 IO 端口的设备驱动程序通信(例如:通过与串行端口设备驱动程序(如果 IO 设备插入串行端口)。
但如果 IO 设备使用端口映射 IO,则IN
和OUT
指令是特权指令,因此需要处于内核模式才能使用它们。如果IO设备使用内存映射IO,则IO设备寄存器将映射到内核空间内存,并且需要处于内核模式才能访问内核空间内存。
所以我不认为直接访问IO设备的设备驱动程序可以在用户模式下运行。
我是正确的,还是我错过了什么?
答案1
Q. IN 和 OUT 指令是特权指令,因此需要在内核模式下才能使用它们
iopl()
。如果端口号足够低,您还可以选择使用ioperm()
.
显然并非所有架构都支持。
看使用inb、inl、inw从用户空间访问内核空间。这链接到操作方法以及示例代码的更新。
Q. 如果IO设备使用内存映射IO,IO设备寄存器将映射到内核空间内存,并且需要处于内核模式才能访问内核空间内存。
这玩意被XFree86/Xorg用来驱动图形适配器了!
你忘了提到中断。这是最困难的部分。幸运的是,这对于现代 PCI 设备来说是标准化的,因此可以在不需要特定于设备的内核驱动程序的情况下驱动它们。看用户空间 I/O HOWTO:通用 PCI UIO 驱动程序
我不确定访问 PCI 设备的具体细节和限制是什么。
不支持 DMA。您可以编写一个最小的 UIO 驱动程序来允许映射一些内存用于 DMA。请参阅 UIO 操作方法。然后你的用户空间驱动程序可以仔细地告诉设备 DMA 到哪里。如果出错,设备可能会写入系统 RAM 中的任何位置。乐趣!