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 *init_name; /* initial name of the device */

struct bus_type *bus; /* type of bus device is on */

struct device_driver *driver; /* which driver has allocated this

...

struct klist_node knode_class;

struct class *class;

const struct attribute_group **groups; /* optional groups */

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

...

}

看一下类图(类图被我整得错综复杂,还不知道怎么组织好,先截一小段)

2,device_register()方法

int device_register(struct device *dev)

{

device_initialize(dev);

return device_add(dev);

}

先分析device_initialize(dev);大体上知道它的功能:初始化device结构体,包括list/mutex/pm/...

->

dev->kobj.kset = devices_kset;

kobject_init(&dev->kobj, &device_ktype);//前面两句,是到/sys/目录下新建一个devices目录。

INIT_LIST_HEAD(&dev->dma_pools);

mutex_init(&dev->mutex);

lockdep_set_novalidate_class(&dev->mutex);

spin_lock_init(&dev->devres_lock);

INIT_LIST_HEAD(&dev->devres_head);

device_pm_init(dev);

set_dev_node(dev, -1);

再分析device_add(dev);大致功能是把初始化好的device回到系统的device层级中

device_private_init(dev);//如果private成员没初始化,在这里init。

|

dev_set_name(dev, "%s", dev->init_name);

->kobject_set_name_vargs(&dev->kobj, fmt, vargs);

//如果指定了device的init_name;通过kobject_set_name_vargs,实际是把init_name赋给了dev->kobject->name

|

if (!dev_name(dev) && dev->bus && dev->bus->dev_name)

dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);

//如果没指定init_name;那么就把其所在的bus->dev_name + dev->id组合成一个dev-kobject->name的名字

|

kobject_add(&dev->kobj, dev->kobj.parent, NULL);//回到kobject系统中,这样就管理他的uevent,kref等。已经指定了名字,为什么传一个NULL值呢?

|

device_create_file(dev, &uevent_attr);//创建uevent属性

|

device_create_file(dev, &devt_attr);//如果dev->devt已经实例化了,那么就建立相关dev节点。其中devt是MKDEV函数的返回值

|

device_add_class_symlinks(dev);//如果实例化了class,那么建立class的symlink

|

blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_ADD_DEVICE, dev);

kobject_uevent(&dev->kobj, KOBJ_ADD);//通过uevent机制,通知用户层,比如有设备插入,可以挂载了。

|

bus_probe_device(dev);//通知所在的bus,有设备加入了,并probe。

->

if (bus->p->drivers_autoprobe) {     //在device_init中已经把这个置1了。

ret = device_attach(dev);     //device_attch和driver_attch的分析见Linux
驱动模型初探2

}

3,kf_device的实现

code片断:

static void kf_device_release(struct device *dev){

printk("%s\n",__func__);

}

static struct device kf_device={

.init_name = "kf-device0",

.devt = MKDEV(KFMAJOR,1),

.release = kf_device_release,

};

static int kf_device_register(void){

int ret = -1;

//Do not point this class

//kf_device.class = &kf_class;

kf_device.bus = &kf_bus_type;

kf_device.parent = &kf_bus;

ret = device_register(&kf_device);

if(ret < 0){

printk("kf device reister error!\n");

}

printk("kf device reister ok!\n");

return ret;

}

static void kf_device_unregister(void){

device_unregister(&kf_device);

}

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

uevent:

1,device_register(struct device *dev)->device_add(dev)->device_create_file(dev, &uevent_attr);

2,如果指定了class,就会在class目录里面建相关目录,通过函数

device_add_class_symlinks(dev);

device_add_attrs(dev);

3,如果指定了相关bus,就会在/sys/bus/里面建相关节点

bus_add_device(dev);

power:

1,device_register(struct device *dev)->device_add(dev)->dpm_sysfs_add(dev);->ysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);

->pm_runtime_attr_group就是power目录,同时这个目录里面的几个文件

static struct attribute *runtime_attrs[] = {

#ifdef CONFIG_PM_RUNTIME

#ifndef CONFIG_PM_ADVANCED_DEBUG

&dev_attr_runtime_status.attr,

#endif

&dev_attr_control.attr,

&dev_attr_runtime_suspended_time.attr,

&dev_attr_runtime_active_time.attr,

&dev_attr_autosuspend_delay_ms.attr,

#endif /* CONFIG_PM_RUNTIME */

NULL,

};

2,struct device中device_driver成员,而struct device_driver中没有device成员,

也可以说明device(美女)很专一,她只能有指定的驱动。

而device_driver(帅哥)很花心,他很有很多device,所以他不能指定某个设备在他的成员中。

时间: 2024-08-03 22:38:17

Linux 驱动模型初探3——device的相关文章

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 驱动模型初探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);

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

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

linux驱动之i2c子系统device注册driver注册简单分析

Linux 驱动设计主要是根据分层分离思想,i2c子系统分为i2cocre.adapter.及device_driver层,其实adapter也是个device,只不过是我们主控芯片的I2C控制接口而已,我们的主控芯片有几个I2C接口就有几个adapter; i2ccore这一层linux已经帮我们实现,主要的工做是类似platform总线的作用,负责drvier及设备的注册,相比platform多了个adapter的注册管理工作,以及i2c的数据发送接收等等算法,说算法有点夸大,其实就是按照i

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)

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

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.如果操作系统要进入休眠状态,首先要逐层通知所有的外设进入休眠模式,