版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精品文档-下载后可编辑Linux系统下PCI设备驱动程序的开发摘要:以一个具体的PCI设备的驱动开发过程为基础,总结了与PCI设备驱动开发的相关问题,详细阐述了基本开发步骤、具体实现、驱动程序内核块的加载以及用户进程和驱动程序的协同工作问题。
1Linux系统下设备驱动的概念
Linux将所有外部设备看成是一类特殊文件,称之为“设备文件”,如果说系统调用是Linux内核和应用程序之间的接口,那么设备驱动程序则可以看成是Linux内核与外部设备之间的接口。设备驱动程序向应用程序屏蔽了硬件在实现上的细节,使得应用程序可以像操作普通文件一样来操作外部设备。
Linux抽象了对硬件的处理,所有的硬件设备都可以像普通文件一样来看待:它们可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作,而驱动程序的主要任务也就是要实现这些系统调用函数。Linux系统中的所有硬件设备都使用一个特殊的设备文件来表示,例如,系统中的个IDE硬盘使用/dev/hda表示。每个设备文件对应有两个设备号:一个是主设备号,标识该设备的种类,也标识了该设备所使用的驱动程序;另一个是次设备号,标识使用同一设备驱动程序的不同硬件设备。设备文件的主设备号必须与设备驱动程序在登录该设备时申请的主设备号一致,否则用户进程将无法访问到设备驱动程序。
在Linux操作系统下有两类主要的设备文件:一类是字符设备,另一类则是块设备。字符设备是以字节为单位逐个进行I/O操作的设备,在对字符设备发出读写请求时,实际的硬件I/O紧接着就发生了,一般来说字符设备中的缓存是可有可无的,而且也不支持随机访问。块设备则是利用一块系统内存作为缓冲区,当用户进程对设备进行读写请求时,驱动程序先查看缓冲区中的内容,如果缓冲区中的数据能满足用户的要求就返回相应的数据,否则就调用相应的请求函数来进行实际的I/O操作。块设备主要是针对磁盘等慢速设备设计的,其目的是避免耗费过多的CPU时间来等待操作的完成。一般说来,PCI卡通常都属于字符设备。
2Linux系统PCI设备驱动程序的开发
2.1基本需求分析
根据设备不同的用途,可以区分不同的PCI设备类型。基于这一设备类型,又可以分析出其他一些基本需求。从本文所使用的数据采集卡可知,其主要用途是用于采集和控制。根据工控过程的特点,需要PCI采集卡在每采样一个数据点时,就以中断的方式交给内核缓冲,再由用户程序适时取出使用。因此,将PCI采集卡作为一个字符设备来处理,并选择触发模式为内触发,数据传送模式为中断传送。本文就是基于这样的需求,按如下所述的步骤和具体实现过程,开发了其驱动程序。
2.2基本步骤
(1)PCI设备文件的建立
既然PCI设备被操作系统当作特殊的文件来看,就要有个文件名。因此,建立一设备文件的名字来代表硬件设备是开发驱动的步。按照习惯,设备文件都放在系统目录/dev下。一般在开发过程中,由于要经常查看设备文件的状态,而在这一目录下已经有很多设备文件,查看起来特别不方便,因此,可以自己在某个地方建立一个文件夹,将该设备文件放在该文件夹下。使用mknod命令可以建立设备特殊文件(注意:只有root账号的超级用户才能使用些命令),其格式示例为:
$mknod/subfolders/mydev/PCIdrvc2540
也就是用主设备号254(一般在Linux操作系统下设备文件的主设备号不会超过254,所以选用254,以确保该设备号是惟一的)和辅助设备号0在目录/subfolders/mydev下建立特殊设备文件PCIdrv。
(2)file_operation数据结构
Linux中的I/O子系统向内核中的其他部分提供了一个统一的标准设备接口,这是通过include/linux/fs.h中的数据结构file_operations来完成的:
structfile_operations{
structmodule*owner;
loff_t(*llseek)(structfile*,loff_t,int);
ssize_t(*read)(structfile*,char*,size_t,loff_t*);
ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);
int(*readdir)(structfile*,void*,filldir_t);
unsignedint(*poll)(structfile*,structpoll_table_struct*);
int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);
int(*mmap)(structfile*,structvm_area_struct*);
int(*open)(structinode*,structfile*);
int(*flush)(structfile*);
int(*release)(structinode*,structfile*);
int(*fsync)(structfile*,structdentry*,intdatasync);
int(*fasync)(int,structfile*,int);
int(*lock)(structfile*,int,structfile_lock*);
ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);
ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);
ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);
unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);
};
当应用程序对设备文件进行诸如open、close、read、write等操作时,Linux内核将通过file_operations结构访问驱动程序提供的函数。例如,当应用程序对设备文件执行读操作时,内核将调用file_operations结构中的read函数。
(3)编写驱动程序子函数
file_operation的数据结构中所定义的子函数的集合构成了具体的设备驱动的执行体。因此编写驱动程序子函数是开发过程中为重要的一步,这些子函数要根据具体的需求来设计。工作中用到的PCI采集卡的主要功能函数有:A/D转换函数AD_INT_Start、AD_INT_Stop、AD_INT_Data,数字量采集与输出函数DI_Data、DO_Data,D/A转换函数AO_Data等。这里不予赘述。
2.3PCI采集卡驱动程序的具体实现
(1)获取PCI采集卡的基本配置信息
PCI采集卡的驱动程序主要是完成对采集卡的寄存器和PCI总线控制器的PCI配置空间的设置和读取,用以启动采集卡,并按照一定的方式进行采集、传送、停止等。若要对这些寄存器进行设置和读取,就要知道这些寄存器的BaseAddress和偏移值、中断号等相关配置信息。这是对硬件操作的步。Linux操作系统对PCI设备提供了大量的初始化函数(这一点不同于Dos和Windows)。因此,在系统启动时,这特定的初始化函数会被调用,用来检测系统中存在的所有的PCI设备,并填充PCI设备的配置空间。因此,在开发PCI设备驱动时,只要执行相关的系统调用(由系统提供),就可获得所需要的PCI设备信息。
下面是几个常用的内核函数:
①pcibios_present()
②intpcibios_find_device(intdevice_id,intvendor_id,
intindex,int*bus_number,int*device_function)
③read_config_byte,read_config_word,read_config_dword
④write_config_byte,write_config_word,write_config_dword
函数①的功能是:返回一个布尔值表明所运行的计算机是否具有支持PCI设备的能力;函数②的功能是:返回设备在总线上的位置及函数指针bus_number、device_function;函数③、④的功能是:通过调用该类函数,设备驱动程序实现寄存器空间的访问,包括读和写。
(2)内存操作
设备驱动的子函数运行在内核态,在设备驱动程序中动态开辟和释放内存。用kmalloc或get_free_pages直接申请页而不是用malloc和free;释放内存用的是kfree或free_pages。kmalloc等函数返回的是物理地址,而malloc等返回的是线性地址,且kmalloc只能开辟128KB。
很多硬件需要一块比较大的连续内存用作DMA传送,并且需要一直驻留在内存,不能被交换到磁盘文件中去。但是kmalloc多只能开辟128KB的内存,这可以通过牺牲一些系统内存的方法来解决。具体做法是:若机器是32MB的内存,在lilo.conf的启动参数中加上mem=30MB,这样Linux就认为此机器只有30MB的内存,剩下的2MB内存在vremap之后就可以为DMA所用。
(3)Linux下的中断及中断处理
Linux中的中断处理程序很有特色。它的一个中断处理程序可分为上半部(tophalf)和下半部(bottomhalf)二个部分。之所以会有上半部和下半部之分,完全是考虑到中断处理的效率。上半部的功能是“登记中断”,当一个中断发生时,它就把设备驱动程序中中断例程的下半部挂到该设备的下半部执行队列中去,然后就等待新的中断的到来。这样一来,上半部执行的速度就会很快,它就可以接受更多设备产生的中断。上半部之所以要快,是因为它是完全屏蔽中断的,如果不执行完,其他的中断就不能被及时处理,只能等到这个中断处理程序执行完毕以后。所以,要尽可能多地对设备产生的中断进行服务和处理,确保中断处理程序的速度。
要使用一个中断,必须先向系统登记。实现系统中断登记的系统调用形式如下:
intrequest_irq(unsignedintirq,void(*handle)(int,void*,structpt_regs*),unsignedintlongflags,constchar*device);
其中:irq是要申请的中断号,handle是中断处理函数指针,flags是中断标识,device是设备名。
如果登记成功,则返回0。这时在/proc/interrupts文件中可以看到自己请求的中断。
(4)内核态和用户态下数据交换问题
用户进程在执行特定系统调用使用设备时,系统就从用户态进入内核态下运行,这时用户进程的环境仍然可用。但在内核缓冲区和用户进程缓冲区间进行数据交换时,必须要用内核提供的专门函数。主要有:put_user(),get_user(),copy_to_user(),copy_from_user()等。
通过这些调用来使用用户缓冲时还要进行用户缓冲读写权限的检验,否则调用数据交换函数时会出错。检验函数为:intverify_area(intaccess,void*u_addr,unsignedlongsize)。
3将驱动程序嵌入内核
由于驱动程序是在内核下运行,因此,要把编写的驱动程序嵌入内核。驱动程序可以按照二种方式编译,一种是编译进kernel,另一种是编译成模块(modules)。如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态卸载,不利于调试。所以推荐使用模块方式。这种方式可以用insmod命令来加载模块和用rmmod来卸载模块。
在用insmod命令将编译好的模块调入内核时,init_module函数被调用。在这里,init_module只做了一件事,就是向系统的字符设备表登记了一个字符设备。register_chrdev需要三个参数:其一是希望获得的设备号,如果为0,系统将选择一个没有被占用的设备号返回;其二是设备文件名;其三是用来登记驱动程序实际执行操作的函数指针。如果登记成功,则返回设备的主设备号;若不成功,则返回一个负值。
下面是用模块方法将驱动程序加载进内核时用的主要功能函数体示例,也就是当执行inmod命令时执行的函数体。
i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 学年湖南省邵阳市隆回县2026届高三上数学期末监测模拟试题含解析
- 胃癌术后护理措施
- 医疗数据合规性验证的共识算法优化
- 医疗数据区块链的安全评估指标体系
- 2026届湖南省湘南联盟生物高三上期末检测模拟试题含解析
- 医疗数据分级保护区块链标准体系构建
- 2026届江苏省姜堰区蒋垛中学生物高一第一学期期末综合测试模拟试题含解析
- 英语科技论文写作 课件 3-引言写作-21
- 贵州省长顺县二中2026届高一数学第一学期期末检测试题含解析
- 医疗数据共享区块链技术的安全性验证方法
- 2025食品行业专利布局分析及技术壁垒构建与创新保护策略报告
- 2025四川省教育考试院招聘编外聘用人员15人考试笔试模拟试题及答案解析
- 水产品速冻能效优化-洞察与解读
- 会议纪要标准化撰写格式及案例参考
- 2025年国家开放大学《刑事诉讼法》期末考试备考试题及答案解析
- 论文导论范文
- 贵州省铜仁市2024-2025学年高二上学期期末教学质量监测政治试卷(含答案)
- GJB573B-2020引信及引信零部件环境与性能试验方法
- 2025年重庆市直、区事业单位招聘考试(管理基础知识)历年参考题库含答案详解(5卷)
- 统编教材五年级上册语文全册课后习题参考答案完整版
- Unit5Theweatherandus单元整体(教学设计)-人教PEP版英语四年级上册
评论
0/150
提交评论