上一节,我们讲了输入输出设备的层次模型,还是比较复杂的,块设备尤其复杂。这一节为了让你更清晰地了解设备驱动程序的架构,我们先来讲稍微简单一点的字符设备驱动。
这一节,我找了两个比较简单的字符设备驱动来解析一下。一个是输入字符设备,鼠标。代码在 drivers/input/mouse/logibm.c 这里。
* Logitech Bus Mouse Driver for Linux
*/
module_init(logibm_init);
module_exit(logibm_exit);
另外一个是输出字符设备,打印机,代码 drivers/char/lp.c 这里。
* Generic parallel printer driver
*/
module_init(lp_init_module);
module_exit(lp_cleanup_module);
内核模块
上一节,我们讲过,设备驱动程序是一个内核模块,以 ko 的文件形式存在,可以通过 insmod 加载到内核中。那我们首先来看一下,怎么样才能构建一个内核模块呢?
一个内核模块应该由以下几部分组成。
第一部分,头文件部分。一般的内核模块,都需要 include 下面两个头文件:
#include <linux/module.h>
#include <linux/init.h>
如果你去看上面两个驱动程序,都能找到这两个头文件。当然如果需要的话,我们还可以引入更多的头文件。
第二部分,定义一些函数,用于处理内核模块的主要逻辑。例如打开、关闭、读取、写入设备的函数或者响应中断的函数。
例如,logibm.c 里面就定义了 logibm_open。logibm_close 就是处理打开和关闭的,定义了 logibm_interrupt 就是用来响应中断的。再如,lp.c 里面就定义了 lp_read,lp_write 就是处理读写的。