打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
学习Linux驱动的开发,初探设备模型的概念

试着总结一下,学习一下,至少现在的我对于设备模型这个概念,几乎完全不懂。

Linux设备模型中三个很重要的概念就是总线、设备和驱动,即bus、device、driver,而实际上内核中也定义了这么一些数据结构,分别为struct bus_type,struct device,struct device_driver,

原型定义均在include/linux/device.h中。而struct bus_type结构中两个非常重要的成员就是kset和kobject这两个结构体。

于是乎,Linux设备模型概念中重要的5个概念都引出来了,即设备模型

在具体实现方面分两个层次:

一是底层数据结构来实现基本对象及其层次关系:kobjects和ksets。

二是基于这两个底层数据结构上实现的设备模型:总线,设备,驱动。

一、底层数据结构:kobject,kset

kobject

结合面向对象的思维。这个kobject属于最基础的结构,也就是最高抽象层(有点像java中的Cobject类)。任何一个设备模型如总线,设备,驱动都属于一个kobject 。在实现上这种派生关系就是在结构体中包含一个kobject的变量。

这个在层次上处理最顶层的kobject结构提供了所有模型需要的最基本的功能:

1 引用计数 用于内核维护其存在与消亡

2 sys水利模型fs表示 每个sys/下的对象对应着一个kobject。

3 热拔插事件处理 处理设备的热拔插事件。

Kobjects 在内核中对应有一套申请,初始化,添加,注册,计数操纵,开释等函数 //2.6.10 struct kobject { char * k_name; //名称 char name[KOBJ_NAME_LEN]; struct kref kref; //计数 struct list_head entry;//用于连接到同类kobjects的链表 struct kobjectn * parent;//用于实现层次,指向其父对象 struct kset * kset; //用于实现层次,所属的集合 struct kobj_typen * ktype;//指向对象的类型 struct dentry * dentry; //指示在sysfs中的目录项 }; Kset和kobj_type

Kset在概念上是一个集合或者叫容器。实现了对象的层锅炉模型锅炉模型。所有属于一个ksets的对象(kobject)的parent都指向该ksets的kobj.同时这个对象都连接到kset 的list表上。同时位于ksets层次之上的是subsys,在最新的内核中已经取消subsys,由于它本质上也就是一个ksets。Kset有一套类似kobject的操纵,实现上只是进一步调用其自身kobj的相应操纵,究竟ksets本质上也是一个kobject。 //2.6.10 struct kset { struct subsystem * subsys; //在新内核中已经没有subsys概念了,同一用kests struct kobj_type * ktype; //类型 struct list_head list; //同一kset的链表 struct kobject kobj; //自身的kobjects struct kset_hotplug_ops * hotplu锅炉模型g_ops; }; 最后 属于同一个集合的对象可以拥有共同的属性:ktype 。

struct kobj_type { void (*release)(struct kobject *); struct sysfs_ops * sysfs_ops; struct attribute ** default_attrs; }; 所谓的属性更具体一点说就是一些键值对。并且在sysfs_ops中的show函数被文件系统调用来显示sys/下面对应进口各属性的值。

如此 ,kobjects与ksets实现层次树的底层骨架。

进一步地,通过封装这些底层结构来实现上层的设备驱动模型。

二、总线 设备 驱动

关于bus,关于device,关于driver,他们是如何建立联系的呢?

基本关系扼要的概括如下:

驱动核心可以注册多种类型的总线。

每种总线下面可以挂载很多设备。(通过kset devices)

每种总线下可以用很多设备驱动。(通过包含一个kset drivers)}

每个驱动可以处理一组设备。

这种基本关系的建立源于实际系统中各种总线,设备,驱动结构的抽象。

具体到usb设备就是usb core的代码会进行整个usb系统的初始化,比如申请struct bus_type usb_bus_type,然后扫描usb总线,看线上连接了哪些usb设备,或者说root hub上连了哪些usb设备

,比如说连了一个usb键盘,那么就为它预备一个struct device,根据它的实际情况,为这个struct device赋值,并插进devices链表中来。又比沙盘模型如root hub上连了一个普通的hub,那么除了要为这个hub本身预备一个struct device以外,还得继续扫描这个hub上是否又连了别的设备,有的话继续重复之前的事情,这样一直进行下往,直到完成整个扫描,终极就把usb_bus_type中的devices链表给建立了起来。

那么drivers链表呢?这个就不用bus方面主动了,而该由每一个driver本身往bus上面登记,或者说挂牌。具体到usb系统,每一个usb设备的驱动程序都会有一个struct usb_driver结构体,其代

码如下,来自include/linux/usb.h //2.6.10 struct usb_driver { struct module *owner; const char *name; int (*probe) (struct usb_inte***ce *intf, const struct usb_device_id *id); void (*disconnect) (struct usb_inte***ce *intf); int (*ioctl) (struct usb_inte***ce *intf, unsigned int code, void *buf); int (*suspend) (struct usb_inte***ce *intf, u32 state); int (*resume) (struct usb_inte***ce *intf); const str沙盘模型//" title="沙盘模型" target="_blank ">沙盘模型uct usb_device_id *id_table; struct device_driver driver; }; bus和device之间是如何建立联系的?

看似很长一段,实际上也就是注释为主.而此刻我们只需留意到其中的struct device_driver driver这个成员,usb core为每一个设备驱动预备了一个函数,让它把自己的这个

struct device_driver driver插进到usb_bus_type中的drivers链表中往.而这个函数正是我们此前看到的usb_register.而与之对应的 usb_deregister所从事的正是与之相反的工作,把这个结构

体从drivers链表中删除.可以说,usb core的确是专心良苦,为每一个usb设备驱动做足了作业,正由于如此,作为一个实际的usb设备驱动,它在初始化阶段所要做的事情就很少,很简单了, 直接调用

usb_register即可.事实上,没有人是理所当然应该为你做什么的,但usb core这么做了.所以每一个写usb设备驱动的人应该铭记,usb device driver尽不是一个人在工作,在他身后,是usb core所提

供的默默无闻又不可或缺的支持。

device和driver之间是如何建立联系的呢?

由于有了热插拔,device可以在计算机启动以后在插进或者拔出计算机了.因此,很难再说是先有device还是先有driver了.由于都有可能.device可以在任何时刻出现,而driver也可以在任何时刻被加载,所以,出现的情况就是,每当一个struct device诞生,它就会往bus的drivers链表中寻找自己的另一半,反之,每当一个一个struct device_driver诞生,它就往bus的devices链表中寻找它的那些设备.假如找到了合适的,那么ok,调用 device_bind_driver绑定好.假如找不到,没有关系,等待吧。

还记得初始化的那几行代码吗?回到usb_register中来,看一下传给他的参数是什么?

我们留意到,那句调用是这样子的, /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); 是的,传递了一个叫做usb_storage_driver的家伙,这是什么?同一文件中,drivers/usb/storage/usb.c:

struct usb_driver usb_storage_driver = { .owner = THIS_MODULE, .name = "usb-storage", .probe = storage_probe, .disconnect = storage_disconnect, .id_table = storage_usb_ids, }; 可以看到这里定义了一个struct usb_driver的结构体变量,usb_storage_driver,关于usb_driver我们上节已经说过了,当时主要说的是其中的成员driver,而眼下要讲的则是另外几个成员.首先,.owner

和.name这两个没啥好多说的,owner这玩艺是用来给模块计数的,每个模块都这么用,赋值总是THIS_MODULE,而name就是这个模块的名字,usb core会处理它,所以假如这个模块正常被加载了的话,使用lsmod命令能看到一个叫做usb-storage的模块名。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
USB驱动分析(一)
关于设备模型、设备与驱动关联的过程分析 - linux设备/驱动
Linux 2.6内核的设备模型
Linux设备模型 - 键盘棒棒的日志 - 网易博客
设备模型(总线、设备、驱动程序和类)
Linux中总线、设备、驱动是如何关联的
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服