Jan Fan     About     Archive     Feed     English Blog

Device Driver, Kernel Module, and Hardware Programming

设备驱动(Device Driver)究竟是什么东西?

来,让我们把这些概念好好地理一理。

What is Device Drivers

In computing, a device driver is a computer program that operates or controls a particular type of device that is attached to a computer.

大多数重要的Driver程序都是运行在内核模态Kernel Space中的, 只有少数会运行在User Space上,比如USB Device Driver。

  +---+
  |App|
  +---+
    |
  +---+
  | OS|
  +---+
    |
 +------+
 |Driver|
 +------+
    |
  +---+
  | HW|
  +---+

A driver provides a software interface to hardware devices, enabling operating systems and other computer programs to access hardware functions without needing to know precise details of the hardware being used.

《Modern Operating System》里的一个图示很好地说明了OS-Driver-HW之间的协调关系,Driver让OS得以以统一的接口处理不同的硬件设备。

standard driver

Load Your Drivers- Loadable Kernel Modules

操作系统只提供了最基础的内存管理\进程调度等功能,并没有提供对多种硬件设备的操作能力,比如硬盘\网卡\打印机\显示器等。 现在的硬件设备数量众多,Kernel的开发必须把OS和Driver分离开,提供模块化的设计和开发能力。 比如Linux就提供了实时加载驱动模块的能力。

In Linux environments, programmers can build device drivers as parts of the kernel, separately as loadable modules, or as user-mode drivers.

所以,为OS编写一个module,就是在为一个或多个硬件设备开发驱动程序。

The Microsoft Windows .sys files and Linux .ko modules contain loadable device drivers.

Linux下提供了相应的命令去加载\移除驱动模块。

$ lsmod # List all loaded modules
$ insmod /lib/modules/3.5.0-30-generic/kernel/drivers/char/i8k.ko # Loading a module called i8k
$ rmmod i8k # Remove the module

modprobe也可以加载module,它和insmod的区别就在于它会把当前要加载module所依赖的其它modules都加载上去(Module Stacking,后面会解释),省得用户一个个依次地去加载。

module的移除,比较常见的就是退出我们的U盘的时候,它还经常失败呢:(

Module removal fails if the kernel believes that the module is still in use (e.g., a program still has an open file for a device exported by the modules)

A Kernel Module vs. An Application

Kernel Module同样作为代码程序,和我们所熟知的Desktop Applications\Software有什么不同呢? 了解这一区别能帮助你更好地理解驱动的本质。

Kernel Module是运行在内核中的,程序结束后没有人会给module收拾烂摊子,module没有像libc那样函数库可以用,module不像普通程序那样有一个固定int main()运行入口,module以源码的形式发布以兼容不同的机器平台。

The role of a module is to extend kernel functionality.

一个module一旦被加载,它对硬件设备的访问能力就可以被其它依赖它的module\OS及OS之上的用户程序所使用。

Hardware

现在我们明白了driver作为内核程序的概念,但还差那临门一脚——这个driver程序是如何与硬件设备通信的?

CPU与内存的通信是我们比较熟悉的,给定一个内存字节的地址(比如32位的机器,就是32条电路线),CPU就可以对这个字节的内容进行读写。 其实硬件设备也是类似的。

Every peripheral device is controlled by writing and reading its registers.

外部硬件设备(peripheral device)有它自己的电路控制系统,也就是它自己的小型CPU。 外设的寄存器就是外设与外部计算机的通信接口,通过传入不同的电路信号,寄存器被设定成不同的值,外设CPU\计算机CPU根据寄存器上不同的值执行不同的操作——打印什么字符\发送什么网络数据包。

+----------+
|peripheral|
|  device  |
+----------+
      |
 +---------+
 |Registers|
 +---------+
      |
  +--------+
  |Computer|
  +--------+

计算机如何访问外设的Register呢?I/O ports

Some processors (most notably the x86 family) have separate read and write electrical lines for I/O ports and special CPU instructions to access ports. Even processors that do not have a separate address space for I/O ports must fake reading and writing I/O ports.

I/O ports相当于外设Register的地址,CPU提供了相应的指令来访问这些I/O ports从而访问外设寄存器。 这与内存地址的概念是类似的,只不过两者的地址处于不同的地址空间。

in dest, src ; Read from a port
out dest, src ; Write to a port   

除了通过I/O ports来与硬件通信,有一些设备的寄存器也可以直接通过“映射内存”(Mapped Memory)来访问,比如显示器的渲染数据\网络包的数据内容等。

While use of I/O ports is common for ISA peripheral boards, most PCI devices map registers into a memory address region.

This memory can be used for a number of purposes, such as holding video data or Ethernet packets, as well as implementing device registers that behave just like I/O ports. One of the most well-known I/O memory regions is the ISA range found on personal computers. This is the memory range between 640 KB (0xA0000) and 1 MB (0x100000).

+----------+
|Peripheral|
|  device  |
+----------+
      |
 +---------+
 |Registers|
 +---------+
      |
   +-------+
   |Mapped-|
   |memory |
   +-------+
      |
  +--------+
  |Computer|
  +--------+

这样一层映射之后,对硬件的操作和对内存的操作就十分相似了,因为从程序员的角度看这两种内存基本上是等价的(当然也还是存在有差异,后面会说明)。

Memory-mapped registers and device memory, both are called I/O memory because the difference between registers and memory is transparent to software.

外设寄存器与计算机内存的主要差别,在于对其的访问操作能否被优化——缓存优化和指令顺序优化,另外外设的访问操作更耗时。

A driver must ensure that no caching is performed and no read or write reordering takes place when accessing registers.

Some platforms—most notably the i386—can have problems when the processor tries to transfer data too quickly to or from the bus.

解决的办法是在I/O操作指令之后加上nop空指令来延长CPU的操作时间。

in …
nop
out …
nop

最后

至此相信你对“驱动”的本质和内容已经有了足够的了解了吧,这篇文章提供了一个简易的驱动编写入门教程,如果你希望深入学习,那么这本open free book是一个不错的选择。

帮女同学重新系统之后记得要装上驱动噢:P

主要参考资料

Comments

多说 Disqus