总线-设备-驱动
/***************如图********************* /------------------------> 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); } }