linux中class_create和class_register分析

原文地址:http://www.cnblogs.com/skywang12345/archive/2013/05/15/driver_class.html

本文介绍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");


附录一,class_create()和class_register()对比

实际上,示例一和示例二是等价的。具体的可以通过查看class_create()和class_register()、class_destroy()和class_unregister()的源码去验证。

class_register()的代码如下:

1 // 将class注册到/sys/class/中
2 #define class_register(class)           \ 
3 ({                      \ 
4     static struct lock_class_key __key; \ 
5     __class_register(class, &__key);    \ 
6 })


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()的代码如下:

1 #define class_create(owner, name)       \ 
2 ({                      \ 
3     static struct lock_class_key __key; \ 
4     __class_create(owner, name, &__key);    \ 
5 })

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的代码如下:

1 static void class_create_release(struct class *cls) 
2 { 
3     pr_debug("%s called for %s\n", __func__, cls->name); 
4     // 释放class结构体
5     kfree(cls); 
6 }

 

实际上,__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()实现的。




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值