Linux的sysfs与驱动模型体会1

使用的linux版本是2.6.18

1、概念与重要的数据结构

SYSFS是一个虚拟的文件系统,这个文件系统的目录结构实质上就是内核对象模型树。

Kobject:内核对象,是模型树中的基本组成单位


53 struct 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:对象集合

127 struct 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,在高层次的概念

176 struct subsystem {

177 struct kset kset;

178 struct rw_semaphore rwsem;

179 };

2、结构图

<参见LDD3的sysfs部分> 关于kset与kobject之间的关系图。

从该图可以看出,结构的组成,主要就是kset和kobject来组成各种高层次的结构。

3、bus子系统基本结构

38 struct 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, struct device_driver * drv);

54 int (*uevent)(struct device *dev, char **envp,

55 int num_envp, char *buffer, int buffer_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子系统的设备与驱动

394 struct device {

395 struct klist klist_children;

396 struct klist_node knode_parent; /* node in sibling 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 synchronize calls 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 allocated this

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 is close to */

422 #endif

423 u64 *dma_mask; /* dma mask (if dma'able device) */

424 u64 coherent_dma_mask;/* Like dma_mask, but for

425 alloc_coherent mappings as

426 not all hardware supports

427 64 bit addresses for consistent

428 allocations such descriptors. */

429

430 struct list_head dma_pools; /* dma pools (if dma'ble) */

431

432 struct dma_coherent_mem *dma_mem; /* internal for coherent mem

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 the sysfs "dev" */

444 struct attribute_group **groups; /* optional groups */

445 int uevent_suppress;

446

447 void (*release)(struct device * dev);

448 };

120 struct 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-in modules */

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_t state);

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)