linux 设备节点 驱动,linux driver ------ 字符设备驱动 之 “ 创建设备节点流程 ”...

在字符设备驱动开发的入门教程中,最常见的就是用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);

......returndev;

}

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);returndevice_add(dev);

}

加载驱动,执行device_add()函数,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)

{intret;

dev_t devno;struct cdev *cdev;struct dev *dev;/*注册设备号*/ret= alloc_chrdev_region(&devno, 0, 1, "led");if (ret < 0)returnret;/*分配、初始化、注册cdev*/cdev=cdev_alloc();if(IS_ERR(cdev)) {

ret=PTR_ERR(cdev);gotoout_unregister_devno;

}

cdev_init(&cdev, &led_fops);

cdev.owner=THIS_MODULE;

ret= cdev_add(&cdev, devno, 1);if(ret)gotoout_free_cdev;/*创建设备类*/led_class= class_create(THIS_MODULE, "led_class");if(IS_ERR(led_class)) {

ret=PTR_ERR(led_class);gotoout_unregister_cdev;

}/*创建设备节点*/dev= device_create(led_class, NULL, devno, NULL, "led");if(IS_ERR(dev)) {

ret=PTR_ERR(dev);gotoout_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);returnret;

}

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;gotoout_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)gotoout_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);returnret;

}

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;gotoout_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)gotoout_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);returnret;

}

module_init(led_init);

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值