使用的linux版本是2.6.18
1、概念与重要的数据结构
SYSFS是一个虚拟的文件系统,这个文件系统的目录结构实质上就是内核对象模型树。
Kobject:内核对象,是模型树中的基本组成单位
53struct kobject { 54 const char * k_name; 55 char name[KOBJ_NAME_LEN]; 56 struct kref kref; 57 struct list_head entry; 58 struct kobject * parent; 59 struct kset * kset; 60 struct kobj_type * ktype; 61 struct dentry * dentry; 62 wait_queue_head_t poll; 63};kset:对象集合
127struct kset { 128 struct subsystem * subsys; 129 struct kobj_type * ktype; 130 struct list_head list; 131 spinlock_t list_lock; 132 struct kobject kobj; 133 struct kset_uevent_ops * uevent_ops; 134};ktype:描述kobject的属性,可通过对属性的操作来作一些信息的获取或更改
96 struct kobj_type { 97 void (*release)(struct kobject *); 98 struct sysfs_ops * sysfs_ops; 99 struct attribute ** default_attrs; 100};subsystem:子系统,实则上是一个kset,在高层次的概念
176struct subsystem { 177 struct kset kset; 178 struct rw_semaphore rwsem; 179};2、结构图
<参见LDD3的sysfs部分>关于kset与kobject之间的关系图。
从该图可以看出,结构的组成,主要就是kset和kobject来组成各种高层次的结构。
3、bus子系统基本结构
38struct bus_type { 39 const char * name; 40 41 struct subsystem subsys; 42 struct kset drivers; 43 struct kset devices; 44 struct klist klist_devices; 45 struct klist klist_drivers; 46 47 struct blocking_notifier_head bus_notifier; 48 49 struct bus_attribute * bus_attrs; 50 struct device_attribute * dev_attrs; 51 struct driver_attribute * drv_attrs; 52 53 int (*match)(struct device * dev, structdevice_driver * drv); 54 int (*uevent)(struct device *dev, char **envp, 55 int num_envp, char *buffer, intbuffer_size); 56 int (*probe)(struct device * dev); 57 int (*remove)(struct device * dev); 58 void (*shutdown)(struct device * dev); 59 60 int (*suspend)(struct device * dev, pm_message_t state); 61 int (*suspend_late)(struct device * dev, pm_message_t state); 62 int (*resume_early)(struct device * dev); 63 int (*resume)(struct device * dev); 64};bus_type内嵌了一个subsystem subsys,所以bus_type可以看作是一个类子系统,实则上就是一个子系统。
通过分析i2c总线的注册过程和对应在sysfs中的目录结构来看。
bus_type– i2c_bus_type
在/sys/目录下,看到目录实际上对应一个子系统。而我们要在这些子系统下新建一些子系统,对于i2c总线,我们要在bus子系统下挂接我们的i2c子系统。通过bus_register(&i2c_bus_type)来完成这一操作。具体的操作实际上就是插入一个kobject。
(1)对i2c的sub_sys的kobject设置名称,唯一的名称,这个名称会在/sys/bus/下看到。
kobject_set_name(i2c_bus_type.sub_sys.kset.kobject);(2)然后就是设置这个子系统的父结点,也就是设定这个子系统的父子系统。所有总线的父子系统都是 bus_subsys。 i2c_bus_type.sub_sys.kset.kobject.kset= bus_subsys.kset(3)最后将 i2c_bus_type子系统加入到 bus_subsys集合内的子系统链表中。 i2c_bus_type.sub_sys.kset.kobject.parent= bus_subsys.kset.kobject add_list_tail(i2c_bus_type.sub_sys.kset.kobject.entry, bus_subsys.kset.list)以上的操作,基本上把i2c_bus_type对应的子系统加入到bus_subsys下面了,在/sys/bus/下面可以看到i2c目录。
在bus_type中可以看到有两个kset,drivers和devices。这两个kset属于i2c子系统下的两个集合。所以将这两个kset挂接到i2c子系统下面。
(4)挂接devices到i2c子系统下面,完成后可在/sys/bus/i2c下看到devices目录
kobject_set_name(devices.kobject,“devices”); devices.subsys= &i2c_bus_type.sub_sys; devices.kobject.parent= i2c_bus_type.sub_sys.kset.kobject add_list_tail(devices.kobject,i2c_bus_type.sub_sys.kset.list);(5)同理,挂接drivers到i2c子系统下面,完成后可在/sys/bus/i2c下看到drivers目录
kobject_set_name(devices.kobject,“devices”); devices.subsys= &i2c_bus_type.sub_sys; devices.kobject.parent= i2c_bus_type.sub_sys.kset.kobject add_list_tail(devices.kobject,i2c_bus_type.sub_sys.kset.list); 4、 bus子系统的设备与驱动 394struct device { 395 struct klist klist_children; 396 struct klist_node knode_parent; /* node insibling list */ 397 struct klist_node knode_driver; 398 struct klist_node knode_bus; 399 struct device * parent; 400 401 struct kobject kobj; 402 char bus_id[BUS_ID_SIZE]; /* position on parent bus */ 403 struct device_type *type; 404 unsigned is_registered:1; 405 struct device_attribute uevent_attr; 406 struct device_attribute *devt_attr; 407 408 struct semaphore sem; /* semaphore to synchronizecalls to 409 * its driver. 410 */ 411 412 struct bus_type * bus; /* type of bus device is on*/ 413 struct device_driver *driver; /* which driver has allocatedthis 414 device */ 415 void *driver_data; /* data private to the driver*/ 416 void *platform_data; /* Platform specific data,device 417 core doesn't touch it */ 418 struct dev_pm_info power; 420#ifdef CONFIG_NUMA 421 int numa_node; /* NUMA node this device isclose to */ 422#endif 423 u64 *dma_mask; /* dma mask (if dma'abledevice) */ 424 u64 coherent_dma_mask;/* Like dma_mask, but for 425 alloc_coherent mappingsas 426 not all hardwaresupports 427 64 bit addresses forconsistent 428 allocations suchdescriptors. */ 429 430 struct list_head dma_pools; /* dma pools (ifdma'ble) */ 431 432 struct dma_coherent_mem *dma_mem; /* internal for coherentmem 433 override */ 434 /* arch specific additions */ 435 struct dev_archdata archdata; 436 437 spinlock_t devres_lock; 438 struct list_head devres_head; 439 440 /* class_device migration path */ 441 struct list_head node; 442 struct class *class; 443 dev_t devt; /* dev_t, creates thesysfs "dev" */ 444 struct attribute_group **groups; /* optional groups */ 445 int uevent_suppress; 446 447 void (*release)(struct device * dev); 448}; 120struct device_driver { 121 const char * name; 122 struct bus_type * bus; 123 124 struct completion unloaded; 125 struct kobject kobj; 126 struct klist klist_devices; 127 struct klist_node knode_bus; 128 129 struct module * owner; 130 const char * mod_name; /* used for built-inmodules */ 131 struct module_kobject * mkobj; 132 133 int (*probe) (struct device * dev); 134 int (*remove) (struct device * dev); 135 void (*shutdown) (struct device * dev); 136 int (*suspend) (struct device * dev, pm_message_tstate); 137 int (*resume) (struct device * dev); 138 139 unsigned int multithread_probe:1; 140};注册驱动程序:
driver_register(&i2c_adapter_driver); i2c_adapter_driver内嵌了一个 kobject,也就是说它将以一个 kobject的模型挂接在系统的模型树里,在 sysfs中,作为一个目录节点。 kobject_set_name(i2c_adapter_driver.kobject,i2c_adatpter_driver.name) i2c_adapter_driver.kobject.kset= i2c_adapter_driver.bus->sub_sys.kset add_list_tail(i2c_adapter_driver.kobject,i2c_adapter_driver.kobject.kset.klist)