驱动是软件和硬件沟通的桥梁,驱动大致可以分为:字符设备驱动(键盘、鼠标、串口等数据不可以随机访问,多不带缓冲区),块设备驱动(硬盘、flash等大容量数据存储设备,数据可随机访问,大都带有缓冲区),网络接口驱动以及特定类型驱动等。
驱动的两大任务:
1.最为系统调用的一部分而执行,运行在进程上下文。
2.负责处理中断,运行在中断上下文。
驱动是内核的一部分,驱动可以编译进内核,也可以以模块的形式只在用到的时候加载进内核,这样可以使内核尽量变得小,一般多采用模块加载的模式。
驱动的漏洞和缺陷将直接危害内核的安全。(应留心未初始的指针和恶意用户程序、缓冲区溢出等)
在编译时候应注意内核版本号
当设备驱动需要同时支持不同版本内核时,在编译阶段,内核模块需要知道当前使用的内核源码的版本,从而使用相应的内核 API。
可以用uname -r命令查看版本号
版本号保存在/usr/include/linux/version.h中
其实宏定义#define LINUX_VERSION_CODE 132643里(我的内核是2.6.35)
132643是十进制表示,转化成16进制是0x020623(是2.6.35)
这里顺带推荐一下linux kernel cross reference这个网站,不解释,你懂得!
从2.4到2.6,外部可装载内核模块的编译、连接过程以及Makefile的书写都发生了改变。
2.4内核中,模块的编译只需内核源码头文件;需要在包含linux/modules.h之前定义MODULE;编译、连接后生成的内核模块后缀为.o。
2.6内核中,模块的编译需要配置过的内核源码;编译、连接后生成的内核模块后缀为.ko;编译过程首先会到内核源码目录下,读取顶层的Makefile文件,然后再返回模块源码所在目录。
3.linux内核模块的基本程序结构
#include<linux/kernel.h>
#incude<linux/module.h>
(必须有)模块许可声明:MODULE_LICENSE("GPL");
函数实现部分
(必须有)模块加载:module_init(函数名);
(必须有)模块卸载:module_exit(函数名);
模块参数、导出符号、和作者信息等可选