在字符设备驱动开发的入门教程中,最常见的就是用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()函数,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, , , "led");
if (ret < )
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, );
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 ; 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, ); 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 ; 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, ); 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 ; 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, ); return ret;
} module_init(led_init);

linux driver ------ 字符设备驱动 之 “ 创建设备节点流程 ”的更多相关文章

  1. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...

  2. [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联

    转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...

  3. Linux 设备驱动开发 —— platform设备驱动应用实例解析

    前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 —— platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...

  4. linux驱动之设备号与创建设备节点

    设备号: 1.自己主动分配 major = register_chrdev(0,"first_drv",&first_sdv_fops);//注冊 注冊设备时给设备号写0, ...

  5. 乾坤合一~Linux设备驱动之块设备驱动

    1. 题外话 在蜕变成蝶的一系列学习当中,我们已经掌握了大部分Linux驱动的知识,在乾坤合一的分享当中,以综合实例为主要讲解,在一个月的蜕茧成蝶的学习探索当中,觉得数据结构,指针,链表等等占据了代码 ...

  6. 蜕变成蝶~Linux设备驱动之watchdog设备驱动

    看门狗(watchdog )分硬件看门狗和软件看门狗.硬件看门狗是利用一个定时器 电路,其定时输出连接到电路的复位端,程序在一定时间范围内对定时器清零 (俗称 “喂狗”),如果程序出现故障,不在定时周 ...

  7. 蜕变成蝶~Linux设备驱动之按键设备驱动

    在上述的驱动系列博客中,我们已经了解了关于阻塞和非阻塞.异步通知.轮询.内存和I/O口访问.并发控制等知识,按键设备驱动相对来说是比较简单的,本章内容可以加深我们对字符设备驱动架构.阻塞与非阻塞.中断 ...

  8. Linux 内核驱动自动创建设备节点并挂载设备

    *注:本文来自http://blog.csdn.net/lwj103862095/article/details/17470573 一.首先需要在最开始定义两个数据结构: static struct ...

  9. linux driver ------ platform模型,通过杂项设备(主设备号是10)注册设备节点

    注册完设备和驱动之后,就需要注册设备节点 Linux杂项设备出现的意义在于:有很多简单的外围字符设备,它们功能相对简单,一个设备占用一个主设备号对于内核资源来说太浪费.所以对于这些简单的字符设备它们共 ...

随机推荐

  1. C# 23种设计模式汇总

    创建型模式工厂方法(Factory Method)在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节.工厂方法模式的核心是一个抽象工厂类,各种具体工 ...

  2. iPhone

    电报交流***vpnpay app不能用了,只要能下载就可以用,谨慎卸载 升级.网络链接不成功的,多试几次,毕竟程序不会运行你的错误操作 ,重新添加链接服务器,继续搞!耐心的进行下面操作即可链接,如有 ...

  3. 洛谷-p2764(最小路径覆盖)(网络流24题)

    #include<iostream> #include<algorithm> #include<queue> #include<cstring> #in ...

  4. Nginx 完整安装篇

    第一步安装各种编译库如c++编译库等 yum install -y gcc //安装GCC ...安装过程省略 yum install -y gcc-c++ //安装C++库用来编译c++ ...安装 ...

  5. Nginx 如何处理上游响应的数据

    陶辉93 一个非常重要的指令 proxy_buffer_size 指令限制头部响应header最大值 proxy_buffering 指令主要是指 上游服务器是否接受完完整包体在处理 默认是on 也就 ...

  6. BZOJ4873[Shoi2017]寿司餐厅——最大权闭合子图

    题目描述 Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个 代号ai和美味度di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无 ...

  7. hiho1259 A Math Problem (数位dp)

    题目链接:http://hihocoder.com/problemset/problem/1259 题目大意:g(t)=(f(i)%k=t)的f(i)的个数 求所有的(0-k-1)的g(i)的异或总值 ...

  8. Ubuntu解压

    tar -zxvf FileName.tar.gz tar -jxvf FileName.tar.bz2 unzip FileName.zip sudo  dpkg  -i   文件名.deb

  9. 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)

    Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...

  10. [UOJ317]【NOI2017】游戏 题解

    题意 ​ 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. ​ 小 L 的赛车有三辆,分别用大写字母 A.B.C 表示.地图一共有四种,分别用小写字 ...