基于嵌入式Linux设备驱动程序的开发肖杰.docx
- 文档编号:29418201
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:17
- 大小:25.42KB
基于嵌入式Linux设备驱动程序的开发肖杰.docx
《基于嵌入式Linux设备驱动程序的开发肖杰.docx》由会员分享,可在线阅读,更多相关《基于嵌入式Linux设备驱动程序的开发肖杰.docx(17页珍藏版)》请在冰豆网上搜索。
基于嵌入式Linux设备驱动程序的开发肖杰
基于嵌入式Linux设备驱动程序的开发
肖 杰 李仁发1 徐 成1
(湖南大学软件学院,计算机与通信学院1,长沙410082)
摘要 嵌入式系统的研究与开发成为当前的一个热点,Linux由于其优势成为很多厂家开发嵌入式应用的操
作系统。
驱动程序的开发己成为嵌入式系统开发的关键。
介绍了嵌入式Linux的特点,设备驱动程序的概
念,简述了基于uClinux下设备驱动程序的开发方法及过程,最后简述了字符设备驱动程序的开发的实例。
关键词 嵌入式系统 驱动程序 嵌入式Linux uClinux
2005年9月16日收到
第一作者简介:
肖杰,男,1974年生,湖南大学工学硕士研究生,
研究方向:
嵌入式系统、计算机网络。
湖南第一师范学校信息技
术系,邮编:
410002,
随着Internet的普及与发展,进入了后PC时
代,嵌入式系统的应用进入了一个全新的时期。
多
年以来嵌入式设备中没有操作系统,但随着硬件的
发展,嵌入式系统变得越来越复杂,有些功能必须
由操作系统提供,这样就出现了嵌入式操作系统。
目前主要的商业嵌入式操作系统有Vxworks、Win-
dowsCE、pSoS,但其价格昂贵、封闭的源代码以及产
品版税等限制了其普及和广泛应用。
嵌入式Linux
以其可应用于多种硬件平台、内核高效稳定、源码
开放、软件丰富、网络通信和文件管理机制完善等
优良特性而正在被广泛采用。
嵌入式Linux系统的软件开发涉及的内容很
多。
如网络、实时多任务、GUI系统、文件系统等,本
文基于嵌入式Linux操作系统下设备程序的开发,
阐述相关技术及设计方法。
1 嵌入式Linux操作系统
基于开放源代码的特性,Linux操作系统已经
日益成为一个成熟的操作系统,获得了广泛的使用
与认可,现在Linux广泛应用于各类计算,其中包括
微型Linux腕表、手持设备、因特网装置、瘦客户机、
防火墙等。
虽然大多数Linux系统运行于PC平台
上,但Linux的这些特点决定它同样适合于嵌入式
系统应用。
嵌入式系统所具有的特殊要求包括:
嵌入式系
统有不同程度实时性要求,嵌入式在体积、功耗等
方面受具体工作环境和开发生产成本的限制。
嵌
入式系统的操作系统应根据这些环境有很好的可
移植性、可配置性和可剪裁性,把Linux用于嵌入式
环境就必须修改Linux满足嵌入式的要求。
修改
Linux使其嵌入式化,主要集中在两方面:
一是体
积,二是实时性。
针对这两方面,国外一些公司和
研究机构开发各具特色的嵌入式Linux版本。
如:
RTLinux、KURT_Linux、uClinux、Xlinux和
Embedix等。
本文选用的嵌入式Linux为uClinux.uClinux
是专为无MMU的微处理器打造的嵌入式Linux操
作系统,由Linux2.0/2.4内核派生而来。
现在
uClinux越来越受到业界的青睐,被移植到更多的无
MMU芯片上[1]。
2 设备驱动程序
设备驱动程序是内核的一部分,是操作系统内核
和机器硬件之间的接口,它由一组函数和一些私有数
据组成,是连接应用程序与具体硬件的桥梁。
Linux
的一个基本特点是它对硬件设备的管理抽象化,系统
中的每一个设备都用一个特殊的文件来表示。
所有
的硬件设备都像普通的文件一样看待,使用与操作系
统相同的标准系统来进行打开、读写和关闭。
2.1 设备与驱动程序的分类
uClinux是由标准Linux派生而来,它们的设备
驱动开发基本相似,但标准Linux支持模块化,设备
驱动都写成模块的形式,而且要求可以在不同的体
系结构上安装。
uClinux是可以支持模块功能的,在
编译内核的时候可以选择支持或不支持模块功能,
但嵌入式系统是针对具体的应用,而且嵌入式系统
中内存空间资源比较紧张,所以在编译内核时,一
般选择不支持模块功能,这样uClinux的驱动程序
都是直接编译到内核中的。
在Linux操作系统下有3类主要的设备文件系
统:
块设备、字符设备和网络设备。
其中字符设备没
有缓冲区,数据的处理是以字节为单位按顺序进行
的,它不支持随机读写,也不允许查找操作。
系统的
串口以及终端,是常见的字符设备,嵌入式系统中简
单的按键、触摸屏、手写板也属于字符设备。
块设备
是指那些在输入输出时数据处理以块为单位的设备,
采用了缓冲技术,支持数据的随机读写,块设备可以
通过它们的设备做特殊文件访问,但是更常见的是通
过文件系统访问。
只有块设备上可以安装文件系统,
Linux的文件系统只有建立在块设备上。
典型的块设
备有硬盘、CD-ROM等。
而网络设备不同于字符设备
和块设备,它面向的上一层不是文件系统而是网络协
议层,是通过BSD套接口访问数据。
设备之间的分类不是绝对的,有些设备可以做字
符设备,也可以做块设备,如磁盘。
并不是每个驱动程
序都控制一台物理设备,通过设备驱动程序接口可以
创建一些伪设备,它们可以完成某些特殊的功能。
只
要把需要加入内核的功能做成伪设备驱动程序,就可
以将其加入内核,而不需要将内核重新定做。
与设备相对应的是三类设备驱动程序,字符设
备驱动程序、块设备驱动程序、网络设备驱动程序,
系统调用是内核和应用程序之间的接口,而设备驱
动程序是内核和机器硬件之间的接口,设备驱动程
序可以分成以下三个主要组成部分。
(1)自动配置和初始化子程序
负责检测所需驱动的硬件设备是否存在以及
是否能正常工作。
如果设备正常,则对设备及其驱
动程序所需的相关软件状态进行初始化,这部分驱
动程序仅在初始化时被调用一次。
(2)服务I/O请求的子程序
是驱动程序的上半部分,调用这部分是系统调
用的结果。
系统认为这部分程序在执行时即可进
行调用的进程,由用户态变成了内核态,并具有进
行此系统调用的用户程序的运行环境。
(3)中断服务程序
又称驱动程序的下半部分,设备在I/O请求结
束或其他状态改变时产生中断。
中断可以产生在
任何一个进程运行时,因此中断服务程序被调用时
不能依赖于任何进程状态,因而也就不能调用任何
与进程运行环境有关的函数。
因为设备驱动程序
一般支持同一类型的若干设备,所以调用中断服务
子程序时都带有一个或多个参数,以唯一标识请求
服务的设备[3]。
2.2 设备驱动程序的file_operations结构
应用程序只有通过对设备文件的open、release、
read、write、ioctl等才能访问硬件设备。
在uClinux
源代码uClinux-dist/linux/include/linux/fs.h中定
义了uClinux驱动程序中必须使用的file_operations
结构,每个设备驱动都实现这个接口所定义的部分
或全部函数。
随着内核的不断升级,file_operations
结构也越来越大,不同的版本的内核会稍有不同。
file_operations定义如下:
int(*fasync)(structinode*,structfile*,int);
int(*check_media_change)(kdev_tdev);
int(*revalidate)(kdev_tdev);};
在这些函数指针中,open、release用于设备的打
开和关闭,是每个驱动程序都要实现的函数,其它
函数根据实际设备的作用不同而实现相应的函数。
这些操作函数将被注册到内核。
当应用程序对该
设备相应的设备文件进行操作时,内核会找到相应
的操作函数并进行调用〔4〕。
2.3 设备驱动程序的编写
分析驱动程序的file_operations结构,用户就可
以编写相应的外部设备驱动程序,其中的主要步骤
根据具体的设备驱动程序的需要,完成file_opera-
tions中的每个函数的编写。
已完成了设备驱动程
序编写的主要工作后必须定义一个初始化函数。
初始化函数主要的工作是:
对硬件寄存器进行设
置、初始化设备相关的参数、注册设备、注册设备使
用的中断和其它的一些初始化工作〔5〕。
2.4 设备驱动程序的初始化
设备驱动程序所提供的入口点,在设备驱动程
序初始化时向系统进行登记,以使系统在适当的时
候调用。
Linux系统中通常调用register_chrdev向系
统注册一个字符型设备。
register_chrdev定义为:
intreister_chrdev(unsignedintmajor,constchar
*name,structfile_operations*fops);
当设备驱动模块从Linux内核中卸载时,对应
的主设备号必须被释放。
在模块卸载调用cleanup_
module()函数时,应该调用下列的函数卸载设备
驱动:
intunregister_chrdev(unsignedintmajor,const
char*name);
初始化部分一般还负责给设备驱动程序申请
系统资源,包括内存、中断、时钟、I/O端口等,这些
资源也可以在open子程序或其它地方申请,这些资
源不用时应该释放,以利于资源的共享〔6〕。
如果设备需要IRQ支持,则要注册中断,注册
中断的函数:
intrequest_irq(unsignedintirq,void(*han-
dler)(int,void*,structpt_regs*),unsignedlong
flags,
constchar*device,void*dev_id);
3 设备驱动程序的编写实例
本实例的嵌入式芯片采用三星的S3C4510B芯
片,S3C4510B是一类性能价格比很高的16/32位
RISC微控制器。
内含一个由ARM公司设计的
ARM7TDMI处理器核。
字符设备的例子
staticintdemo_open(structinode*inode,structfile*file){
if(demo_flag==1){/*检查驱动忙否*/
return–1;
}
/*可以初始化一些内部数据结构*/
printk(KERN_CRIT“DEMO:
demodeviceopen\n);
MOD_INC_USE_COUNT;/*模块使用次数加1*/
demo_flag=1;
return0;
}
staticintdemo_release(structinode*inode,structfile*file){
if(demo_flag==0){
return0;
}
printk(KERN_CRIT“DEMO:
demodeviceclose\n”);
MOD_DEC_USE_COUNT;
demo_flag=0;
return0;
}
staticssize_tdemo_read(structfile*file,char*buf,size_tcount,loff
_t*offset){
/*检查是否已有线程在读数据,返回error*/
//DEMO_RD_LOCK;
printk(KERN_CRIT“DEMO:
demoisreading,demo_param=%
d\n”,demo_param);
//DEMO_RD_UNLOCK;
/*通常返回成功读到的数据*/
return0;
}
staticintdemo_ioctl(structinode*inode,structfile*file,unsignedint
cmd,unsignedlongarg){
if(cmd==COMMAND1){
printk(KERN_CRIT“DEMO:
setcommandCOMMAND1\n”);
return0;
3253期肖 杰,等:
基于嵌入式Linux设备驱动程序的开发
中的每一个设备都用一个特殊的文件来表示。
所有
的硬件设备都像普通的文件一样看待,使用与操作系
统相同的标准系统来进行打开、读写和关闭。
2.1 设备与驱动程序的分类
uClinux是由标准Linux派生而来,它们的设备
驱动开发基本相似,但标准Linux支持模块化,设备
驱动都写成模块的形式,而且要求可以在不同的体
系结构上安装。
uClinux是可以支持模块功能的,在
编译内核的时候可以选择支持或不支持模块功能,
但嵌入式系统是针对具体的应用,而且嵌入式系统
中内存空间资源比较紧张,所以在编译内核时,一
般选择不支持模块功能,这样uClinux的驱动程序
都是直接编译到内核中的。
在Linux操作系统下有3类主要的设备文件系
统:
块设备、字符设备和网络设备。
其中字符设备没
有缓冲区,数据的处理是以字节为单位按顺序进行
的,它不支持随机读写,也不允许查找操作。
系统的
串口以及终端,是常见的字符设备,嵌入式系统中简
单的按键、触摸屏、手写板也属于字符设备。
块设备
是指那些在输入输出时数据处理以块为单位的设备,
采用了缓冲技术,支持数据的随机读写,块设备可以
通过它们的设备做特殊文件访问,但是更常见的是通
过文件系统访问。
只有块设备上可以安装文件系统,
Linux的文件系统只有建立在块设备上。
典型的块设
备有硬盘、CD-ROM等。
而网络设备不同于字符设备
和块设备,它面向的上一层不是文件系统而是网络协
议层,是通过BSD套接口访问数据。
设备之间的分类不是绝对的,有些设备可以做字
符设备,也可以做块设备,如磁盘。
并不是每个驱动程
序都控制一台物理设备,通过设备驱动程序接口可以
创建一些伪设备,它们可以完成某些特殊的功能。
只
要把需要加入内核的功能做成伪设备驱动程序,就可
以将其加入内核,而不需要将内核重新定做。
与设备相对应的是三类设备驱动程序,字符设
备驱动程序、块设备驱动程序、网络设备驱动程序,
系统调用是内核和应用程序之间的接口,而设备驱
动程序是内核和机器硬件之间的接口,设备驱动程
序可以分成以下三个主要组成部分。
(1)自动配置和初始化子程序
负责检测所需驱动的硬件设备是否存在以及
是否能正常工作。
如果设备正常,则对设备及其驱
动程序所需的相关软件状态进行初始化,这部分驱
动程序仅在初始化时被调用一次。
(2)服务I/O请求的子程序
是驱动程序的上半部分,调用这部分是系统调
用的结果。
系统认为这部分程序在执行时即可进
行调用的进程,由用户态变成了内核态,并具有进
行此系统调用的用户程序的运行环境。
(3)中断服务程序
又称驱动程序的下半部分,设备在I/O请求结
束或其他状态改变时产生中断。
中断可以产生在
任何一个进程运行时,因此中断服务程序被调用时
不能依赖于任何进程状态,因而也就不能调用任何
与进程运行环境有关的函数。
因为设备驱动程序
一般支持同一类型的若干设备,所以调用中断服务
子程序时都带有一个或多个参数,以唯一标识请求
服务的设备[3]。
2.2 设备驱动程序的file_operations结构
应用程序只有通过对设备文件的open、release、
read、write、ioctl等才能访问硬件设备。
在uClinux
源代码uClinux-dist/linux/include/linux/fs.h中定
义了uClinux驱动程序中必须使用的file_operations
结构,每个设备驱动都实现这个接口所定义的部分
或全部函数。
随着内核的不断升级,file_operations
结构也越来越大,不同的版本的内核会稍有不同。
file_operations定义如下:
structfile_operations{
int(*lseek)(structinode*,structfile*,off_t,int);
int(*read)(structinode*,structfile*,char*,int);
int(*write)(structinode*,structfile*,constchar*,int);
int(*readdir)(structinode*,structfile*,void*,dilldir);
int(*select)(structinode*,structfile*,int,select_table*);
int(*ioctl)(structinode*,structfile*,unsignedint,unsigned
long);
int(*mmap)(structinode*,structfile*,structvm_area_struct*);
int(*open)(structinode*,structfile*);
int(*release)(structinode*,structfile*);
int(*fsync)(structinode*,structfile*);
324科 学 技 术 与 工 程6卷
摘要 嵌入式系统的研究与开发成为当前的一个热点,Linux由于其优势成为很多厂家开发嵌入式应用的操
作系统。
驱动程序的开发己成为嵌入式系统开发的关键。
介绍了嵌入式Linux的特点,设备驱动程序的概
念,简述了基于uClinux下设备驱动程序的开发方法及过程,最后简述了字符设备驱动程序的开发的实例。
关键词 嵌入式系统 驱动程序 嵌入式Linux uClinux
2005年9月16日收到
第一作者简介:
肖杰,男,1974年生,湖南大学工学硕士研究生,
研究方向:
嵌入式系统、计算机网络。
湖南第一师范学校信息技
术系,邮编:
410002,
随着Internet的普及与发展,进入了后PC时
代,嵌入式系统的应用进入了一个全新的时期。
多
年以来嵌入式设备中没有操作系统,但随着硬件的
发展,嵌入式系统变得越来越复杂,有些功能必须
由操作系统提供,这样就出现了嵌入式操作系统。
目前主要的商业嵌入式操作系统有Vxworks、Win-
dowsCE、pSoS,但其价格昂贵、封闭的源代码以及产
品版税等限制了其普及和广泛应用。
嵌入式Linux
以其可应用于多种硬件平台、内核高效稳定、源码
开放、软件丰富、网络通信和文件管理机制完善等
优良特性而正在被广泛采用。
嵌入式Linux系统的软件开发涉及的内容很
多。
如网络、实时多任务、GUI系统、文件系统等,本
文基于嵌入式Linux操作系统下设备程序的开发,
阐述相关技术及设计方法。
1 嵌入式Linux操作系统
基于开放源代码的特性,Linux操作系统已经
日益成为一个成熟的操作系统,获得了广泛的使用
与认可,现在Linux广泛应用于各类计算,其中包括
微型Linux腕表、手持设备、因特网装置、瘦客户机、
防火墙等。
虽然大多数Linux系统运行于PC平台
上,但Linux的这些特点决定它同样适合于嵌入式
系统应用。
嵌入式系统所具有的特殊要求包括:
嵌入式系
统有不同程度实时性要求,嵌入式在体积、功耗等
方面受具体工作环境和开发生产成本的限制。
嵌
入式系统的操作系统应根据这些环境有很好的可
移植性、可配置性和可剪裁性,把Linux用于嵌入式
环境就必须修改Linux满足嵌入式的要求。
修改
Linux使其嵌入式化,主要集中在两方面:
一是体
积,二是实时性。
针对这两方面,国外一些公司和
研究机构开发各具特色的嵌入式Linux版本。
如:
RTLinux、KURT_Linux、uClinux、Xlinux和
Embedix等。
本文选用的嵌入式Linux为uClinux.uClinux
是专为无MMU的微处理器打造的嵌入式Linux操
作系统,由Linux2.0/2.4内核派生而来。
现在
uClinux越来越受到业界的青睐,被移植到更多的无
MMU芯片上[1]。
2 设备驱动程序
设备驱动程序是内核的一部分,是操作系统内核
和机器硬件之间的接口,它由一组函数和一些私有数
据组成,是连接应用程序与具体硬件的桥梁。
Linux
的一个基本特点是它对硬件设备的管理抽象化,系统
}
if(cmd==COMMAND2){
printk(KERN_CRIT“DEMO:
setcommandCOMMAND2\n”);
return0;
}
printk(KERN_CRIT“DEMO:
setcommandWRONG\n”);
return0;
}
structfile_operationsdemo_fops={
open:
demo_open,
read:
demo_read,
release:
demo_release,
ioctl:
demo_ioctl,
};
staticvoiddemo_cleanup(void){
/*确保要清掉的模块是已初始化的*/
if(demo_initialized==1){
/*禁止中断*/
/*释放该模块的中断服务程序*/
unregister_chrdev(DEMO_MAJOR,“demo_drv”);
demo_initialized==0;
printk(KERN_CRIT“DEMO:
demodeviceiscleanup/n”);
}
return;
}
/*驱动程序初始化函数*/
staticintdemo_init(void){
inti;
/*确定模块以前未初始化*/
if(demo_initialized==1)
return0;
/*分配并初始化所有数据结构为缺省状态*/
i=register_chrdev(DEMO_MAJOR,“demo_drv”,&demo_fops);
if(i<0){
printk(KERN_CRIT“DEMO:
i=%d\n”,i)
return–EIO;
}
printk(KERN_CRIT“demo_drvregisteredsuccessfully:
)=\n);
/*请求中断*/
demo_initialized=1;
return0;
}
4 结束语
本文基于嵌入式Linux下的设备驱动程序的开
发,并例举一个字符设备驱动程序的实例,简述了
驱动程序的开发过程,熟悉了基本的流程,然后就
可以在其上开发各种各样的设备驱动程序了。
参考文献
1 杜威,慕春棣.基于uClinux的触摸屏软硬件设计与关键技术分
析.计算机工程与设计,2005;26(4):
915—917
2 李祥兵,郑扣根.Linux中I2C总线驱动程序的开发.计算机工程
与设计,2005;26
(1):
41—43
3 慕春棣.嵌入式系统的构建.北京:
清华大学出版社,2004
4 冯军,杨艳姿等.嵌入式Linux下网络设备驱动程序的开发.江南
大学学报(自然科学版),2004;3(5):
460—462
5 田志刚.嵌入式Linux系统及其应用研究.微计算机应用,2003;
24(5):
290—295
6 郑伟,王钦若.Linux内核空间设备驱动程序的开发.微计算机
信息,2003;19(12):
85—97
DevelopingDeviceDriverProgramBasedon
EmbeddedLinux
XIAOJie,LIRenfa1,XUCheng1
(Software
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 嵌入式 Linux 设备 驱动程序 开发