这是内核启动之后要调用的驱动模型的开始代码:

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:;
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 = ; 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 ;

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 ;
}
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.

确切的说是kobject's parent赋值为kobject关联的kset's kobjcect

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:;
unsigned int state_in_sysfs:;
unsigned int state_add_uevent_sent:;
unsigned int state_remove_uevent_sent:;
};
 *
* 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。
 

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

  1. linux驱动模型——platform(1)

    一.驱动模型包含什么? 1.1. 类class 1.1.2. 它能够自动创建/dev下的设备节点,不需要mknod /dev/xxx c x x创建.当然class还有其另外的作用,且自动创建设备节点 ...

  2. linux驱动模型<输入子系统>

    在linux中提供一种输入子系统的驱动模型,其主要是实现在input.c中. 在输入子系统这套模型中,他把驱动分层分类.首先分为上下两层,上层为input.c .下层为驱动的实现,下层分为两部分,一部 ...

  3. linux驱动模型——platform(2)

    一. platform 组织架构 1.1. platform工作体系都定义在drivers/base/platform.c中 1.2. platform相关函数声明在include/linux/pla ...

  4. Linux设备驱动模型之platform(平台)总线详解

    /********************************************************/ 内核版本:2.6.35.7 运行平台:三星s5pv210 /*********** ...

  5. Linux驱动中的platform总线分析

    copy from :https://blog.csdn.net/fml1997/article/details/77622860 概述 从Linux2.6内核起,引入一套新的驱动管理和注册机制:pl ...

  6. linux内核驱动模型

    linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构 ...

  7. linux设备模型_转

    建议原博文查看,效果更佳. 转自:http://www.cnblogs.com/wwang/category/269350.html Linux设备模型 (1) 随着计算机的周边外设越来越丰富,设备管 ...

  8. Linux设备模型 (1)

    随着计算机的周边外设越来越丰富,设备管理已经成为现代操作系统的一项重要任务,这对于Linux来说也是同样的情况.每次Linux内核新版本的发布,都会伴随着一批设备驱动进入内核.在Linux内核里,驱动 ...

  9. Linux Platform驱动模型(一)-设备信息

    我在Linux字符设备驱动框架一文中简单介绍了Linux字符设备编程模型,在那个模型中,只要应用程序open()了相应的设备文件,就可以使用ioctl通过驱动程序来控制我们的硬件,这种模型直观,但是从 ...

随机推荐

  1. Akka(26): Stream:异常处理-Exception handling

    akka-stream是基于Actor模式的,所以也继承了Actor模式的“坚韧性(resilient)”特点,在任何异常情况下都有某种整体统一的异常处理策略和具体实施方式.在akka-stream的 ...

  2. JavaScript 基本语法结构

    1 变量 JavaScript的变量是弱类型的,就是所有的对象都是使用var 来进行声明 2 变量的命名规则 1.由字母.数字.下划线组成,区分大小写 2.以字母开头 3.变量名不能有空格 4.不能使 ...

  3. 深入理解计算机系统chapter6

    1. 2. 3. 存储器山

  4. 转载 iOS拦截导航栏返回按钮事件的正确方式

    原文链接:http://www.jianshu.com/p/25fd027916fa 当我们使用了系统的导航栏时,默认点击返回按钮是 pop 回上一个界面.但是在有时候,我们需要在点击导航栏的返回按钮 ...

  5. 使用Xshell+Xmanager远程监控jvisualvm

    使用jvisualvm的remote方式监控服务器端jvisualvm时,不是很方便,因此通过local方式,应该是正路. 一.服务器端(Linux,最小安装模式,没有图形界面) 1.安装xauth ...

  6. 【模版】AC自动机(简单版)

    题目背景 这是一道简单的AC自动机模版题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交. 题目描述 给定n个模式串和1个文本串,求有多少个模式串在文本 ...

  7. GBDT(MART)概念简介

    GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Regression Tree),是一种用于回归的机器学习算法,该算法由 ...

  8. 混合高斯模型(Mixtures of Gaussians)和EM算法

    这篇讨论使用期望最大化算法(Expectation-Maximization)来进行密度估计(density estimation). 与k-means一样,给定的训练样本是,我们将隐含类别标签用表示 ...

  9. 通过修改 LayoutInflater,全局替换字体!!!

    序 在 Android 下使用自定义字体已经是一个比较常见的需求了,最近也做了个比较深入的研究. 那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,但是写下来发现内容还挺多的,所以我 ...

  10. wxPython中菜单、按钮学习

    ---恢复内容开始--- wx.Window 是一个基类,许多构件从它继承.包括 wx.Frame 构件.技术上这意味着,我们可以在所有的 子类中使用 wx.Window 的方法.我们这里介绍它的几种 ...