APP下载

嵌入式系统驱动程序研究及应用

2012-09-22罗志娟

长沙航空职业技术学院学报 2012年4期
关键词:驱动程序内核字符

罗志娟

(长沙航空职业技术学院,湖南 长沙 410124)

嵌入式系统是电子技术及计算机技术完美结合的产物。Linux因可应用于多种硬件平台、内核高效稳定、软件资源丰富、源代码开放、网络通信和文件管理机制完善等特点,已成为最具优势的嵌入式操作系统。[1]在嵌入式Linux操作系统中,出于对内核的保护,用户一般不能直接访问物理硬件资源,需要调用驱动程序实现对外设的控制。嵌入式系统的开发,重点和难点就在于驱动程序的开发,设备驱动程序的不同正是各内核版本之间的主要区别。

1 嵌入式驱动程序

设备驱动程序作为机器硬件和操作系统内核之间的接口,屏蔽掉硬件的细节,而应用程序通过系统调用与操作系统内核连接,将硬件设备看成是一个设备文件,操作硬件设备时就像操作普通文件一样,如图1所示。

图1 两种不同形式的生命教育体系

Linux操作系统下主要有块设备和字符设备两种设备文件类型。[2]当字符设备发出读/写请求时,实际的硬件I/O设备紧接着发生,如鼠标、键盘;而块设备不同,它利用一块系统内存作为缓冲区,只有当用户进程能满足用户对设备的请求,才会返回请求的数据,否则将调用请求函数来进行实际的输入输出操作,如硬盘。

Linux操作系统中,所有的设备文件都有文件属性、主设备号和从设备号。[3]其中文件属性用来区分设备类型(c表示字符设备,b表示块设备);主设备号用来标识驱动程序,从设备号标识同设备驱动程序下的不同硬件设备。值得注意的是,主设备号必须与登记设备驱动程序时申请的主设备号一致,否则用户进程无法访问驱动程序。用户进程通过设备文件就可以与实际的硬件通信了。

进行嵌入式系统的开发,只要用到操作系统,编写设备驱动程序就必不可少。嵌入式设备硬件种类异常丰富,虽然Linux内核源代码中已包含了很多的设备驱动程序,但仍不可能包括所有设备驱动,对于所需要的驱动程序,用户可以在硬件生产厂家或Internet上寻找,若找不到就要根据相近硬件的驱动程序来改写或重新编写。

2 驱动程序设计框架

2.1 驱动程序的基本工作原理

用户进程要与硬件打交道必须通过设备文件,而操作设备文件就是进行系统调用,数据结构file_operations在驱动程序与系统调用的关联过程中起着关键作用。[4]不同的内核版本,file_operations 结构存在着差异,file_operations的典型结构如下所示:

linux的设备驱动程序就是通过file_operations结构完成工作的。[5]它中间的每个成员都与一个系统调用相对应。当用户进程要操作设备文件时,系统调用利用其主设备号找到与之对应的驱动程序,同时获得file_operations中相应的函数指针,使该函数获得控制权。[6]因此,驱动程序开发的主要工作就是根据设备的需求,不断完善file_operations中的各个子函数。

2.2 驱动程序实例

给出一个简单的字符设备驱动程序(test_driver.c)实例,介绍字符设备驱动程序实现全过程。该设备名称为 test,主设备号为 240,驱动在Linux2.6内核中成功加载,并在长沙佳程科技公司提供的 VCM-L600税控收款机(采用三星S3C44B0芯片)上编写测试程序,调试成功。

2.2.1 主体程序编写

主体程序的编写实际上就是实现数据结构file_operations中某些子函数。本例中,当调用read时,函数read_test将被调用,它的作用是把1写进用户的缓冲区。其中,buf是用户进程空间的一个地址,read函数的一个参数,当read_test被调用时,系统进入了核心态,buf这个地址是不能直接使用的,要使用kernel提供的函数__put_user()把数据传送给用户。而且在向用户空间拷贝数据之前,还要利用verify_area函数验证buf是否可用。函数read_test具体实现如下:

2.2.2 模块加载与卸载

驱动程序可以按照动态加载编译成模块(modules)或静态编译进内核(kernel)两种方式编译。静态编译进内核时,内核一旦启动,驱动程序即将自动加载,这样不仅会增加内核大小,也会使得内核的源文件被改动,设备也无法动态卸载,极不利于调试。故一般最基本的核心代码编译进内核中,而其他的编译为内核的模块文件。为了方便设备的卸载,通常采用动态编译的方式。在动态编译过程中使用insmod命令将模块动态加载到正在运行的内核,不需要时使用rmmod命卸载模块。

在动态编译过程中,若要将模块调入内存,则需使用insmod命令调用函数module_init,向系统的字符设备表登记一个字符设备test。Linux系统中若要在系统中登记字符型设备,则要调用内核函数register_chrdev。它含有三个参数:第一个设备号,用户可以根据需要指定,本例中指定为240,若为0,系统返回一个尚未被占用的设备号,第二个设备文件名,第三个为该驱动入口点的文件操作结构指针。如果登记成功,返回设备的主设备号,设备名将会出现在/proc/devices文件里;否则返回一个负值。若要卸载模块,则要用rmmod命令调用函数module_exit,内核函数unregister_chrdev会将字符设备test在系统字符设备表中占有的表项释放。

3 驱动程序的添加与测试

3.1 驱动程序的添加

设备驱动程序编写完成后,下一步就要将该驱动程序添加至内核中。要将驱动成功添加至内核就必须修改Linux的源代码,然后将内核重新编译。驱动程序嵌入内核可分为以下六个步骤:

1)将驱动源文件(test_driver.c)复制到linux2.4drivercharvcmdrv目录下。该目录保存了Linux下字符设备的驱动程序。

2)修改上述目录下的makefile文件,在文件中添加语句:

obj-$(config_vcm600_TEST)+=vcmdrv/test_driver.o

在配置Linux内核时若选择了支持新定义的设备,该语句可使得编译内核时将源文件test_driver.c 编译成目标文件 test_driver.o。

3)修改该目录下的config.in文件,在comment character devices?语句后添加语句:

bool‘VCM -L600 test driver’CONFI6_VCM600_TEST

4)打开 vendors/Samsung/44B0/下 makefile文件,添加节点:

Test,C,240,0

5)修改vendors/Samsung/44B0/下 rc文件,实现挂载

6)编译内核,利用make menuconfig将驱动程序的目标文件(test_driver.o)生成于内核目录driver/char/vcmdrv下。

至此驱动程序被加载进内核,若在/romfs/dev目录中看到@test?.C.240.0,说明该驱动已成功加载。

3.2 测试

为进一步验证驱动程序成功加载进内核,可编写一应用程序调用该驱动。应用程序(test_apply.c)如下,该程序打开设备test,即调入test的驱动程序,通过驱动程序中定义的read函数读取10个1存入buf中,最后在终端打印buf中的数据。

#include <stdio.h> //stdio.h标准I/O 库,提供了带缓冲的文件操作功能

#include <sys/types.h>//types.h中定义基本系统数据类型

#include <sys/stat.h> //stat.h 提供文件状态

#include <fcntl.h > //fcntl.h定义了一组基于C的非缓冲的文件操作函数,实现对文件的控制

应用程序编写好后,需将源文件编译为目标文件,通常有两种方法:①利用编译命令arm-elfgcc -elf2flt -o test_driver test_driver.c,将源程序编译为目标文件;②写好makefile文件放在与驱动程序相同目录下,在命令行输入make命令编译。这里采用第二种方法,makefile文件如下:

执行make命令调用makefile文件,生成应用程序test_apply.c的目标文件 test_apply.o。Makefile文件中,将应用程序的目标文件放在了nfs中,便于实现挂载。

重新编译内核后,将加载了新驱动的内核打包并利用tftp命令下载至目标机中,即可进入minicom终端,运行程序,查看结果。

4 结论

通过介绍嵌入式Linux设备驱动程序的工作原理,以字符设备驱动程序为实例,简述了字符设备驱动程序开发的基本流程。虽然驱动程序的种类随着设备的增加而日益繁多,而且某些设备驱动程序的开发还需要中断服务,但驱动程序和内核之间有严格定义、管理的接口,所以其基本的结构和开发过程都是建立在规范的基础上的,各种驱动程序的结构和开发过程是一致的,熟悉了驱动开发的基本流程后,就可进行各种设备驱动程序的开发了。

[1]李俊.嵌入式 Linux设备驱动开发详解[M].北京:人民邮电出版社,2008.

[2]张威,黄冲.嵌入式Linux设备驱动的设计方法研究[J].江西师范大学学报(自然科学版),2007,(7).

[3]戴明华,李长云,等.嵌入式Linux驱动程序框架研究综述[J].长沙大学学报,2012,(3).

[4]曹颖鹏.基于嵌入式Linux驱动程序的研究与设计[D].西安:西安电子科技大学,2010.

[5]如何编写 Linux设备驱动程序[EB/OL].http://bbs.chinaunix.net/thread-2047152-1 -1.html

[6]王骁俊.RMLinux在嵌入式设备上的移植及驱动开发[D]上海:上海交通大学,2008.

猜你喜欢

驱动程序内核字符
强化『高新』内核 打造农业『硅谷』
字符代表几
一种USB接口字符液晶控制器设计
图片轻松变身ASCⅡ艺术画
HBM电子称与西门子S7-200系列PLC自由口通讯
基于嵌入式Linux内核的自恢复设计
Linux内核mmap保护机制研究
计算机硬件设备驱动程序分析
微生物内核 生态型农资
基于MPC8280的CPU单元与内部总线驱动程序设计