device_create()、device_register()、deivce_add()区别

来源:互联网 发布:谭浩强c语言 编辑:程序博客网 时间:2024/06/14 07:00

本文基于linux 3.10.40,其他版本仅供参考

在字符设备驱动开发的入门教程中,最常见的就是用device_create()函数来创建设备节点了,但是在之后阅读内核源码的过程中却很少见device_create()的踪影了,取而代之的是device_register()与device_add(),将device_create()函数展开不难发现:其实device_create()只是device_register()的封装,而device_register()则是device_add()的封装。

struct device *device_create(struct class *class, struct device *parent,                 dev_t devt, void *drvdata, const char *fmt, ...){    ......    dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);    ......    return dev;}
struct device *device_create_vargs(struct class *class, struct device *parent,                   dev_t devt, void *drvdata, const char *fmt,                   va_list args){    ......    dev->devt = devt;    dev->class = class;    dev->parent = parent;    dev->release = device_create_release;    dev_set_drvdata(dev, drvdata);    ......    retval = device_register(dev);    ......}
int device_register(struct device *dev){    device_initialize(dev);    return device_add(dev);}

device_add()会在/sys目录对应设备目录下创建uevent属性节点,应用层的udev则会根据uevent来创建/dev目录下的设备节点,这里关于udev的部分不再赘述,我们继续分析device_create()、device_register()、device_add()三个函数在实际运用中的区别。

以一个简单的led设备字符设备驱动为例,下面分别用device_create()、device_register()、device_add()三个函数来创建设备节点“/dev/led”:

1. device_create()

static class *led_class;static int __init led_init(void){    int ret;    dev_t devno;    struct cdev *cdev;    struct dev *dev;    /* 注册设备号 */    ret = alloc_chrdev_region(&devno, 0, 1, "led");    if (ret < 0)         return ret;    /* 分配、初始化、注册cdev*/    cdev = cdev_alloc();    if (IS_ERR(cdev)) {        ret = PTR_ERR(cdev);        goto out_unregister_devno;    }    cdev_init(&cdev, &led_fops);    cdev.owner = THIS_MODULE;    ret = cdev_add(&cdev, devno, 1);        if (ret)         goto out_free_cdev;    /* 创建设备类 */    led_class = class_create(THIS_MODULE, "led_class");    if (IS_ERR(led_class)) {        ret = PTR_ERR(led_class);        goto out_unregister_cdev;    }     /* 创建设备节点 */    dev = device_create(led_class, NULL, devno, NULL, "led");    if (IS_ERR(dev)) {        ret = PTR_ERR(dev);        goto out_del_class;    }    return 0;out_del_class:    class_destroy(c78x_class); out_unregister_cdev:    cdev_del(cdev);out_free_cdev:    kfree(cdev);out_unregister_devno:    unregister_chrdev_region(devno, 1);    return ret;}module_init(led_init);

2. device_register()

static class *led_class;static int __init led_init(void){    ......     /* 注册设备号 */    ......    /* 分配、初始化、注册cdev*/    ......    /* 创建设备类 */    ......    /* 创建设备节点 */    dev = kzalloc(sizeof(*dev), GFP_KERNEL);    if (!dev) {        ret = -ENOMEM;        goto out_del_class;    }    dev->class = led_class;         // 关联设备类    dev->parent = NULL;                 dev->devt = devno;              // 关联设备号    dev_set_drvdata(dev, NULL);         dev_set_name(dev, "led");       // 设置节点名字    dev->release = device_create_release;    ret = device_register(dev);    if (ret)         goto out_put_dev;    return 0;out_put_dev:    put_device(dev);    kree(dev);out_del_class:    class_destroy(c78x_class);    out_unregister_cdev:        cdev_del(cdev);out_free_cdev:    kfree(cdev);out_unregister_devno:    unregister_chrdev_region(devno, 1);    return ret;}module_init(led_init);

3. device_add()

static class *led_class;static int __init led_init(void){    ......     /* 注册设备号 */    ......    /* 分配、初始化、注册cdev*/    ......    /* 创建设备类 */    ......    /* 创建设备节点 */    dev = kzalloc(sizeof(*dev), GFP_KERNEL);    if (!dev) {        ret = -ENOMEM;        goto out_del_class;    }    dev->class = led_class;         // 关联设备类    dev->parent = NULL;                 dev->devt = devno;              // 关联设备号    dev_set_drvdata(dev, NULL);         dev_set_name(dev, "led");       // 设置节点名字    dev->release = device_create_release;    device_initialize(dev);    ret = device_add(dev);    if (ret)         goto out_put_dev;    return 0;out_put_dev:    put_device(dev);    kree(dev);out_del_class:    class_destroy(c78x_class);    out_unregister_cdev:        cdev_del(cdev);out_free_cdev:    kfree(cdev);out_unregister_devno:    unregister_chrdev_region(devno, 1);    return ret;}module_init(led_init);
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 把老公生日忘了怎么办 老公说老婆脑子不好怎么办 和上司暧昧被同事发现怎么办 减肥不吃晚餐饿了怎么办 小孩晚饭吃多了怎么办 减肥晚上不吃饭饿了怎么办 两个人在一起性格不合怎么办 赌在你身上输了怎么办 苹果7lcould满了怎么办 e招贷不用了怎么办 牙活动了怎么办还疼 30岁掉了一颗牙怎么办? 在淘宝上交话费交错了怎么办 演出队在小区旁边扰民怎么办 雷雨天加了油怎么办 戴ok镜眼睛重影怎么办 乌龟背上长白色的花纹怎么办? 全自动洗衣机里面掉个硬币怎么办 跆拳道课上孩子乱动说话怎么办? 孩子不愿意上跆拳道课了怎么办 车座位里面倒了汤怎么办 腿被棍子打肿了怎么办 刚买的手机碎屏怎么办 被木棍么么打到头项怎么办 大王卡用到40g怎么办 王卡40g用完了怎么办 父亲把母亲打成重伤怎么办 狗狗脖子摔歪了怎么办 吃鸡游戏中重伤怎么办 吃鸡游戏摔伤了怎么办 现在没能力偿还网贷怎么办 上海找夜场工作被骗了怎么办? 买了烂尾的楼盘怎么办 孕七个月蛀牙疼怎么办 宝宝只吃一边奶怎么办 实房付了定金后悔了怎么办 开车时遇到意外事故时怎么办 没干过影楼门市怎么办 uplay下载游戏速度0k怎么办 缓刑期间被别人打成轻伤怎么办 缓刑期间被别人打了怎么办