1、字符设备与块设备的区别:1、字符设备是面向流的,最小访问单位是字节;而块设备是面向块的,最小访问单位是512字节或的更高次幂。、字符设备只能顺序按字节访问,而块设备可随机访问。3、块设备上可容纳文件系统,访问形式上,字符设备通过设备节点访问,而块设备虽然也可通过设备节点访问,但一般是通过文件系统来访问数据的。而网络设备没有设备节点,是因为网络设备是面向报文的,很难实现相关read、te等文件读写函数。所以驱动的实现也与字符设备和块设备不同。13 inx驱动的一些重要概念设备号Lin把所有设备都当作文件,为了管理这些设备,系统为它们各自都编了号,而每个设备号又分为主设备号和次设备号。主设备号用来
2、区分不同类型的设备,而次设备号用来区分同一类型内的多个设备(及其设备分区)。在建立字符驱动时需要做的第一件事是获取设备号。设备号的分配方式一般有种,静态分配和动态分配,静态分配设备号,就是驱动程序开发者,静态地指定一个设备号。对于一部分常用的设备,n内核开发者已经为其分配了设备号。这些设备号可以在内核源码documenatn/dvcestxt文件中找到。如果只有开发者自己使用这些设备驱动程序,那么其可以选择一个尚未使用的设备号。当添加新硬件时,很可能造成设备号冲突,影响设备的使用。为了解决手动分配设备号存在冲突的问题,内核开发者提出动态分配设备号的方法。使用该方法驱动程序在加载的时候,通过ux
3、内核提供的专门的函数动态获取设备号。nt allochrvregn(ev_t *ev, nsigne basemor, unsignedcun, const char*ame)设备节点in系统中对所有设备的访问都是基于文件的形式。对于每一种设备,在加载驱动程序的时候都会在de目录下创建一个文件,这个文件就是设备节点。对于每一个设备节点,在实际运行时, linu系统通过FS(虚拟文件系统)来完成将文件的各种系统调用与具体的驱动程序函数之间的映射。 设备节点可以通过mkn命令在系统启动的时候手动创建,也可以通过udv自动创建。在驱动用加入对dev的支持主要做的就是:在驱动初始化的代码里调用内核提供
4、的API向内核注册驱动信息clscreat:创建clas class_ece_crea :创建dvie驱动加载时会在/sys/lass目录下生成与该模块相关的信息,同时用户空间中的udev会自动响应dice_crea()函数,去ssf下寻找对应的类从而创建设备节点。驱动初始化时,需要完成以下工作:1,通过allo_chrde_regio()及相关函数分配主/次设备号。 2,使用evccrete()创建/dev和/sys节点。 ,使用cde_n()和dv_a()将自身注册为字符驱动程序。混杂设备考虑到有的系统包含很多简单字符设备驱动,单独为这些设备分配设备号比较浪费资源,同时工作量也很大,lin
5、u系统针对这些情况推出了一种叫混杂设备模型的驱动框架(iscellaneus)。混杂设备主要有2个特征:)所有的mic设备被分配同一个主设备号MSC_AJO(10),但是可以选择一个单独的次设备号。如果一个字符设备驱动要驱动多个设备,那么它就不应该用isc设备来实现;2)混杂设备驱动初始化时,只需要执行简单的一个注册函数,即可自动完成设备号分配,设备节点创建,向内核注册等工作,极大的简化了驱动初始化流程。硬件IO操作IO端口与O内存x6体系和ARM体系的寻址方式是有差别的:在x86下,为了能够满足CPU高速地运行,内存与CP之间通过北桥相连并通过地址方式访问,而外设通过南桥与C相连并通过端口访
6、问。因为这两种访问方式的不同,linux分出了两种不同的访问操作:以地址方式访问硬件使用IO内存操作。以端口方式访问硬件使用IO端口操作。在ARM下也实现了类似的操作,通过两条不同的总线(HBUS和APB BS)来连接不同访问速度的外设。但是它与6不同,无论是内存还是外设,ARM都是通过地址访问。在AM下,访问寄存器就像访问内存一样从指定的寄存器地址获取数据,修改。所以,ARM下一般是使用O内存的操作。但这并不是说I端口的操作在ARM下不能用,它们的代码差不多,只是没有使用的必要,下面也将介绍O内存操作。如何使用IO内存获得硬件的地址我们不能在lnux使用实际的物理地址,要对指定的物理地址进行
7、操作,必须要先将物理地址与虚拟地址对应,通过虚拟地址访问。于是有了以下的物理地址映射函数:#incudevo*orema(unsged logphy_add,uiged lng ze);函数传入两个参数,需要访问的物理内存(寄存器)的首地址py_addr和这段内存区域的大小ize,返回与该段物理地址对应的虚拟地址。这段地址可以多次被映射,当然,每次映射的虚拟地址也不一样。ps =0x20f000; /、指定物理地址vir = (sined lg)iormap(ph,x0c);/2、通过iormp获得对应的虚拟地址/0c表示只要1字节的大小 GPECON = (unsigned log*)(vi
8、rt + 0x40);/3、指定需要操作的寄存器的地址*GECON &=(3 4); /配置GP1为输出端口为了实现更好的移植性,上面的程序就有缺陷了。内核建议,尽量使用内核提供的内存访问接口:#include/从内存读取数据,返回值是指定内存地址中的值usign int ioed(vid *adr)usigd nt ored16(oid *dd)unsigint orad32(oi *ddr)/往指定内存地址写入数据idowrite8( vaue,i *add)oidiowrt(16 vale, void *addr) owite32(u2 vl, void *ad)参照硬件说明,通过对寄存
9、器的控制实现操作硬件硬件说明文档驱动的调试Linux设备模型lnu系统作为开源的下系统,支持世界上大部分的硬件,导致iux内核看上去非常臃肿、杂乱、不易维护。为了优化,linu系统从26版本开始提出了全新的设备模型(也称作Dier el)概念。设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口。驱动的开发,就简化为对内核所规定的数据结构的填充和实现。1)Linux设备模型中包含四个重要概念:Bs、ls、Dvic、 Devicerive。us(总线):s(总线)是一类特殊的设备,它是连接处理器和其它设备之间的通道(chnnel)。在设备模型中,所有的设备都通过总线相连,甚至是那些内
10、部的虚拟平台总线(pltform bus).las(类):在Linux设备模型中,ass的概念非常类似面向对象程序设计中的Class(类),它主要是集合具有相似功能或属性的设备,这样就可以抽象出一套可以在多个设备之间共用的数据结构和接口函数。因而从属于相同lss的设备的驱动程序,就不再需要重复定义这些公共资源,直接从Clas中继承即可。Deice(设备):抽象系统中所有的硬件设备,描述它的名字、属性、从属的Bu、从属的Clss等信息。evie Drivr(驱动):Lnu设备模型用Drer抽象硬件设备的驱动程序,它包含设备初始化、电源管理相关的接口实现。而Lin内核中的驱动开发,基本都围绕该抽象
11、进行(实现所规定的接口函数)。2)Ln设备模型的运行机制配对(Math):当总线上添加了新设备或者新驱动函数的时候,内核会调用一次或者多次这个函数。举例,如果我现在添加了一个新的驱动函数,内核就会调用所属总线的match函数,配对总线上所有的设备,如果驱动能够处理其中一个设备,函数返回0,告诉内核配对成功。探测(pobe)当配对(mtch)成功后,内核就会执行device_drivr中的pro回调函数,而该函数就是所有ier的入口,可以执行诸如硬件设备初始化、字符设备注册、设备文件操作op注册等动作。所以说,真正的驱动函数入口是在prbe函数中。卸载(emoe) 当该驱动函数或者驱动函数正在操
12、作的设备被移除时,内核会调用驱动函数中的remoe函数调用,进行一些设备卸载相应的操作。atfrm设备针对一些可以通过CPU直接寻址的设备(比如集成在嵌入式SO芯片上的控制器,CPU可以直接访问其寄存器),liux内核在设备模型的基础上(eice和dece_driver),对这些设备进行了更进一步的封装,抽象出pltfm 、aform device和patrm dv,以便驱动开发人员可以方便的开发这类设备的驱动。paltfm设备对嵌入式Linu驱动开发是非常重要的,因为我们编写的大多数设备驱动,都是为了驱动pftm设备。由图片可知,Pltform设备在内核中的实现主要包括三个部分:Paform
13、 Bus,基于底层bus模块,抽象出一个虚拟的Platfrm bus,用于挂载Platorm设备;ltormDice,基于底层deie模块,抽象出aor Devc,用于表示Pafrm设备;ltform Dier,基于底层devcerivr模块,抽象出Platfor Drie,用于驱动Patform设备。Linux platform_dive机制和传统的eiceriver 机制(通过deregiter函数进行注册)相比,最大的区别在于pltform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过ltfo_dice提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性(这些标准接口是安全的)。latfor机制的本身使用并不复杂,由两部分组成:platorm_dvic和latfromdive。通过lator机
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1