本文基于mstar801平台Linux2.6.35.11。
一、底层数据结构kset及kobject
kernel2.6.35.11/include/linux/kobject.h
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;
unsigned int uevent_suppress:1;
};
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
};
kernel2.6.35.11/lib/kobject.c
EXPORT_SYMBOL_GPL(kobject_get_path);
EXPORT_SYMBOL_GPL(kobject_init_and_add);
EXPORT_SYMBOL_GPL(kobject_rename);
EXPORT_SYMBOL_GPL(kobject_create_and_add);
EXPORT_SYMBOL_GPL(kset_create_and_add);
kobject:
kobject是Linux2.6引入的新的设备管理机制,通过这个数据结构使所有设备在底层都具有统一接口。
总线、设备和驱动就是通过kobject连接起来的;一般用于设备和驱动模型。
结合面向对象的思想,任何一个设备模型:总线、设备和驱动都属于一个kobject,这种派生关系就是在结构体中包含一个kobject的变量。
该结构体提供了所有模型需要的最基本的功能:引用计数,sysfs表示,热插拔事件处理。
内核用kobject结构将各个对象组成一个分层的结构体系,与模块化的子系统相匹配;有两个独立的机制用于连接:parent指针和kset域。
kset:
kset是管理kobject的集合;一般用于总线模型。
kobject通常通过kset组成成层次化的结构,kset是具有相同类型的kobject的集合;kset数据结构内嵌了一个kobject对象,所有属于kset的kobject对象的parent域都指向这个内嵌的对象。
二、基于底层数据结构kobject的设备模型:总线,设备,驱动
1.总线——bus_type:
kernel2.6.35.11/include/linux/device.h
struct bus_type {
const char *name; //总线名称
struct bus_attribute *bus_attrs; //总线属性
struct device_attribute *dev_attrs; //设备属性
struct driver_attribute *drv_attrs; //驱动属性
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
struct subsys_private *p; //总线类型私有数据
};
kernel2.6.35.11/drivers/base/base.h
struct subsys_private {
struct kset subsys; //与该总线相关的子系统
struct kset *devices_kset; //挂载在总线上的设备kset
struct kset *drivers_kset; //总线驱动程序的kset
struct klist klist_devices; //挂载在总线上的设备链表
struct klist klist_drivers; //驱动程序链表
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct list_head class_interfaces;
struct kset glue_dirs;
struct mutex class_mutex;
struct class *class;
};
说明:从上边结构体可以看出:一条总线拥有两条链表;一条是设备链表、一条是驱动链表。有了总线对应的数据结构,就可以获得总线关联了多少设备、以及有哪些驱动来支持这类设备。
后来注册的设备\驱动就是添加到kset中的。
kernel2.6.35.11/drivers/base/bus.c
EXPORT_SYMBOL_GPL(bus_register);
EXPORT_SYMBOL_GPL(bus_unregister);
EXPORT_SYMBOL_GPL(bus_register_notifier);
EXPORT_SYMBOL_GPL(bus_unregister_notifier);
EXPORT_SYMBOL_GPL(bus_get_kset);
EXPORT_SYMBOL_GPL(bus_get_device_klist);
EXPORT_SYMBOL_GPL(bus_create_file);
EXPORT_SYMBOL_GPL(bus_remove_file);
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_find_device);
EXPORT_SYMBOL_GPL(bus_find_device_by_name);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
EXPORT_SYMBOL_GPL(bus_rescan_devices);
EXPORT_SYMBOL_GPL(device_reprobe);
EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
2.设备——device:
kernel2.6.35.11/include/linux/device.h
struct device {
struct device *parent; //父设备
struct device_private *p; //设备结构的私有数据
struct kobject kobj; //kobject对象
const char *init_name; //设备初始化名字
const struct device_type *type; //设备方法
struct mutex mutex; //信号量
struct bus_type *bus; //设备所在总线
struct device_driver *driver; //该设备的驱动
void *platform_data; //平台总线私有数据
struct dev_pm_info power;
struct dev_power_domain *pwr_domain;
#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */
struct device_dma_parameters *dma_parms;
struct list_head dma_pools; /* dma pools (if dma'ble) */
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata archdata;
struct device_node *of_node; /* associated device tree node */
dev_t devt; /* dev_t, creates the sysfs "dev" */
spinlock_t devres_lock;
struct list_head devres_head;
struct klist_node knode_class;
struct class *class;
const struct attribute_group **groups; /* optional groups */
void (*release)(struct device *dev);
};
kernel2.6.35.11/drivers/base/base.h
struct device_private {
struct klist klist_children;
struct klist_node knode_parent;
struct klist_node knode_driver;
struct klist_node knode_bus;
void *driver_data; //我们关心的数据
struct device *device;
};
说明:利用结构中的kobject跟kset进行关联;在进行设备注册时,将设备添加到总线中去。
kernel2.6.35.11/drivers/base/core.c
EXPORT_SYMBOL_GPL(device_add);
EXPORT_SYMBOL_GPL(device_del);
EXPORT_SYMBOL_GPL(device_register);
EXPORT_SYMBOL_GPL(device_unregister);
EXPORT_SYMBOL_GPL(device_for_each_child);
EXPORT_SYMBOL_GPL(device_find_child);
EXPORT_SYMBOL_GPL(device_initialize);
EXPORT_SYMBOL_GPL(get_device);
EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
EXPORT_SYMBOL_GPL(__root_device_register);
EXPORT_SYMBOL_GPL(root_device_unregister);
EXPORT_SYMBOL_GPL(device_create_vargs);
EXPORT_SYMBOL_GPL(device_create);
EXPORT_SYMBOL_GPL(device_destroy);
EXPORT_SYMBOL_GPL(device_rename);
EXPORT_SYMBOL_GPL(device_move);
EXPORT_SYMBOL_GPL(device_create_bin_file);
EXPORT_SYMBOL_GPL(device_remove_bin_file);
EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
EXPORT_SYMBOL_GPL(dev_set_name);
3.驱动device_driver:
kernel2.6.35.11/include/linux/device.h
struct device_driver {
const char *name;
struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
const struct of_device_id *of_match_table;
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct dev_pm_ops *pm;
struct driver_private *p;
};
kernel2.6.35.11/drivers/base/base.h
struct driver_private {
struct kobject kobj;
struct klist klist_devices;
struct klist_node knode_bus;
struct module_kobject *mkobj;
struct device_driver *driver;
};
kernel2.6.35.11/drivers/base/driver.c
EXPORT_SYMBOL_GPL(driver_register);
EXPORT_SYMBOL_GPL(driver_unregister);
EXPORT_SYMBOL_GPL(driver_for_each_device);
EXPORT_SYMBOL_GPL(driver_find_device);
EXPORT_SYMBOL_GPL(driver_create_file);
EXPORT_SYMBOL_GPL(driver_remove_file);
EXPORT_SYMBOL_GPL(driver_add_kobj);
EXPORT_SYMBOL_GPL(get_driver);
EXPORT_SYMBOL_GPL(put_driver);
三、USB输入设备的总线、设备与驱动
1.USB总线,包含bus_type、间接包含kset
kernel2.6.35.11/include/linux/usb.h
extern struct bus_type usb_bus_type;
kernel2.6.35.11/drivers/usb/core/driver.c
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
};
2.设备,包含device、间接包含kobject
kernel2.6.35.11/include/linux/input.h
struct input_dev{
......
struct device dev;
......
}
3.驱动,包含device_driver、间接包含kobject
kernel2.6.35.11/include/linux/usb.h
struct usb_driver {
......
struct usbdrv_wrap drvwrap;
......
}
struct usbdrv_wrap {
struct device_driver driver;
int for_devices;
};