Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建

转载 2012年03月21日 10:15:51

似乎每一章介绍的内容比较少,但学习是一个循序渐进的过程,不在于一天学多少,重要的一天能真正的学懂多少,所以我主张一步一步来,从多个渠道去学习知识,实现互补。

本节测试代码传到此处了:char_step1 大家可以下载测试一下。

字符设备的注册与设备节点的自动创建

cdev 结构

内核内部使用struct cdev<linux/cdev.h>来表示一个字符设备

struct cdev {
    struct kobject kobj; //kobj设备模型以后介绍
    struct module *owner;
    const struct file_operations *ops;//文件操作
    struct list_head list;
    dev_t dev;//设备号
    unsigned int count; //设备个数
};

注册字符设备

动态初始化:

struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_ops;

静态初始化:

struct cdev my_cdev;
cdev_init(&my_dev, &my_ops);

向内核注册(添加设备):

int cdev_add(struct cdev *dev, dev_t num, unsigned count);
dev: 指向以初始化的字符设备结构
num: 设备号
count: 所要添加的设备个数
返回值:
成功返回0 失败返回错误码,设备被注册时候可能立即会呗调用,所以在驱动程序还没有准备好处理设备操作时候不要先调用cdev_add

注销字符设备:

在不需要用西设备时候需要注销设备
void cdev_del(struct cdev *);

早期的方法

在2.6的内核之前注册字符设备有一个简单易用的方法,现在也可以使用但是不建议使用,因为到最后这个方法会从内核消失

注册字符设备:

static inline int register_chrdev(unsigned int major, 
    const char *name, const struct file_operations *fops);
major: 主设备号 (当major为0时表示有内核分配一个可用的主设备号并返回)
name: 驱动名
fops: 文件操作
缺点: 不能同时注册多个设备, 他是用一种默认的方式去建立一个cdev结构,而这样的话它不能使用大于255的主次设备号

注销设备:

static inline void unregister_chrdev(unsigned int major, const char *name)

设备节点的自动创建

在上一个程序中,虽然能够争取的得到一个设备号,但是并不会在/dev/目录下生成一个设备节点。

使用手动创建

mknod /dev/device_name c major minor
device_name: 指设备名,
c: 表述创建字符设备节点(同理b 表示创建块设备文件节点)
major: 主设备号
minor: 次设备号
在做测试时候这样做事可以理解的,而在作为一个模块要发行时候,这样就太不方面了,①要先查看设备是否成功创建,②查看注册设备的主设备号,③输入命令创建文件节点
当然可以写一个shell脚本来完成这些事情。

自动创建设备节点

需要的纤体内核空间支持udev,在内核配置,及busybox配置时候需要指定
内核中定义了struct class 与 struct devic结构<linux/device.h>
创建一个class结构
#define class_create(owner, name)    \
({            \
    static struct lock_class_key __key;   \
    __class_create(owner, name, &__key); \
})
owner表示拥有这个模块的指针
name 表示设备名
调用此函数后 创建了一个struct class结构放在sysfs下边,而后调用
struct device *device_create(struct class *cls, 
    struct device *parent,
                    dev_t devt, void *drvdata,
                    const char *fmt, ...)
在/dev目录下创建设备节点
cls : 是上边函数的创建的struct class结构指针
parent: 指向设备的父节点设备(如果没有填NULL
devt: 被添加设备的设备号
drvdata: 回调函数参数
fmt ,args:一个或者多个设备名
至此我们就自动创建了一个设备节点

删除设备节点

在设备不需要使用时候我们需要删除设备节点:
void device_destroy(struct class *class, dev_t devt);//删除设备节点
void class_destroy(struct class *cls);//删除sysfs下得struct class结构
至于深层的一些实现机制,没有细细研究,大家干兴趣可以参考相关资料

实例:

初始化 添加设备到内核

  1.     simple_cdev = cdev_alloc(); //动态初始化字符设备  
  2.     if(simple_cdev != NULL)   
  3.     {   
  4.         simple_cdev->ops   = &simple_fops; //文件操作  
  5.         simple_cdev->owner = THIS_MODULE;   
  6.     }   
  7.     else  
  8.     {   
  9.         printk(KERN_ERR "alloc cdev err no memory");   
  10.         unregister_chrdev_region(dev, DEV_COUNT); //如果分配资源出错则释放设备号  
  11.         return -ENOMEM;   
  12.     }   
  13.   
  14.     err = cdev_add(simple_cdev, dev, DEV_COUNT); //向内核添加设备  
  15.     if(err < 0)   
  16.     {   
  17.         printk(KERN_ERR "add cdev err \n");   
  18.         goto error1;   
  19.     }   
  20.     else  
  21.     {   
  22. #if SIMPLE_DEBUG   
  23.         printk(KERN_INFO "add char dev OK!\n");   
  24. #endif   
  25.     }   

自动创建设备节点

  1.     simple_class = class_create(THIS_MODULE, SIMPLE_NAME);   
  2.     if(simple_class == NULL)   
  3.     {   
  4.         printk(KERN_ERR "create simple class error\n");   
  5.         goto error2;   
  6.     }   
  7.     else  
  8.     {   
  9. #if SIMPLE_DEBUG   
  10.         printk(KERN_INFO "create simple class  OK!\n");   
  11. #endif   
  12.     }   
  13.   
  14.     simple_dev = device_create(simple_class, NULL, dev, NULL, SIMPLE_NAME);   
  15.     if(simple_dev == NULL)   
  16.     {   
  17.         printk(KERN_ERR "create device error");   
  18.         goto error3;   
  19.     }   
  20.     else  
  21.     {   
  22. #if SIMPLE_DEBUG   
  23.         printk(KERN_INFO "create simple device  OK!\n");   
  24. #endif   
  25.     }  

删除设备节点,注销字符设备

  1. dev = MKDEV(simple_major, simple_minor); //计算出设备号  
  2. device_destroy(simple_class, dev); //删除设备节点  
  3. class_destroy(simple_class);//删除并释放class结构  
  4. cdev_del(simple_cdev);//注销设备   
  5. cdev_put(simple_cdev);//对动态的设备需要使用cdev_put‘来释放资源 

相关文章推荐

Linux驱动编程 step-by-step (九)字符设备模拟pipe的驱动程序

字符设备模拟pipe的驱动程序 让我们用一个”pipe“的设备驱动去结束简单字符设备吧(这里所说的pipe并非标准的pipe只是模拟了一个从一端写入从另一端写入的设备) 测试代码1      测试...

Linux驱动编程 step-by-step (二) 简单字符设备驱动

简单字符设备驱动 1、主次设备号 主设备号标识设备连接的的驱动,此设备好由内核使用,标识在相应驱动下得对应的设备 在linux中设备号是一个32位的dev_t类型 typedef __u3...

linux驱动开发--字符设备:自动创建设备节点

 自动创建设备文件 定义在中 class结构:该结构体类型变量对应一个设备类,被创建的类存放在/sys目录下面 device结构:该结构体类型变量对应设备,被创建的设备存放于/sys目录下...
  • wbcuc
  • wbcuc
  • 2017年01月18日 19:28
  • 125

Linux 字符设备驱动结构(二)—— 自动创建设备节点

上一篇我们介绍到创建设备文件的方法,利用cat /proc/devices查看申请到的设备名,设备号。 第一种是使用mknod手工创建:mknod filename type major minor ...

linux驱动开发之字符设备--自动创建设备节点

mdev在/dev下创建设备的方法有两种,一种是手动的使用 mknod 进行创建。另外一种是使用 mdev 进行自动的创建设备。 mdev集成在busybox中,mdev 会自动检测 /sys/cla...

linux字符设备驱动中自动创建设备节点

本文简述在linux字符设备驱动编程中自动创建设备节点。至于手动创建设备节点的编程...
  • yxtouch
  • yxtouch
  • 2014年10月23日 19:48
  • 840

Linux驱动编程--字符设备文件注册

CreateClass DestroyClass

linux驱动之自动创建设备节点

利用cat /proc/devices查看申请到的设备名,设备号。 创建设备节点 1.使用mknod手工创建:mknod filename type major minor 2.自动创建设备节点...

Linux驱动模块自动创建设备节点

在宋宝华《Linux设备驱动开发详解》中我们能找到如下描述: devfs与udev的另一个显著区别在于:采用devfs,当一个并不存在的/dev节点被打开的时候,devfs能自动加载对应的驱动,而ud...

【Linux驱动】自动创建设备节点

开始学习驱动的时候,是将驱动程序编译成模块然后用mknod命令手动建立设备节点以提供给应用程序调用。这对于刚开始调试驱动程序的时候常用的一种方法。但是,当有种需要必须在系统启动的时候就将驱动程序就绪,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建
举报原因:
原因补充:

(最多只允许输入30个字)