linux的设备驱动一般分为几类?各有什么特点?

linux的设备驱动一般分为几类?各有什么特点?,第1张

大致分为三类,字符驱动,块设备驱动,网络设备驱动。

字符设备可以看成是用字节流存取的文件

块设备则可以看成是可以任意存取字节数的字符设备,在应用上只是内核管理数据方式不同

网络设备可以是一个硬件设备,或者是软件设备,他没有相应的read write,它是面向流的一种特殊设备。

在Linux中,字符设备驱动由如下几个部分组成。

1.字符设备驱动模块加载与卸载函数

在字符设备驱动模块加载函数中应该实现设备号的申请和cdev的注册,而在卸载函数中应实现设备号

的释放和cdev的注销。

Linux内核的编码习惯是为设备定义一个设备相关的结构体,该结构体包含设备所涉及的cdev、私有

数据及锁等信息。2.字符设备驱动的file_operations结构体中的成员函数

file_operations结构体中的成员函数是字符设备驱动与内核虚拟文件系统的接口,是用户空间对Linux

进行系统调用最终的落实者。设备驱动的读函数中,filp是文件结构体指针,buf是用户空间内存的地址,该地址在内核空间不宜直

接读写,count是要读的字节数,f_pos是读的位置相对于文件开头的偏移。

设备驱动的写函数中,filp是文件结构体指针,buf是用户空间内存的地址,该地址在内核空间不宜直

接读写,count是要写的字节数,f_pos是写的位置相对于文件开头的偏移。

由于用户空间不能直接访问内核空间的内存,因此借助了函数copy_from_user()完成用户空间缓冲

区到内核空间的复制,以及copy_to_user()完成内核空间到用户空间缓冲区的复制,见代码第6行和第14

行。

完成内核空间和用户空间内存复制的copy_from_user()和copy_to_user()的原型分别为:

unsigned long copy_from_user(void *to, const void _ _user *from, unsigned long count)

unsigned long copy_to_user(void _ _user *to, const void *from, unsigned long count)

上述函数均返回不能被复制的字节数,因此,如果完全复制成功,返回值为0。如果复制失败,则返

回负值。如果要复制的内存是简单类型,如char、int、long等,则可以使用简单的put_user()和

get_user()读和写函数中的_user是一个宏,表明其后的指针指向用户空间,实际上更多地充当了代码自注释的

功能。内核空间虽然可以访问用户空间的缓冲区,但是在访问之前,一般需要先检查其合法性,通过

access_ok(type,addr,size)进行判断,以确定传入的缓冲区的确属于用户空间。

Linux设备模型使用了三个数据结构分别来描述总线、设备和驱动。所有的设备和对应的驱动都必须挂载在某一个总线上,通过总线,可以绑定设备和驱动。

这个属于分离的思想,将设备和驱动分开管理。

总线是处理器和设备之间的通道。总线有多种类型,每种总线可以挂载多个设备。

在设备模型中,所有的设备都通过总线相连,以总线来管理设备和驱动函数。总线有bus_type结构表示。

设置总线的属性后,会在对应的总线目录下增加了一个新的文件,通过对该文件的读写访问,触发相应的函数 *** 作,从而实现/sys/的文件接口与内核设备模型的数据交互。

bus_attribute中有两个函数指针,show和store。

使用宏BUS_ATTR

BUS_ATTR(_name, _mode, _show, _store)

该宏会定义一个名叫bus_attr__name的bus_attibute的结构,并且成员name设置为_name,文件权限mode设置为_mode,两个函数调用分别人show和store。

使用以下调用:

该函数失败时返回错误号。

一旦调用该函数,会就在指定bus总线的目录下新建一个名叫_name的文件

驱动程序是在CPU运行时,提供 *** 作的软件接口。所有的设备必须有与之配套驱动程序才能正常工作。一个驱动程序可以驱动多个类似或者完全不同的设备。

和设备不一样的是,在注册驱动函数是必须指定该驱动函数对应的总线,因为驱动函数注册成功后,会存放在对应总线的driver目录下,如果没有总线,注册当然会失败。

1、定义结构体device_driver。

2、调用注册函数:

设备就是连接在总线上的物理实体。设备是有功能之分的。具有相同功能的设备被归到一个类,如输入设备(鼠标,键盘,游戏杆等)。

linux系统中每个设备都用一个device结构的表示

注册一个完整的device结构前,至少定义parrent、bus_id、bus和release成员

1、定义结构体device。

2、调用注册函数:

使用宏DEVICE_ATTR

DRIVER_ATTR(_name, _mode, _show, _store)

该宏会定义一个名叫driver_attr__name的driver_attibute的结构,并且成员name设置为_name,文件权限mode设置为_mode,两个函数调用分别人show和store。

一旦调用该函数,会就在指定dev设备的目录下新建一个名叫_name的文件.

设备模型是2.6内核新引入的特征。设备模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构。

sys下有如下目录

block:用于管理块设备,系统中的每一个块设备会在该目录下对应一个子目录。

bus:用于管理总线,每注册一条总线,在该目录下有一个对应的子目录。

其中,每个总线子目录下会有两个子目录:devices和drivers。devices包含里系统中所有属于该总线的的设备。drivers包含里系统中所有属于该总线的的驱动。

class:将系统中的设备按功能分类。

devices:该目录提供了系统中设备拓扑结构图。

dev:该目录已注册的设备节点的视图。

class/net/eth0的路径其实就是devices目录中一个网卡设备的软连接。

sys中的其他目录都是将device目录下的数据加以转换加工而得。上面的图中,将usb设备归类到bus总线上,又把它归类到class。正是在sys中有很多这样的结构,内核就有一个完整而且复杂的拓扑结构图。

而维护这些关系的结构体就包括kobject、kset、ktype和subsystem等数据结构

kobject是一个对象的抽象,它用于管理对象。每个kobject对应着sysfs中的一个目录。

kobject用struct kobject来描述。

kset是一些kobject的集合,这些kobject可以有相同的ktype,也可以不同。同时,kset自己也包含一个kobject。在sysfs中,kset也是对应这一个目录,但是目录下面包含着其他的kojbect。

每个kobject对象都内嵌有一个ktype,该结构定义了kobject在创建和删除时所采取的行为。

device和driver里面都有一个成员变量bus,表示它们归哪个总线管理;

bus里面则有两个链表,device链表和driver链表。

当有新的设备加入的时候,就会将它加入它对应的bus的device链表,然后在它的驱动链表中寻找是否有驱动driver和该device匹配成功,如果匹配成功设备就可以正常使用了,否则,不好意思继续等待。

当有新的驱动加入的时候,就会将它加入它对应的bus的driver链表,然后在它的设备链表中寻找是否有设备device和该driver匹配成功,如果成功设备就可以正常使用了

bus_add_device()

bus_probe_device

device_attach

__device_attach


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8566919.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-18
下一篇 2023-04-18

发表评论

登录后才能评论

评论列表(0条)

保存