Linux 驱动模型初探2——device_driver

1,思考

device_driver也是一个kobject?,但你注意没有,在sys/目录下有bus/,有device/就是没有device_driver/,Y?为什么这么设计?

先看struct devic_driver;

struct device_driver {

const char *name;

struct bus_type *bus;

...

int (*probe) (struct device *dev);

int (*remove) (struct device *dev);

void (*shutdown) (struct device *dev);

int (*suspend) (struct device *dev, pm_message_t state);

int (*resume) (struct device *dev);

...

const struct dev_pm_ops *pm;

struct driver_private *p;

};

虽然 device_driver中没有kobject,但他的driver_private成员中有kobject,

struct driver_private {

struct kobject kobj;

...

};

但如何证明,他使用这个private数据的kobj来与其它kojb来交互呢,看driver_register()中,bus_add_driver(struct device_driver *drv)是通过kobject/kset与bus来进行“连接”的。

kobject_init_and_add(&priv->kobj,
&driver_ktype, NULL, "%s", drv->name);kobject的add也是通过priv->kobj。建议把bus_add_driver记住,后续还有使用。

好,第一个问题回答了,那么第二个问题?其实跟第一个的回答一样,在bus_add_driver的函数中。先看一下调用关系:

int driver_register(struct device_driver *drv)

->

bus_add_driver(struct device_driver *drv)

->

priv->kobj.kset = bus->p->drivers_kset;

kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,"%s", drv->name);

->

kobject_add_varg(kobj, parent, fmt, args);

->

kobject_add_internal(kobj);

->

/* join kset if set, use it as parent if we do not already have one */

if (kobj->kset) {

if (!parent)

parent = kobject_get(&kobj->kset->kobj);

kobj_kset_join(kobj);

kobj->parent = parent;

}

答案应这段code。因为kobj->kset已经赋值,所以此时的kobj->parent就是bus->p->drivers_kset。所以,新加的driver都会在bus中的driver文件件中,而不是/sys/下的一个drivers文件夹。

第三个问题,为什么这样设计?

暂时没想通,架构层面的东西,可以上升到了哲学观了。我期待有哲人指点,或者周公托梦。

2,driver_register(struct device_driver *drv)走读

读register函数之前,先看一上struct device_driver的类图(只列出关键成员)

再看一下,driver_register(),我把几个关键的函数Highlight出来

int driver_register(struct device_driver *drv)

{

int ret;

struct device_driver *other;

BUG_ON(!drv->bus->p);

if ((drv->bus->probe && drv->probe) ||

(drv->bus->remove && drv->remove) ||

(drv->bus->shutdown && drv->shutdown))

printk(KERN_WARNING "Driver ‘%s‘ needs updating - please use "

"bus_type methods\n", drv->name);

other = driver_find(drv->name, drv->bus);

if (other) {

printk(KERN_ERR "Error: Driver ‘%s‘ is already registered, "

"aborting...\n", drv->name);

return -EBUSY;

}

ret = bus_add_driver(drv);

if (ret)

return ret;

ret = driver_add_groups(drv, drv->groups);

if (ret) {

bus_remove_driver(drv);

return ret;

}

kobject_uevent(&drv->p->kobj, KOBJ_ADD);

return ret;

}

该函数的核心函数是bus_add_driver,在前面基本上已经分析了,他就是在指定bus(busy_type类型)的drivers文件夹中添加自己,内部的逻辑就是添加到bus->p->klist_drivers的链表中。

顺便讲一下,开关的if判断

if ((drv->bus->probe && drv->probe) ||

(drv->bus->remove && drv->remove) ||

(drv->bus->shutdown && drv->shutdown))

如果drv和drv->bus都实现了probe/remove/shutdown方法,就会有个警告打印。看上面的类图也可以看到有两个Probe,从Warning的信息来看,如果bus实现了probe函数,就使用bus的。但我们知道,bus上可以挂很多driver,实操中应该是不实现bus的probe,而且是留给相应的driver去实现。那么两个probe有啥关系?看一张关系图(来处网友tynew)

如果都实现了,会打印这种错误

再看driver_add_groups函数,是把driver结构体中**groups添加到sys文件系统中(看上面类图)

再看kobject_uevent(&drv->p->kobj, KOBJ_ADD);函数是处理KOBJ_ADD的事件,里面会调用call_usermodehelper(argv[0],
argv, env->envp, UMH_WAIT_EXEC);启动一个用户程序。这就是uevent的功能

3,kf_driver的实现

code:(完整版见github项目)

static int kf_device_driver_probe(struct device *dev){

printk("enter drive probe\n");

return 0;

}

static struct device_driver kf_device_driver={

.name = "kf-device-driver",

.probe = kf_device_driver_probe,

};

static int kf_device_dirver_register(void){

int ret = -1;

kf_device_driver.bus = &kf_bus_type;//指定挂在哪条bus(bus_type)上

ret = driver_register(&kf_device_driver);

printk("kf_device_driver reister ok!\n");

return ret;

}

static void kf_device_dirver_unregister(void){

driver_unregister(&kf_device_driver);

}

编译成ko,在平台上,insod上去,我们来看看sys文件系统。

在/sys/bus/kf-bus/driver中增加了一些文件

kf-device-driver就是我们新加的dirver的name

driver_register()->bus_add_driver()->kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name);

->...->kobject_add_internal(kobj);生成kf-device-dirver

那bind uevent unbind呢?

uevent:

driver_register()->bus_add_driver()->driver_create_file(drv, &driver_attr_uevent);

bind,unbind

driver_register()->bus_add_driver()->add_bind_files(drv);

->driver_create_file(drv, &driver_attr_unbind);   driver_create_file(drv, &driver_attr_bind);

//uevent,以及内核通知链(blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

BUS_NOTIFY_BOUND_DRIVER, dev);)需要新开一篇讲

driver还有一个很重要的函数__driver_attach。他跟bus的__device_attach殊途同归,看它们是怎么走在一起的?看上面的关系图。

时间: 2024-10-20 08:48:34

Linux 驱动模型初探2——device_driver的相关文章

Linux 驱动模型初探3——device

讲device之前,我要引入一个比喻,这个比喻来自一个学长(z2007b).driver是帅哥,device是美女,bus是红娘,bus是提供device和driver配对的场所(方法?).好吧,暂时先这样定,现在要讲的就是美女. 1,老规则,先看看struce device这个美女有哪些特性(成员)和方法 struct device { struct device *parent; struct device_private*p; struct kobject kobj; const char

Linux 驱动模型初探1——BUS

##写在前面的话## 这几篇文章是2011年,当时的老大对我提出的一个"作业".当时研究了一把,完成了第一篇BUS,老大看过之后,表示满意,要我把后面继续完成.然,世事变迁,老大离开了公司,去了其它公司.之后,我也从S公司离开了.所做的工作也有小范围的调整.近期又回到驱动这块,再看到之前的笔记,感慨万千,我决计是要完成搁浅了近3年"作业". 测试代码我已经提交到github上:https://github.com/koffuxu/kornel/tree/dev/dr

Linux 驱动模型初探4——汇总和拾遗

1,直接上code #include <linux/device.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/stat.h> #include <linux/slab.h> #include <linux/kobject.h> #include <linux/kdev_t.

浅析Linux驱动模型中的底层数据结构kobject和kset

1.kobject Linux内核用kobject来表示一个内核对象.它和Sysfs文件系统联系密切,在内核中注册到系统中的每个kobject对象在sysfs文件系统中对对应着一个文件目录.kobject数据结构通常的用法是嵌入到其对他的数据结构中(即容器,比如cdev结构),用于实现内核对该类数据结构对象的管理.这些数据结构(容器)通过kobject连接起来,形成了一个树状结构. 它在源码中的定义为: /*<include/linux/kobject.h>*/ struct kobject

Linux驱动模型解析bus之platform bus

这是内核启动之后要调用的驱动模型的开始代码: drivers/base/init.c/** * driver_init - initialize driver model. * * Call the driver model init functions to initialize their * subsystems. Called early from init/main.c. */ void __init driver_init(void) { /* These are the core

linux内核驱动模型

linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构成内核对象集,用kset表示,内核对象集也包含自己的内核对象,从而组成层次化的结构.2.用sysfs文件系统导出到用户空间.内核中的所有内核对象组织成树状,以对象属性为叶子.通过sysfs文件系统,将用户空间对文件的读写操作转化为对内核对象属性的显示和保存方法.从而导出内核对象信息,并提供配置接口.

Linux 设备模型基本概念

1.设备模型引入 Linux 2.6内核最初为了应付电源管理的需要,提出了一个设备模型来管理所有的设备.在物理上,外设之间是有一种层次关系的,比如把一个U盘插到笔记本上,实际上这个U盘是接在一个USB Hub上,USB Hub又是接在USB 2.0 Host Controller (EHCI)上,最终EHCI又是一个挂在PCI Bus上的设备.这里的一个层次关系是:PCI->EHCI->USB Hub->USB Disk.如果操作系统要进入休眠状态,首先要逐层通知所有的外设进入休眠模式,

转 Linux设备模型 (1)

作者:wwang 出处:http://www.cnblogs.com/wwang 本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接. 随着计算机的周边外设越来越丰富,设备管理已经成为现代操作系统的一项重要任务,这对于Linux来说也是同样的情况.每次Linux内核新版本的发布,都会伴随着一批设备驱动进入内核.在Linux内核里,驱动程序的代码量占有了相当大的比重.下图是我在网络上搜索到的

【linux设备模型】之platform设备驱动

一.platform总线.设备和驱动 platform是一种虚拟总线,对应的设备称为platform_device,对应的驱动称为platform_driver. platform_device定义在<linux/platform_device.h>中: 1 struct platform_device { 2 const char * name; 3 int id; 4 struct device dev; 5 u32 num_resources; 6 struct resource * r