Linux设备驱动之设备模型(3)

分配给kobject的名字(用kobject_set_name)就是给 sysfs 目录使用的名字,因此在sysfs层级中相同部分的kobject命名必须唯一,不能包含下划线,避免使用空格。

这个入口所处的目录表示kobject的parent指针,如果parent为NULL,则指向的是它的kset,因此可以说sysfs的层级其实对应的就是kset的层级。但当kset也为NULL时,这个入口就会创建在sysfs的top level,不过实际中很少出现这种情况。

属性(atrributes)

属性即为上面所提到的一旦导出就会由内核自动生成的包含kobject内核信息的文件。结构如下:

struct attribute { char *name; /* 属性名,也是sysfs对应entry下的文件名 */ struct module *owner; /* 指向负责实现这个属性的模块 */ mode_t mode; /* 权限位,在<linux/stat.h>中定义 */ };

属性的导出显示及导入存储函数:

/* kobj: 需要处理的kobject attr: 需要处理的属性 buffer: 存储编码后的属性信息,大小为PAGE_SIZE return: 实际编码的属性信息长度 */ struct sysfs_ops { ssize_t (*show)(struct kobject *kobj, struct attribute *attr,char *buffer); /* 导出到用户空间 */ ssize_t (*store)(struct kobject *kobj, struct attribute *attr,const char *buffer, size_t size); /* 存储进内核空间 */ };

需要注意的是:

每个属性都是用name=value表示,name即使属性的文件名,value即文件内容,如果value超过PAGE_SIZE,则应分为多个属性来处理;

上述函数可以处理不同的属性。可以在内部实现时同过属性名进行区分来实现;

由于store是从用户空间到内核,所以实现时首先要检查参数的合法行,以免内核崩溃及其他问题。

缺省属性(Default Attributes)

在kobject创建时都会赋予一些缺省的默认属性,即上面所提到的kobj_type中的default_attrs数组,这个数组的最后一个成员须设置成NULL,以表示数组大小。所有使用这个kobj_type的kobject都是通过kobj_type中的sfsfs_ops回调函数入口实现对缺省属性的定义。

非缺省属性(Nondefault Attributes)

一般来说,定义时就可以通过default_attrs完成所有的属性,但这里也提供了后续动态添加和删除属性的方法:

int sysfs_create_file(struct kobject *kobj, struct attribute *attr); int sysfs_remove_file(struct kobject *kobj, struct attribute *attr); 二进制属性(Binary Attributes)

上述属性包含的可读的文本值,二进制属性很少使用,大多用在从用户空间传递一些不改动的文件如firmware给设备的情况下。

struct bin_attribute { struct attribute attr; /* 定义name,owner,mode */ size_t size; /* 属性最大长度,如没有最大长度则设为0 */ ssize_t (*read)(struct kobject *kobj, char *buffer,loff_t pos, size_t size); ssize_t (*write)(struct kobject *kobj, char *buffer,loff_t pos, size_t size); };

read/write一次加载多次调用,每次最多PAGE_SIZE大小。注意write无法指示最后一个写操作,得通过其他方式判断操作的结束。
二进制属性不能定义为缺省值,因此需明确的创建与删除:

int sysfs_create_bin_file(struct kobject *kobj,struct bin_attribute *attr); int sysfs_remove_bin_file(struct kobject *kobj,struct bin_attribute *attr); 符号连接(Symbolic Links)

方法:

int sysfs_create_link(struct kobject *kobj, struct kobject *target,char *name); void sysfs_remove_link(struct kobject *kobj, char *name); 热插拔事件生成(Hotplug Event Generation)

热插拔事件即当系统配置发生改变是内核向用户空间的通知。然后用户空间会调用/sbin/hotplug通过创建节点、加载驱动等动作进行响应。这个热插拔事件的产生是在kobject_add和kobject_del时。我们可以通过上面kset中定义的uevent_ops对热插拔事件产生进行配置:

struct kset_uevent_ops { /* 实现事件的过滤,其返回值为0时不产生事件 */ int (* const filter)(struct kset *kset, struct kobject *kobj); /* 生成传递给/sbin/hotplug的name参数 */ const char *(* const name)(struct kset *kset, struct kobject *kobj); /* 其他传递给/sbin/hotplug的参数通过这种设置环境变量的方式传递 */ int (* const uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env); }; 顶层容器 Buses, Devices, Drivers and Classes Buses

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/14652.html