分类: LINUX
2011-01-31 10:03:07
linux class device
谨以此文纪念过往的岁月。
1.class的创建
linux class顾名思义就是类,何所谓类呢?就是一组设备具有共同性而抽象出来的。这个概念在C++中很常见。linux中借用这个来管理一组类似的设备。
在linux中采用class_create来创建一个新类。
抓住主干来分析函数
struct class *__class_create(struct module *owner, const char *name,struct lock_class_key *key)
{
struct class *cls;
int retval;
cls = kzalloc(sizeof(*cls), GFP_KERNEL);
cls->name = name; --设置类名
cls->owner = owner; --设置所有者
cls->class_release = class_create_release; --设置释放函数
retval = __class_register(cls, key); --这个是负责class的注册。
return cls;
}
在linux中dev->kobj.kset指向其父的kset,dev->kobj.parent=&parent.kobj,同时会采用链表的办法实现设备兄弟之间的关系。
int __class_register(struct class *cls, struct lock_class_key *key)
{
struct class_private *cp;
int error;
pr_debug("device class '%s': registering\n", cls->name);
cp = kzalloc(sizeof(*cp), GFP_KERNEL);
if (!cp)
return -ENOMEM;
klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put);
INIT_LIST_HEAD(&cp->class_interfaces);
kset_init(&cp->class_dirs); --这个是创建该class的kset
__mutex_init(&cp->class_mutex, "struct class mutex", key);
error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
if (error) {
kfree(cp);
return error;
}
/* set the default /sys/dev directory for devices of this class */
if (!cls->dev_kobj)
cls->dev_kobj = sysfs_dev_char_kobj;
if (cls != &block_class)
cp->class_subsys.kobj.kset = class_kset; --设置该类的父kset为class_kset
cp->class_subsys.kobj.ktype = &class_ktype;
cp->class = cls;
cls->p = cp;
error = kset_register(&cp->class_subsys); --注册一个kset,因为他也算是一个父,其子设备的dev->kobj.kset会指向该kset
if (error) {
kfree(cp);
return error;
}
error = add_class_attrs(class_get(cls));
class_put(cls);
return error;
}
上面的函数很好理解。不过这个需要在理解kobject,kset以及ktype这几者之间的关系,very important!!!在创建一个类后,就可以创建隶属于
该类的设备。
2.device_create
函数原型为:
struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
参数class为class_create创建的一个新类。
device创建和上一次学习的device_register和有关联,因为在device_create中会有device_register的函数实现设备的注册。
struct device *device_create_vargs(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt,va_list args)
{
struct device *dev = NULL;
int retval = -ENODEV;
if (class == NULL || IS_ERR(class))
goto error;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
retval = -ENOMEM;
goto error;
}
dev->devt = devt;
dev->class = class; --设置class类 ,这个会关系到以后dev->kobj.parent的值。
dev->parent = parent; --设置parent
dev->release = device_create_release;
dev_set_drvdata(dev, drvdata);
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
retval = device_register(dev);
if (retval)
goto error;
return dev;
error:
put_device(dev);
return ERR_PTR(retval);
}