宋宝华
1้引言
目前,软件工程师大致可分为两ä个层次:
1应用软件工ื程师rr:主ว要利用库函数和
进行应用软件的编写;
2๐固件工程师rrr:主ว要进行的移植及
设备驱动程序的设计。
般而言,固件工ื程师的要求要高于应用软件工程师的层次,而其中ณ的设备驱动
编程又是程序设计中比较复杂的部分,究其原因,主ว要包括如下几个方แ面:
1设备驱动属于内核的部分,编写设备驱动需要有定的操作
系统内核基础;
2๐编写设备驱动需要对硬件的原理有相当的了解,大多数情况下我们是针对
个特定的嵌入式硬件平台编写驱动的;
3设备驱动中广泛涉แ及到多进程并发的同步互斥等控制,容易出现b;
4由于属于内核的部分,设备驱动的调试也相当复杂。
目前,市面上的设备驱动程序参考书籍非常稀缺,少有的经典是由社区的
三位领导者rrrr编写的
rr目前该书已经出版到第3版,中文译本由á中国电力出版社出版。该书将设
备驱动编写技术进行了较系统的展现,但是该书所列举实例的背景过于复杂,使得读者需要
将过多的精力投放于对例子背景的理解上,很难完全集中精力于驱动程序本身。往往
需要将此书翻来覆去地研读许多遍,才能有较深的体会。
rr中英文版封面
本文将仍然秉承rr书以实例为ฦ主的风格,但是实例的背景将非
常简单,以求使读者能将集中精力于设备驱动本身,理解内核模块设
备驱动的结构设备驱动中的并发控制等内容。另外,与rr所
不同的是,针对设备驱动的实例,本文还给出了用户态的程序来访问该设备,展现设备驱动
的运行情况及用户态和内核态的交互。相信阅读完本文将为您领悟rr
书中的内容打下很好的基础。
本文中的例程除引用的以外皆由笔者亲自调试通过,主要基于的内核版本为ฦ24๒,
例子要在其他内核上运行只需要做少量的修改。
构建本文例程运行平台的个ฐ较好方法是:在平台上安装r虚拟机,
并在r虚拟机上安装ณr。注意安装ณ的过程中ณ应该选中“开发工具”和“内核开
发”二项如果本文的例程要在特定的嵌入式系统中运行,还应安装相应的交叉编译器,并
2
包含相应的源代码,如下图:
2内核模块
设备驱动属于内核的部分,内核的个模块可以以两种方式被编译和加
载:
1直接编译进内核,随同启动时加载;
2编译成个可加载和删除的模块,使用加载rb和命令类
似,但依赖于相关的配置文件,r删除。这种方แ式控制了内核的大小,而模块旦ຆ被
插入内核,它就和内核其他部ຖ分样。
下面我们给出个内核模块的例子:
所有模块都需要的头文件
&ุ相关宏
_""ิ;
___ຕ
{
r"";
rr0;
}
__ຕ_
{
r"";
3
}
__;
_ຕ_;
分析上述程序,发现个内核模块需包含模块初ม始化和模块卸载函数,前者在
的时候运行,后者在r的时候运行。初ม始化与卸载函数必须在宏_ຕ
和_使用前定义,否则ท会出现编译错误。
程序中的_"ิ"用于声明模块的许可证。
如果要把上述程序编译为个运行时加载和删除的模块,则编译命令为ฦ:
–__r__––rr24–
由此可见,内核模块的编译需要给指示–__r_ຕ_
–参数。选项跟着内核源代码中目录的路径。
下列命令将可加载模块:
下列命令完成相反过程:
r
如果要将其直接编译入内核,则ท需要将源代码文件拷贝入内核源代码的相
应路径里,并修改。
我们有必要补充下内核编程的些基本知识:
内存
在内核模式下,我们不能使用用户态的和r函数申请和释放内存。进
行内核编程时,最常用的内存申请和释放函数为在r文件中ณ声明的
和r,其原型为ฦ:
,ไrr;
r__r;๙
的rr参数通常设