总线-设备-驱动
/***************如图*********************
/------------------------> bus_type <-------------------------\
| +--------------------+ |
| | | |
| | name | |
| +--------------------+ |
| | kset | |
| | +--------+ | |
| | | subsys | | |
| | drivers +--------+ | |
| | | kobj | | |
| | +--------+ | |
| | | list | | |
| | +--------+ | |
| | | | | |
| +--------------------+ |
| | kset | |
| | +--------+ | |
| | | subsys | | |
| | devices +--------+ | |
| | | kobj | | |
| | +--------+ | |
| /------------------------------->| list |<----------------------\ |
| | | +--------+ | | |
| | | | | | | |
| | +--------------------+ | |
| | | | | |
| | | subsys | | |
| | | | | |
| | +--------------------+ | |
| | | | | |
| | | | | |
| | | | | |
| | | |
| | | |
| | device device | |
| | +-------------+ +-------------+ | |
| | | node | | node | | |
| | +-------------+ +-------------+ | |
| \-->| bus_list |<------- ...... ---------->| bus_list |<--/ |
| +-------------+ +-------------+ |
| | driver_list| | driver_list| |
| +-------------+ +-------------+ |
| | children | | children | |
| +-------------+ +-------------+ |
| | parent | | parent | |
| +-------------+ +-------------+ |
| | kobj | | kobj | |
| +-------------+ +-------------+ |
\------| bus | | bus |--------/
+-------------+ +-------------+
| driver | | driver |
+-------------+ +-------------+
| | | |
*****************************************/
总线
最关键的如图三部分 (1) 名称 (2) 驱动集合 (3) 设备集合
(一) 查看总线ls -l /sys/bus/ 命令可以看到当前系统加载的总线。
(二) 内核总线数据结构
//linux-2.6.32.21/include/linux/device.h
struct bus_type {
const char *name;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
//...
struct bus_type_private *p;
};
//linux-2.6.32.21/drivers/base/base.h
struct bus_type_private {
struct kset subsys;
struct kset *drivers_kset;
struct kset *devices_kset;
struct klist klist_devices;
struct klist klist_drivers;
//...
};
设备
设备是需要注册在总线上的。而kernel中提供了两种设备注册函数 1) device_register() 2) platform_device_register() 关于这两个注册方法的区别。我们先看代码
/*** linux-2.6.32.21/drivers/base/platform.c ***/
int platform_device_add(struct platform_device *pdev)
{
if (!pdev->dev.parent)
pdev->dev.parent = &platform_bus;
//...
ret = device_add(&pdev->dev);
}
platform_device_register(struct platform_device *pdev)
{
return platform_device_add(pdev);
}
/***linux-2.6.32.21/drivers/base/core.c ***/
int device_register(struct device *dev)
{
return device_add(dev);
}
OK,我们可以看出, platform_device_register相当于对device_register
多加了一层封装,主要将设备的父节点设为platform总线。
设备最终还是要挂在各自的总线下面。就是下面的部分
/***linux-2.6.32.21/drivers/base/core.c ***/
int device_add(struct device *dev)
{
//...
error = bus_add_device(dev);
}
/***linux-2.6.32.21/drivers/base/bus.c ***/
int bus_add_device(struct device *dev)
{
struct bus_type *bus = bus_get(dev->bus);
if (bus) {
/* 这!把设备加入总线的klist_devices列表 */
klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
}
}