探讨嵌入式Linu*系统设备驱动的开发与设计
【摘要】主要探讨了嵌入式linu*设备驱动程序的概念,
纳嵌入式linu*设备驱动程序的共性,阐述嵌入式linu*设备驱动程
序具体开发流程以及驱动程序的关键代码,总结嵌入式linu*设备
驱动程序开发的主导思想。
【关键词】嵌入式系统;linu*;设备驱动程序;内核
【abstract】thepaperpresentstheconceptofembedded
linu*devicedriverprogram,summarizedintheembeddedlinu*
devicedriverofgenerality,embeddedlinu*devicedriver
specificdevelopmentprocessaswellasthedriverofthekey
code,sumuptheembeddedlinu*devicedriverdevelopmentof
thedominantideology.
【keywords】embeddedsystem;linu*;devicedriver;
kernel
0序言
嵌入式系统被广泛运用到消费、汽车、电子、微控制、无线通讯、
数码产品、网络设备、平安系统等领域。越来越多的公司、研究单
位、大专高校、以及个人开场进展嵌入式系统的研究,嵌入式系统
设计将是未来相当长一段时间内研究的热点。
1linu*设备驱动程序概述
嵌入式linu*以其可应用于多种硬件平台、内核高效稳定、源码开
放、软件丰富、网络通讯和文件管理机制建立等优良特点linux移植,成为嵌
.z
入式系统领域中的一个研究热点。嵌入式linu*系统中,内核提供保
护机制,用户空间的进程通常不能直接硬件。进展嵌入式系统的开
发,很大的工作量是为各类设备编撰驱动程序,除非系统不使用操
作系统。linu*设备驱动程序在linu*内核源代码中占有很大比列,
从2.0、2.2到2.4版本的内核,源代码的宽度日渐降低,虽然主要
是设备驱动程序在降低。
设备驱动程序在linu*内核中占有非常重要的位置,它是内核用于
完成对化学设备的控制操作的功能模块。不仅cpu、内存以及其他
极少的几个局部之外,所有的设备控制操作都必须由与被控设备相
关的代码,也就是驱动程序来完成。内核必须包括与系统中的每位
外部设备对应的驱动程序。否则设备就难以在linu*下正常工作。这
就是驱动程序开发成为linu*内核开发的主要工作的诱因。从内核源
码的代码分布可以看出,设备驱动源码起码抢占了一半的内核源码
量,更能说明设备驱动程序对操作系统的意义和价值。
2嵌入式linu*设备驱动程序开发
2.1设备驱动程序工作原理
在linu*操作系统下有3类主要的设备文件类型:块设备、字符设
备和网路设备。这些分类方式可以将控制不同输入/输出设备的驱
动程序与其它操作系统软件别离开来。字符设备与块设备的主要区
别是:在对字符设备发出读/写恳求时,实际的硬件i/o通常紧接着
发生。块设备则不然,它借助一块系统显存作缓冲区,假定用户进
程对设备的恳求能满足用户的要求,就返回恳求的数据;否则,就
.z
调用恳求函数来进展实际的i/o操作。网路设备可以通过bsd套接
口数据。所有嵌入式linu*设备驱动程序都有一些共性,是编撰所有
类型的驱动程序都通用的,操作系统提供应驱动程序的支持也大致
一样。这种特点包括:
(1)读/写
几乎所有设备都有输入和输出。每位驱动程序都要负责本设备的
读/写操作,操作系统的其它局部不须要晓得对设备的具体读/写操
作是如何进展的,那些都由驱动程序屏蔽掉了。操作系统定义好一
些读/写插口,由驱动程序完成具体的功能。在驱动程序初始化时,
须要把具有这些插口的读/写函数注册到操作系统。
(2)中断
中断在现代计算机构造中有重要的地位,操作系统必须提供驱动
程序响应中断的能力。通常是把一个中断处理程序注册到系统中,
操作系统在硬件中断发生后,调用驱动程序的处理程序。linu*支持
中断的共享,即多个设备共享一个中断。
(3)时钟
在实现驱动程序时,好多地方会用到时钟,比如*些合同里的超时
处理,没有中断机制的硬件的寻址等。操作系统应为驱动程序提供
定时机制,通常是在预定的时间过了之后,反弹注册的时钟函数。
嵌入式linu*系统驱动程序开发与普通linu*没有太多区别。嵌入式
设备因为硬件种类十分丰富,在缺省的内核发布版中不可能包括所
有驱动程序。可以在硬件生产厂家或则intemet上找寻驱动程序,
.z
假如找不到,可以按照一个相仿硬件的驱动程序来改写。实现一个
嵌入linu*设备驱动的大致流程如下:(1)定义主、次设备号,也
可以动态获取;(2)实现驱动初始化和清除函数,假若驱动程序采用
模块形式,则要实现模块初始化和清除函数;(3)设计所要实现的文
件操作,定义file_operations构造;(4)实现所需的文件操作调用,
如read、write等;(5)实现中断效劳函数,并用requestirq向内
核注册;(6)将驱动编译到内核或编译成模块,用insmod命令加载;
(7)生成设备节点文件。
与普通文件相比嵌入式linux驱动程序实战开发 pdf,设备文件的操作要复杂得多,不可能简单地通
过read、write和llseek等来实现。所有其它类型的操作都可以
通过vfs的ioctl调用来执行,因此,只须要在驱动程序中实现
ioctl函数,并在其中添加相应的case即可。通过cmd分辨操作,
通过arg传递参数和结果。
2.2设备驱动程序的开发流程设备驱动插口
structfile_operationiodriver_fops=
{read:1odriver_read,
write:iodriver_write,
};
字符设备驱动插口中关键的file_operations构造:
的定义如下:
structfile_operations{
structmodule*owner;
.z
loft_t(*llseek)(structfile*,loff_t,int);
ssize_t(*read)(structfile*,char*,size_t,loft_t);
ssize_t(*write)(structfile*,constchar*,size_t,1off_t*);
int(readdirstructinode*,structfile*,void*,filldir_t);
int(*select)(structinode*,structfile*,int,selecttable*);
int(*ioct1)(structinode*,structfile*,unsignedint,unsigned
int);
int(*mmap)(structinode*,structfile*,struct
vm_area_struct*);
int(*open)(structinode*,structfile*);
void(*release)(structinode*,structfile*);
int(*fsync)(structinode*,structfile*);
};
2.2.2注册和注销模块
2.2.2.1设备注册模块
staticint_nitiodriver_init(void)
{intret=0:
ret=register_chrdv(major_num,“iodriver〞,iodriv
if(ret)
{printk(kern_alert“iodriverregisterfailure!〞)}
else
.z
{printk(kern_alert“iodriverregistersuccess!〞)}
returnret;
2.2.2.2设备注销模块
staticint_e*itiodriver_e*it(void)
{intret=0;
ret=unregister_chrdv(major_num,“iodriver〞);
if(ret)
{printk(kern_alert“iodriverunregisterfailure!〞);}
else
{printk(kern_alert“iodriverunregistersuccess!〞);}
returnret;
2.2.3根本入口点设备函数的具体实现
2.2.3.1设备读取模块
staticssize_tiodriver_read(structfile*file,char*buflinux学习,size_t
len,loft_t*off)
{if(__copy_to_user(bur,iodriver_var,sizeof(int)))
{retum_efault;}
retumsizeof(int);
2.2.3.2设备写入模块
.z
staticssize_tiodriver_write(structfile*file,constchar*buf,
size_tlen,loff_t*off)
{if(__copy_from_user(iodriver_var,buf,sizeof(int)))
{retum__efault;}
retumsizeof(int);
2.2.4module_init和module_e*it宏
module_init(iodriver_init);
module_e*it(iodriver_e*it);
3设备驱动程序编译到内核的过程
把驱动程序编译进内核的步骤如下:
(1)把iodriver.c复制到linu*-2.4.20-8/drivers/char下,并更改
该目录下的config.in文件,config.in是每位模块的配置脚本,在
这个文件当中定义配置这些模块、怎样配置等嵌入式linux驱动程序实战开发 pdf,因而当添加了io的
配置后,会在内核配置时出现这个模块的配置选项。
(2)更改当前目录下的makefile,在每位模块的makefile中包括
该模块所包含的子模块,在chardevices中,要包括io设备,就
要告诉makefile编译iodriver.c并包含编译出的iodriver.c文件,
这样最后内核做时,才能进这个模块。
(3)重新配置内核,选中io模块执行命令makemenuconfig,进
入内核配置菜单。
(4)重新编译内核,并更新嵌入式目标系统的内核。
.z
(5)成立设备文件,重新启动嵌入式目标系统的linu*,步入目录
/proc,查看devices文件,在devices文件列举了当前系统所有的
字符设备和块设备,包括设备号和设备名称,在character
devices的最后移行的设备是:254iodriver,这说明iodriver设备
早已正确地加载到了内核。
(6)添加设备文件节点,执行如下命令,添加设备文件节点,在
此成立的设备名称用于在应用程序中对应的设备。倘若为字符设备,
设备号类型用c表示,块设备则用b表示;主设备号就是
/proc/devices中的iodriver的设备号,因为该类设备只有一个,
因而次设备号为0,假如还有该类型的其他设备,则一次为1、2、
3等。
4完毕语
设备驱动程序是操作系统内核和机器硬件之间的插口。内核借助
驱动程序的插口完成对设备的初始化和释放,在系统内核和硬件之
间传送数据,并时刻检查和处理设备出现的错误。它是操作系统最
根本的组成局部,因而熟悉驱动的编撰是很重要的。
参考文献
[1]宋宝华.linu*设备驱动开发解读[m].:人民邮电,2008.
[2]赵炯.linu*内核完全分析--基于0.12内核[m].**:机械工
业,2009.
[3]魏永明.linu*设备驱动程序[m].:中国电力,2006.
[4]吴迪.嵌入式系统原理、设计与应用[m].:机械工业,2004.
.z
[5]罗苑棠.嵌入式linu*应用系统开发实例精讲[m].:电子工
业,2007.
.z