相对于前面分析的总线,设备,驱动模型来说 ,linux class模型就相对比较简单了.我们这里先分析class的注册过程, 然后举一个利用class动态创建字符设备的实例.
在 linux /sys目录下有一个class目录,在这个目录下存放着所有注册在内核中的class设备.
class初始化
还是先来看看/sys/class目录是如何建立起来的:
382 int __init classes_init(void)
383 {
384 class_kset = kset_create_and_add("class", NULL, NULL);
385 if (!class_kset)
386 return -ENOMEM;
387 return 0;
388 }
注册一个class_ket ,class这个目录在/sys下就创建起来了~~~~~~.
class创建并注册
老规矩先还是理理流程:
class_create()->class_register()->kset_register()
从这里的流程也可以看出class的注册是很简单的,它其实就是注册了一个ket
跟踪一下class_register()的代码:
137 int class_register(struct class *cls)
138 {
139 int error;
140
141 pr_debug("device class '%s': registering\n", cls->name);
142
143 INIT_LIST_HEAD(&cls->devices);
144 INIT_LIST_HEAD(&cls->interfaces);
145 kset_init(&cls->class_dirs);
146 init_MUTEX(&cls->sem);
147 error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
148 if (error)
149 return error;
150
151 #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
152 /* let the block class directory show up in the root of sysfs */
153 if (cls != &block_class)
154 cls->subsys.kobj.kset = class_kset;
155 #else
156 cls->subsys.kobj.kset = class_kset;
157 #endif
158 cls->subsys.kobj.ktype = &class_ktype;
159
160 error = kset_register(&cls->subsys);
161 if (!error) {
162 error = add_class_attrs(class_get(cls));
163 class_put(cls);
164 }
165 return error;
166 }
第151-158行, 定义cls->subsys.kobj 的ket和ktype, cls->subsys.kobj.kset = class_kset; cls->subsys.kobj.ktype = &class_ktype; class_kset是初始化class创建的, class_ktype定义了class属性文件的操作方法.
第160行,注册一个kset ,会在/clsaa目录下创建相应的目录 .因为cls->subsys.kobj.kset = class_kset .
创建class属性文件
那么class层的属性文件是如何创建的呢?看看这个函数就很清楚了:
77 int class_create_file(struct class *cls, const struct class_attribute *attr)
78 {
79 int error;
80 if (cls)
81 error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
82 else
83 error = -EINVAL;
84 return error;
85 }
sysfs_create_file() 这个函数就不多解释了, 以前文章已经分析过了.
读写class属性文件
还是老办法 ,要找到读写class属性文件的方法,首先要找到该文件父目录kobj关联的ktype , 从上面注册class的代码中可以看出, cls->subsys.kobj.ktype = &class_ktype; 每个kobj都指定了class_ktype .好了,找到了ktype我们就可以看它读写文件的实现了.
static struct kobj_type class_ktype = {
.sysfs_ops = &class_sysfs_ops,
.release = class_release,
};
static struct sysfs_ops class_sysfs_ops = {
.show = class_attr_show,
.store = class_attr_store,
};
static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct class_attribute *class_attr = to_class_attr(attr);
struct class *dc = to_class(kobj);
ssize_t ret = -EIO;
if (class_attr->show)
ret = class_attr->show(dc, buf);
return ret;
}
以class文件读方法来分析, 首先是找到class_attr,然后调用它定义的show()方法.