内核版本:2.6.10
目标:理解设备模型和sysfs文件系统
1. 初探:
sysfs文件系统的作用:用于将系统中的设备组织成层次结构,并向用户态提供详细的内核数据结构信息。
挂载命令:mount -t sysfs sysfs /sys。
sysfs信息来源:kobject层次结构,也就是linux系统的设备模型。
2. linux设备底层模型
kobject:
每个在内核注册的kobject对象都对应于sysfs文件系统中的一个目录。
kobject是基类;bus, device, driver等是扩展类。
strut kobject {
char *k_name; // 指向设备名称的指针
char name[KOBJ_NAME_LEN]; // 设备名称
struct kref kref; // 对象引用计数;
struct list_head entry; // 从属于kset的所有kobject形成链表,该字段是链表节点;
struct kobject *parent; // 指向父结构;
struct kset *kset; // 所属kset;
struct kobj_type *ktype; // 指向其对象描述符的指针;
struct dentry *dentry; // sysfs文件系统中与该对象对应的文件节点路径的指针;
// 对象上锁;
};
相关函数:
void kobject_init(struct kobject *kobj);
int kobject_set_name(struct kobject *kobj, char *format, ...);
struct kobject *kobject_get(struct kobject *kobj); // 引用计数加一。
void kobject_put(struct kobject *kobj); // 引用计数减一,如果降为0,则释放kobj对象。
int kobject_add(struct kobject *kobj);
将kobj加入linux设备层次;
将kobj加入kset链表中;
在kobj的parent的目录下创建子目录,且各级父节点引用计数加一;
int kobject_del(struct kobject *kobj);
int kobject_register(struct kobject *kobj);
kobject_init();
kobject_add();
int kobject_unregister(struct kobject *kobj);
kobject_del();
kobject_put();
kobj_type:
struct kobj_type {
void (*release)(struct kobject *); // 释放kobj占用的资源。
struct sysfs_ops *sysfs_ops; // 提供show()和store()函数,用于用户态显示和设置kobj的指定属性。
struct attribute **default_attrs; //
};
struct attribute {
char *name; // 每个属性对应kobj目录下的一个文件;name就是文件名。sysfs_ops提供了对文件的读写方法。
struct module *owner;
mode_t mode;
};
kset:
作用:建立上层(sub-system)与下层(kobject)的关联性。管理kobject的集合。
struct kset {
struct subsystem *subsys;
struct kobj_type *ktype; // 从属于该kset的kobj的ktype均指向该字段;
struct list_list list; // 从属于该kset的所有kobj形成链表,该字段是链表头;
struct kobject kobj; // 从属于该kset的所有kobj的parent均指向该字段;
struct kset_hotplug_ops *hotplug_ops;
};
subsystem:
作用:管理kset的集合。描述系统中某一类子系统。
struct subsystem {
struct kset kset; // 就一个kset ?
struct rw_semaphore sw_sem;
};
3. 设备模型上层容器
bus:
struct bus_type {
char *name; // 总线类型的名称。每个bus_type类型的结构对应/sys/bus/下的一个子目录。
struct subsystem subsys;
struct kset drivers; // 所有与该总线相关的驱动程序;对应/sys/bus/pci/drivers/目录。
struct kset devices; // 所有连接在该总线上的设备;对应/sys/bus/pci/devices/目录。
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 (*hotplug)(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
int (*suspend)(struct device *dev, int state);
int (*resume)(struct device *dev);
};
device:
系统中的任一设备在设备模型中都由一个device对象描述。
struct device {
struct list_head g_list; // 全局设备链表。
struct list_head node; // 与兄弟对象构成链表。
struct list_head bus_list; // 同一总线上的设备形成的链表。
struct list_head driver_list; // 同一驱动管理的设备形成的链表。
struct list_head children; // 子设备链表的链表头。
struct device *parent; // 指向父设备。
struct kobject kobj;
char bus_id[BUS_ID_SIZE];
struct bus_type *bus;
struct device_driver *driver; // 驱动程序对象、
void *driver_data; // 提供给驱动的数据。
/* ... */
};
driver:
系统中的每个驱动程序由一个device_driver对象描述。
struct device_driver {
char *name; // 驱动程序的名称。
struct bus_type *bus; // 该驱动所管理的设备,挂接的总线类型。
struct kobject kobj;
struct list_head childrens; // 该驱动所管理的设备的链表头。
int (*probe)(struct device *dev); // 探测设备可否被该驱动管理。
int (*remove)(struct device *dev);
};