文章目录
本文介绍linux中class_create和class_register的相关使用方法
1 class结构体介绍
内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
2 class相关API说明
如下表:
3 class_create()使用示例
示例一,通过class_create()、class_destroy()去注册和注销/sys/class/my_char_dev
代码如下
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
struct class *mem_class;
static int __init class_create_destroy_init(void)
{
// class_create动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加到内核中。创建的逻辑类位于/sys/class/。
// 参数:
// owner, 拥有者。一般赋值为THIS_MODULE。
// name, 创建的逻辑类的名称。
mem_class = class_create(THIS_MODULE, “my_char_dev”);
if (mem_class==NULL)
{
printk("<0> create class failed!\n");
return -1;
}
return 0;
}
static void __exit class_create_destroy_exit(void)
{
if (mem_class != NULL) {
class_destroy(mem_class);
mem_class = NULL;
}
}
module_init(class_create_destroy_init);
module_exit(class_create_destroy_exit);
MODULE_LICENSE(“GPL”);
4 class_register()使用示例
示例二,通过class_register()、class_unregister()去注册和注销/sys/class/my_char_dev
代码如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#define CLASS_NAME "my_char_dev"
struct class *mem_class;
static void class_create_release (struct class *cls)
{
printk("%s\n", __func__ );
kfree(cls);
}
static int __init class_create_destroy_init(void)
{
printk("%s\n", __func__);
int ret;
// 申请class结构体内存
mem_class = kzalloc(sizeof(*mem_class), GFP_KERNEL);
if (mem_class == NULL)
{
printk("create mem class failed!\n");
return -1;
}
printk("create mem class success\n");
mem_class->name = CLASS_NAME;
mem_class->owner = THIS_MODULE;
// 注销时class时的回调函数,在此回调函数中释放之前所分配的class结构体内存
mem_class->class_release = class_create_release;
// 将class注册到内核中,同时会在/sys/class/下创建class对应的节点
int retval = class_register(mem_class);
if (ret)
{
printk("class_register failed!\n");
kfree(mem_class);
return -1;
}
printk("class_register success\n");
return 0;
}
static void __exit class_create_destroy_exit(void)
{
printk("%s\n", __func__);
if (mem_class != NULL)
{
class_unregister(mem_class);
mem_class = NULL;
}
}
module_init(class_create_destroy_init);
module_exit(class_create_destroy_exit);
MODULE_LICENSE("GPL");
5 class_create()和class_register()对比
实际上,示例一和示例二是等价的。具体的可以通过查看class_create()和class_register()、class_destroy()和class_unregister()的源码去验证。
class_register()的代码如下:
// 将class注册到/sys/class/中
#define class_register(class) \
({ \
static struct lock_class_key __key; \
__class_register(class, &__key); \
})
class_register()是通过调用__class_register()来注册到sysfs中的。
__class_register()的代码如下:
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);
__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 defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
/* let the block class directory show up in the root of sysfs */
if (cls != &block_class)
cp->class_subsys.kobj.kset = class_kset;
#else
cp->class_subsys.kobj.kset = class_kset;
#endif
cp->class_subsys.kobj.ktype = &class_ktype;
cp->class = cls;
cls->p = cp;
// 将class注册到内核中
error = kset_register(&cp->class_subsys);
if (error) {
kfree(cp);
return error;
}
error = add_class_attrs(class_get(cls));
class_put(cls);
return error;
}
class_unregister()的代码如下:
void class_unregister(struct class *cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
remove_class_attrs(cls);
// 将class从内核中注销
kset_unregister(&cls->p->class_subsys);
}
下面,我们查看class_create()、class_destroy()的相关代码。
class_create()的代码如下:
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \
__class_create(owner, name, &__key); \
})
class_create()是通过调用__class_create()注册到内核中的。
__class_create()的代码如下:
struct class *__class_create(struct module *owner, const char *name, struct lock_class_key *key)
{
struct class *cls;
int retval;
// 分配class结构体
cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
cls->name = name;
cls->owner = owner;
// class对应的释放函数,在class从内核中注销时会执行该函数
cls->class_release = class_create_release;
// 通过调用__class_register()将class注册到内核中
retval = __class_register(cls, key);
if (retval)
goto error;
return cls;
error:
kfree(cls);
return ERR_PTR(retval);
}
class_create_release的代码如下:
static void class_create_release(struct class *cls)
{
pr_debug("%s called for %s\n", __func__, cls->name);
// 释放class结构体
kfree(cls);
}
实际上,__class_create()是通过调用__class_register()注册到sysfs中的!所以,本质上,class_create()和class_register()的作用是类似的。
class_destroy()的代码如下:
void class_destroy(struct class *cls)
{
if ((cls == NULL) || (IS_ERR(cls)))
return;
// 调用class_unregister()将class从内核中注销
class_unregister(cls);
}
实际上,class_destroy()是通过调用class_unregister()实现的。