




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
正如Linux torvalds 所说were back to the times when men were men and wrote their device drivers,come on ,then!以下我将我的小心得与大家分享,并请高手指点江山啊!1. Linux驱动程序接口系统调用是操作系统内核与应用程序之间的接口,设备驱动程序则是操作系统内核与机器硬件的接口。几乎所有的系统操作最终映射到物理设备,除了CPU、内存 和少数其它设备,所有的设备控制操作都由该设备特殊的可执行代码实现,此代码就是设备驱动程序。操作系统内核需要访问两类主要设备:字符设备和块设备。与 此相关主要有两类设备驱动程序,字符设备驱动程序和块设备驱动程序。Linux(也是所有UNIX)的基本原理之一是:系统试图使它对所有各类设备的输 入、输出看起来就好象对普通文件的输入、输出一样。设备驱动程序本身具有文件的外部特征,它们都能使用象open(),close(),read(),write()等系统调用。为使设备的存取能象文件一样处理,所有设备在目录中应有对应的文件名称,才可使用有关系统调用。通常Linux驱动程序接口分为如下四层:1).应用程序进程与内核的接口;2).内核与文件系统的接口;3).文件系统与设备驱动程序的接口;4).设备驱动程序与硬件设备的接口。2. 驱动程序文件操作数据结构每个驱动程序都有一个file-operation的数据结构,包含指向驱动程序内部函数的指针。file-operation的数据结构为:struct file-operation int (*lseek)();int (*read)();int (*write)();int (*readdir)();int (*select)();int (*ioctl)();int (*mmap)();int (*open)();int (*close)();int (*release)();int (*fsync)();int (*fasync)();int (*check-media-change)();int (*revalidate)();内核中有两个表,一个用于字符设备驱动程序,一个用于块设备驱动程序。这两个表用于保存指向file-operation数据结构的指针,驱动程序内部函 数的地址保存在这一结构。内核用主设备号作为索引访问file-operation结构,可以访问驱动程序子程序地址。SBS617设备采用了PCI总线 字符设备的驱动程序实现方式。完成了设备驱动程序,经GNU软件编译,链接,产生一可加载模块,可以用于动态装入Linux操作系统内核,也可以在需要时 从内核中卸除。3. file_operations介绍在结构file_operations里,指出了设备驱动程序所提供的入口点位置,分别是:(1) lseek,移动文件指针的位置,显然只能用于可以随机存取的设备。(2) read,进行读操作,参数buf为存放读取结果的缓冲区,count为所要读取的数据长度。返回值为负表示读取操作发生错误,否则返回实际读取的字节 数。对于字符型,要求读取的字节数和返回的实际读取字节数都必须是inode-i_blksize的的倍数。(3) write,进行写操作,与read类似。(4) readdir,取得下一个目录入口点,只有与文件系统相关的设备驱动程序才使用。(5) selec,进行选择操作,如果驱动程序没有提供select入口,select操作将会认为设备已经准备好进行任何的I/O操作。(6) ioctl,驱动程序特殊控制入口点,进行读、写以外的其它操作,参数cmd为自定义的命令。 这是很有意思的部分,之后我会详尽介绍;(7) mmap,用于把设备的内容映射到地址空间,一般只有块设备驱动程序使用。(8) open,打开设备准备进行I/O操作。返回0表示打开成功,返回负数表示失败。如果驱动程序没有提供open入口,则只要/dev/driver文件存在就认为打开成功。(9) release,即close操作。设备驱动程序所提供的入口点,在设备驱动程序初始化的时候向系统进行登记,以便系统在适当的时候调用。4 PCI字符设备驱动程序要设计PCI设备驱动程序,必须进一步结合硬件设备和PCI总线的特性。设计PCI设备驱动程序的重要任务是找寻相应的硬件并实现对它的访问。作为外围设 备的硬件必须响应三种地址空间的访问,即内存,IO,寄存器地址空间。前两种地址空间可以为PCI总线上的所有设备共享。寄存器空间占用物理地址,可以通 过特殊的函数来访问配置寄存器。一旦可以访问配置寄存器,设备驱动程序就可以访问硬件了。每个设备的PCI配置寄存器均由256Bytes构成,其中64Bytes是标准化的,4Bytes标识了一个唯一的函数ID,通过这个ID驱动程序就可以定位该设备。存取系统中的字符设备和存取系统文件一样。应用程序使用标准的系统调用来打开、读写和关闭设备,就像使用一个文件-样。当字符设备初始化时,通过向chrdevs数组中添加一个入口,设备驱动程序在系统内核中注册。chrdevs数组由device_struct数据结构组成。设备的主设备号用来作为此chrdevs的索引,因为一个设备的主设备号是固定的。LINUX系统里,通过调用register_chrdev向系统注册字符型设备驱动程序。register_chrdev定义为:#include linux/fs.h#include linux/errno.hint register_chrdev(unsigned int major, const char *name,struct file_operations *fops);其中,major是为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态地分配一个主设备号。name是设备名。fops就是前面所说的 对各个调用的入口点的说明。此函数返回0表示成功。返回-EINVAL表示申请的主设备号非法,一般来说是主设备号大于系统所允许的最大设备号。返回-EBUSY表示所申请的主设备号正在被其它设备驱动程序使用。如果是动态分配主设备号成功,此函数将返回所分配的主设备号。5 PCI设备启动与检测PC主板BIOS在系统启动时,可以自动检测PCI设备并配置设备的每一地址区。当驱动程序访问设备时,它的内存、I/O地址空间已经映射到进程的地址空 间了。在驱动程序init_module()中,通过调用函数pcibios_find_device()函数返回设备在总线上的位置及函数指针,其中的 包含文件及函数原型为:#include Linux/pci.h#include Linux/config.h#include Linux/bios32.hint pcibios_find_device(unsigned short vendor,unsigned short id, unsigned short index,unsigned char *bus, unsigned short *function)6 地址空间访问在设备驱动程序检测到设备之后,通常要从三个地址空间读写数据,其中寄存器空间的读写尤为重要,因为只有通过它驱动程序才可能找到设备内存和I/O空间的映射地址。设备驱动程序通过调用以下函数实现寄存器空间的访问,其中的包含文件及函数原型为:#include Linux/bios32.hint pcibios_read_config_byte( unsigned char bus,unsigned char function,unsigned char where,unsigned char b*ptr)int pcibios_write_config_byte(unsigned char bus,unsigned char function,unsigned char where,unsigned char b*ptr)类似的还有:pcibios_read_config_word (), pcibios_write_config_word () ,pcibios_read_config_dword () ,pcibios_write_config_dword() 调用。PCI设备最多有6个地址区,类型可以为内存区或I/O区。接口板可以通过配置寄存器的PCI_BASE_ADDRESS_0到PCI_BASE_ADDRESS_5来报告各地址区的实际地址位置。内存、IO空间的访问通过inb(),memcpy()等调用。当然可以通过pcibios_read_config_byte(),pcibios_write_config_byte()来访问配置寄存器的相应基地址值。7 中断处理对中断的处理是属于系统核心的部分, PC主板BIOS为多数设备分配了一个唯一的中断号,在配置寄存器中保存,设备驱动程序通过pcibios_read_config_byte() 函数读取相应的值,格式为:xxx_irq=pcibios_read_config_byte(pci_bus,pci_device_fn,PCI_INTERRUPT_LINE,&pci_cofig-int_line)操作系统中有中断寄存器,将特定的中断请求与中断处理函数联系在一起,当中断发生时调用相应的中断处理函数处理。Linux操作系统下可用request_irq(),free_irq( )实现中断的请求,释放,其中包含文件及形式为:#include Linux/sched.hint request_irq(unsigned int irq,void (*handler)(int irq,void dev_id,struct pt_regs *regs),unsigned long flags,const char *device,void *dev_id);void free_irq(unsigned int irq, void *dev_id);参数irq表示所要申请的硬件中断号。handler为向系统登记的中断处理子程序,中断产生时由系统来调用,调用时所带参数irq为中断 号,dev_id为申请时告诉系统的设备标识,regs为中断发生时寄存器内容。device为设备名,将会出现在/proc/interrupts文件 里。flag是申请时的选项,它决定中断处理 程序的一些特性,有两种方式写中断方式设备驱动程序:即快中断方式和定时等待方式。采取快中断方式需要将request_irq()的第三个type类型 参数设为SA_INTERRUPT。 正常中断与快中断的区别在于: 从正常中断返回时,内核可以利用机会调度更优先的进程执行;而快中断不进行调度立即恢复被中断程序的执行.在LINUX系统中,中断可以被不同的中断处理程序共享,这要求每一个共享此中断的处理程序在申请中断时在flags里设置SA_SHIRQ,这些处理程 序之间以dev_id来区分。如果中断由某个处理程序独占,则dev_id可以为NULL。request_irq返回0表示成功,返回-INVAL表示irq15或handler=NULL,返回-EBUSY表示中断已经被占用且不能共享。中断处理函数形式为:void xxx_irq_handler(int xxx_irq,void *dev_id,struct pt_regs *regs)8 特殊控制函数ioctl()ioctl()具有设备特殊性,不同于read() , write(),在于它允许应用程序访问、配置设备,并进入可能的操作模式。 通常的read()、write()不能使用这些控制操作。ioctl()可以控制I/O通道。设备驱动的一个特点是要与其它设备硬件交换读/写的数据并 需要同步控制。多数的ioctl()由一系列的switch语句组成,ioctl()命令及操作选择考虑到硬件的特性和实际要实现的功能。写ioctl()程序之前,应选择相应的命令,不应该简单使用1-N的数字。选择ioctl()的命令有以下的考虑:首先命令码在系统中应该唯一,以避免与其它设备冲突,每个命令码应由多个比特域构成。参考两个文件来帮助选择ioctl()的命令,include/asm/ioctl.h及Documentation/ioctl_number.txt有如下定义:命令码有四个8比特组,其相应取值的宏定义及含义如下表:命令码取值宏定义及含义比特组名称 取值宏定义 含义type _IOC_TYEBITS 表示每个驱动程序唯一的类型标识number _IOC_NRBITS 表示序列号direction _IOC_NONE, _IOC_READ,_IOC_WRITE,_IOC_READ|WRITE 表示数据传输的方向size _IOC_SIZEBITS 表示传输数据的大小在头文件中定义了设置命令码的一些有用的宏:_IO(type,nr);_IOR(type,nr,size);_IOW(type,nr,size);_IOC_DIR(nr);_IOC_TYPE(nr);_IOC_NR(nr);_IOC_SIZE(nr);这些设置与具体的硬件功能有关,可以参考有关的硬件手册。通过以上方式可以设置命令、获得设备参数及实现控制操作,完成设备驱动程序的重要功能。对于设备驱动程序,ioctl() 函数非常重要,用户可以通过它来控制设备函数,获取状态信息,进行数据的读写。ioctl()在用户空间的形式为:int (*ioctl)(struct inode *inode , struct file *file ,unsigned int cmd , unsigned long arg)其中cmd相当于一个选择码,取决于使用的特殊控制命令,cmd命令通常在头文件中声明。直接的调用的格式为:temp = ioctl( fd, XX_xxxx, param* );fd是设备文件句柄。XX_xxxx 是控制码。Param是一个参数结构的指针,当调用ioctl()时,需要理解一些特殊参数结构 ,可以参考下面的四个表格。返回值0表示成功,-1失败。9.调用Linux内核函数Linux有许多内核函数可以调用。例如;1)memcpy_fromfs( *toptr, *fromptr, sizeof();/ 用于从文件系统传输数据2) memcpy_tofs ( *toptr, *fromptr, sizeof();/ 用于将数据传输到文件系统#include asm/segment.hvoid memcpy_fromfs(void * toptr,const void * fromptr,unsigned long n);void memcpy_tofs(void * toptr,const void * fromptr,unsigned long n);在用户程序调用read 、write时,因为进程的运行状态由用户态变为核心 态,地址空间也变为核心地址空间。而read、write中参数buf是指向用户程 序的私有地址空间的,所以不能直接访问,必须通过上述两个系统函数来访问用户程序的私有地址空间。memcpy_fromfs由用户程序地址空间往核心地 址空间复制,memcpy_tofs则反之。参数toptr为复制的目的指针,fromptr为源指针,n 为要复制的字节数。3) ptr = vmalloc( sizeof() );/ 动态分配内存4) vfree( ptr ); / 动态释放内存5) vremap( xxx_mapping chn .pci_addr,xxx_mapping chn .len );/ 映射PCI地址,chn = current_map_chn.6)作为系统核心的一部分,设备驱动程序在申请和释放内存时不是调用malloc和free,而调用kmalloc和kfree,定义为:#include linux/kernel.hvoid * kmalloc(unsigned int len, int priority);void kfree(void * ptr);参数len为希望申请的字节数,ptr为要释放的内存指针。priority为分配内存操作的优先级,即在没有足够空闲内存时如何操作,一般用GFP_KERNEL。7)与中断和内存不同,使用一个没有申请的I/O端口不会使CPU产生异常, 也就不会导致诸如segmentation fault一类的错误发生。任何进程都可以访问任何一个I/O端口。此时系统无法保证对I/O端口的操作不会发生冲突,甚至会因此而使系统崩溃。因此,在使用I/O端口前,也应该检查此I/O端口是否已有 别的程序在使用,若没有,再把此端口标记为正在使用,在使用完以后释放它。这样需要用到如下几个函数:int check_region(unsigned int from, unsigned int extent);void request_region(unsigned int from, unsigned int extent,const char *name);void release_region(unsigned int from, unsigned int extent);调用这些函数时的参数为:from表示所申请的I/O端口的起始地址;extent为所要申请的从from开始的端口数;name为设备名,将会出现在/proc/ioports文件里。check_region返回0表示I/O端口空闲,否则为正在被使用。在申请了I/O端口之后,就可以如下几个函数来访问I/O端口:#include asm/io.hinline unsigned int inb(unsigned short port);inline unsigned int inb_p(unsigned short port);inline void outb(char value, unsigned short port);inline void outb_p(char value, unsigned short port);其中inb_p和outb_p插入了一定的延时以适应某些慢的I/O端口。9)在设备驱动程序里,一般都需要用到计时机制。在LINUX系统中,时钟是由系统接管,设备驱动程序可以向系统申请时钟。与时钟有
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 稀土抛光粉工应急处置考核试卷及答案
- 金融客服考试题及答案
- 水声换能器制造工技能操作考核试卷及答案
- 民族拉弦弹拨乐器制作工质量管控考核试卷及答案
- 搅拌工职业技能考核试卷及答案
- 排水管道工技能巩固考核试卷及答案
- 矿井开掘工质量追溯知识考核试卷及答案
- 铸管制芯工入职考核试卷及答案
- 铝电解工知识考核试卷及答案
- 2025年外科创伤急救处理流程模拟考试卷答案及解析
- 学生课程免考(修)申请表(模板)
- 粘膜免疫 2课件
- 电子课件-《可编程序控制器及其应用(三菱-第三版)》-A04-1724-课题一-可编程序控制器基础知识
- 统计业务知识(统计法规)课件
- 实验计划样表
- 艾滋病个案流行病学调查表
- 广告策划与创意课件-2
- 地质勘察任务书模板
- 全国中心血站上岗证考试题库
- 环境社会学整本书课件完整版电子教案全套课件最全教学教程ppt(最新)
- 计算机组装与维护完整版课件(全)
评论
0/150
提交评论