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 pieces */
        devices_init(); //  /sys/devices
        buses_init(); // /sys/bus
        classes_init(); // /sys/class
        firmware_init();
        hypervisor_init();

        /* These are also core pieces, but must come after the
         * core core pieces.
         */
        platform_bus_init();
        system_bus_init();
        cpu_dev_init();
        memory_dev_init();
}

且看platform_bus_init

drivers/base/platform.c
struct device platform_bus = {
        .bus_id         = "platform",
};
struct bus_type platform_bus_type = {
        .name           = "platform",
        .dev_attrs      = platform_dev_attrs,
        .match          = platform_match,
        .uevent         = platform_uevent,
        .pm             = PLATFORM_PM_OPS_PTR,
};

int __init platform_bus_init(void)
{
        int error;
     /* /sys/devices/platform (this platform is bus_id‘s value) */
     error = device_register(&platform_bus);     if (error)          return error; 
      /* /sys/bus/platform (this platform is the value of bus_type‘s name field) */
      error = bus_register(&platform_bus_type); 

     if (error)           device_unregister(&platform_bus); 

     return error; }

这里讲述 bus_register(&platform_bus_type):

/**
 * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
 *
 * @subsys - the struct kset that defines this bus.  This is the main kobject
 * @drivers_kset - the list of drivers associated with this bus
 * @devices_kset - the list of devices associated with this bus
 * @klist_devices - the klist to iterate over the @devices_kset
 * @klist_drivers - the klist to iterate over the @drivers_kset
 * @bus_notifier - the bus notifier list for anything that cares about things
 * on this bus.
 * @bus - pointer back to the struct bus_type that this structure is associated
 * with.
 *
 * This structure is the one that is the actual kobject allowing struct
 * bus_type to be statically allocated safely.  Nothing outside of the driver
 * core should ever touch these fields.
 */
struct bus_type_private {
        struct kset subsys;
        struct kset *drivers_kset;
        struct kset *devices_kset;
        struct klist klist_devices;
        struct klist klist_drivers;
        struct blocking_notifier_head bus_notifier;
        unsigned int drivers_autoprobe:1;
        struct bus_type *bus;
};
int bus_register(struct bus_type *bus)
{
        int retval;
        struct bus_type_private *priv;                                          

        priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;                                                 

        priv->bus = bus;
        bus->p = priv;                                                         

        BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);                       

        retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
        if (retval)
                goto out;                                                       

        priv->subsys.kobj.kset = bus_kset;
        priv->subsys.kobj.ktype = &bus_ktype;
        priv->drivers_autoprobe = 1;                                            

        retval = kset_register(&priv->subsys);
        if (retval)
                goto out;                                                       

        retval = bus_create_file(bus, &bus_attr_uevent);
        if (retval)
                goto bus_uevent_fail;                                           

        priv->devices_kset = kset_create_and_add("devices", NULL,
                                                 &priv->subsys.kobj);
        if (!priv->devices_kset) {
                retval = -ENOMEM;
                goto bus_devices_fail;
        }                                                                       

        priv->drivers_kset = kset_create_and_add("drivers", NULL,
                                                 &priv->subsys.kobj);
        if (!priv->drivers_kset) {
                retval = -ENOMEM;
                goto bus_drivers_fail;
        }                                                                       

        klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
        klist_init(&priv->klist_drivers, NULL, NULL);                           

        retval = add_probe_files(bus);
        if (retval)
                goto bus_probe_files_fail;                                      

        retval = bus_add_attrs(bus);
        if (retval)
                goto bus_attrs_fail;                                            

        pr_debug("bus: ‘%s‘: registered\n", bus->name);
        return 0;

struct bus_type_private *priv指向struct bus_type,这里会显示/sys/bus/platform

retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);

priv->subsys.kobj.kset = bus_kset;

retval = kset_register(&priv->subsys);// subsys is a kset.

这里显示/sys/bus/platform/devices

priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj);

这里显示/sys/bus/platform/drivers

priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);

kset_create_and_add--->kset_register

/**
 * kset_register - initialize and add a kset.
 * @k: kset.
 */
int kset_register(struct kset *k)
{
        int err;                                                                   

        if (!k)
                return -EINVAL;                                                    

        kset_init(k); // INIT_LIST_HEAD(&k->kobj->entry); INIT_LIST_HEAD(&k->list);
        err = kobject_add_internal(&k->kobj);
        if (err)
                return err;
        kobject_uevent(&k->kobj, KOBJ_ADD);
        return 0;
} 
static int kobject_add_internal(struct kobject *kobj)
{
    kobj_kset_join(kobj);
    error = create_dir(kobj); // /sys/bus/platform
}
/* add the kobject to its kset‘s list */
static void kobj_kset_join(struct kobject *kobj)
{
        if (!kobj->kset)
                return;                                                         

        kset_get(kobj->kset);
        spin_lock(&kobj->kset->list_lock);
        list_add_tail(&kobj->entry, &kobj->kset->list);
        spin_unlock(&kobj->kset->list_lock);
} 

If a kset is associated with a kobject, then the parent for the kobject can be set to
NULL in the call to kobject_add() and then the kobject‘s parent will be the kset itself.

struct kobject {
        const char              *name;
        struct list_head        entry;
        struct kobject          *parent;
        struct kset             *kset;
        struct kobj_type        *ktype;
        struct sysfs_dirent     *sd;
        struct kref             kref;
        unsigned int state_initialized:1;
        unsigned int state_in_sysfs:1;
        unsigned int state_add_uevent_sent:1;
        unsigned int state_remove_uevent_sent:1;
}; 
 *
 * A kset defines a group of kobjects.  They can be individually
 * different "types" but overall these kobjects all want to be grouped
 * together and operated on in the same manner.  ksets are used to
 * define the attribute callbacks and other common events that happen to
 * a kobject.
 *
 * @list: the list of all kobjects for this kset
 * @list_lock: a lock for iterating over the kobjects
 * @kobj: the embedded kobject for this kset (recursion, isn‘t it fun...)
 * @uevent_ops: the set of uevent operations for this kset.  These are
 * called whenever a kobject has something happen to it so that the kset
 * can add new environment variables, or filter out the uevents if so
 * desired.
 */
struct kset {
        struct list_head list;
        spinlock_t list_lock;
        struct kobject kobj;
        struct kset_uevent_ops *uevent_ops;
};
struct list_head {
        struct list_head *next, *prev;
}; 

从list_add_tail(&kobj->entry, &kobj->kset->list); 调用中,我们一下子就明白了,

bus =&struct bus_type platform_bus_type;bus->p->->subsys.kobj.kset = bus_kset;// bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); 创建了bus的kset显示/sys/bus所以&kobj->kset->list就是bus_kset->list,list_add_tail就是把bus->p->->subsys.kobj.entry加入到bus_kset->list链表中。bus_kset包含不同bus的subsys的kset,而代表subsys的kset的就是这个kset中的kobject。所以把kobjetct的entry加入到表示kset的kset->list中。换句话说,struct kset这个集合包含的内容由其嵌入的struct list_head list来表示,这个struct kset自身由其嵌入的struct kobject kobj来表示。所以这里就是把platform这个kset加入到bus这个kset中。用户空间的视图表示就是/sys/bus/platform。
 
时间: 2024-11-08 21:37:00

Linux驱动模型解析bus之platform bus的相关文章

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驱动模型中的底层数据结构kobject和kset

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

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设备驱动模型--分离分层思想

一.设备驱动的分层思想:以platform设备驱动.input设备驱动为例看看他们在分层思想上的体现 [1]在核心层:一类设备总线通用的功能特性,如果某一设备支持的总线比较特别可以不使用这些功能特性,在自己的设备总线结构体中 进行重载. 例(1)platform核心层:定义在drivers/base/platform.c文件 Linux内核对设备总线先进行了一次全局的抽象,即概括了所有设备驱动总线具有的功能特性: struct bus_type { //具备总线名.总线属性.总线上设备属性.总线

Linux驱动中的platform总线分析

copy from :https://blog.csdn.net/fml1997/article/details/77622860 概述 从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver .Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示:驱动用 platform_driver 进行注册. linux_platform_driver 机制和传统的device_driver机

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