cdev方式注册驱动
来源:互联网 发布:安卓ar软件 编辑:程序博客网 时间:2024/06/03 17:26
1、简介
内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev_region()、alloc_chrdev_region() 和 register_chrdev()。
(1)register_chrdev 比较老的内核注册的形式 早期的驱动
(2)register_chrdev_region/alloc_chrdev_region + cdev 新的驱动形式
区别:register_chrdev()函数是老版本里面的设备号注册函数,可以实现静态和动态注册两种方法,主要是通过给定的主设备号是否为0来进行区别,为0的时候为动态注册。register_chrdev_region以及alloc_chrdev_region就是将上述函数的静态和动态注册设备号进行了拆分的强化。
1.2 使用流程
字符驱动cdev注册流程
1. 申请并注册主从设备号
2. 初始化已定义的cdev变量,cdev变量指定file_operations接口
3. 添加cdev变量到内核,完成驱动注册,添加cdev时需要一个已申请成功的主从设备号
字符驱动cdev注销流程
4. 删除已添加的cdev
5. 注销申请的主从设备号
1.3 主要方法
//动态分配设备编号int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name);dev:自动分配的主设备号将保存在dev中firstminor:第一个次设备号 一般为0count:要分配的设备数量name:设备名//指定一个主设备号和一个起始从设备号,如果成功返回0 失败返回错误码dev_t first = MKDEV(int major, int minor);int register_chrdev_region(dev_t first, unsigned int count, char *name);First :要分配的设备编号范围的初始值, 这组连续设备号的起始设备号, 相当于register_chrdev()中主设备号Count:连续编号范围. 是这组设备号的大小(也是次设备号的个数)Name:编号相关联的设备名称. (/proc/devices); 本组设备的驱动名称//注销设备void unregister_chrdev_region(dev_t from,unsigned count)//初始化cdev变量,并设置fopsvoid cdev_init(struct cdev *cdev, const struct file_operations *fops)//添加cdev到linux内核,完成驱动注册int cdev_add(struct cdev *p, dev_t dev, unsigned count)dev:申请好的主设备号+起始从设备号count:为该驱动所占用从设备号的数目//从内核中删除cdev数据void cdev_del(struct cdev *p)
demo
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/uaccess.h>/*声明class_create 和device_create相关信息*/#include <linux/device.h>//cdev用到的头文件#include <linux/cdev.h>#define DEMO_DEBUG#ifdef DEMO_DEBUG#define dem_dbg(fmt, arg...) printk(KERN_WARNING fmt, ##arg)#else#define dem_dbg(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)#endif#define DEVICE_COUNT 1//1 定义cdev结构体变量和dev_nr主从设备号变量static struct cdev demo_cdev;static dev_t dev_nr;static int demo_open (struct inode *pnode, struct file *filp){ dem_dbg("==>%s major: %d minor: %d\n", __FUNCTION__, imajor(pnode), iminor(pnode)); return 0;}static ssize_t demo_read (struct file *filp, char __user *buf, size_t count, loff_t *offp){ unsigned char ary[100] = "read successfully\n"; unsigned long len = min(count, sizeof(ary)); int retval; printk("==>%s major: %d minor: %d\n", __FUNCTION__, imajor(filp->f_dentry->d_inode), iminor(filp->f_dentry->d_inode)); if(copy_to_user(buf, ary, len) != 0){ retval = -EFAULT; goto cp_err; } return len;cp_err: return retval; }static int demo_release (struct inode *pnode, struct file *filp){ dem_dbg("==>%s major: %d minor: %d\n", __FUNCTION__, imajor(pnode), iminor(pnode)); return 0;}static struct file_operations fops = { .owner = THIS_MODULE, .read = demo_read, .open = demo_open, .release = demo_release,}; static struct class *demo_class;static int __init demo_init(void){ int res, i; struct device *demo_device; dem_dbg("==>demo_init\n"); //2.1 动态申请主从设备号 res = alloc_chrdev_region(&dev_nr, 0, DEVICE_COUNT, "demo_chrdev"); //2.2 指定主从设备号 //dev_nr = MKDEV(200, 0); //res = register_chrdev_region(dev_nr, DEVICE_COUNT, "demo_cdev"); if(res){ dem_dbg("==>alloc chrdev region failed!\n"); goto chrdev_err; } //3 初始化cdev数据 cdev_init(&demo_cdev, &fops); //4 添加cdev变量到内核,完成驱动注册 res = cdev_add(&demo_cdev, dev_nr, DEVICE_COUNT); if(res){ dem_dbg("==>cdev add failed!\n"); goto cdev_err; } //创建设备类 demo_class = class_create(THIS_MODULE,"demo_class"); if(IS_ERR(demo_class)){ res = PTR_ERR(demo_class); goto class_err; } for(i=0; i<DEVICE_COUNT; i++){ //创建设备节点 demo_device = device_create(demo_class,NULL, MKDEV(MAJOR(dev_nr), i), NULL,"demo%d",i); if(IS_ERR(demo_device)){ res = PTR_ERR(demo_device); goto device_err; } } return 0;device_err: while(i--) device_destroy(demo_class,MKDEV(MAJOR(dev_nr), i)); class_destroy(demo_class);class_err: cdev_del(&demo_cdev); cdev_err: unregister_chrdev_region(dev_nr, DEVICE_COUNT);chrdev_err: //申请主设备号失败 return res;}static void __exit demo_exit(void){ int i; dem_dbg("==>demo_exit\n"); //5 删除添加的cdev结构体,并释放申请的主从设备号 cdev_del(&demo_cdev); unregister_chrdev_region(dev_nr, DEVICE_COUNT); for(i=0; i<DEVICE_COUNT; i++) device_destroy(demo_class,MKDEV(MAJOR(dev_nr), i)); class_destroy(demo_class);}module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("Dual BSD/GPL");
阅读全文
0 0
- cdev方式注册驱动
- 笔记二:字符设备之cdev方式注册字符驱动
- 字符设备驱动--- 数据结构 设备注册struct cdev , 注销
- 字符设备驱动--- 数据结构 设备注册struct cdev , 注销
- 一步步写驱动---cdev
- 驱动之cdev
- 驱动之cdev
- Linux驱动的注册方式
- Linux设备驱动----之一 cdev
- Linux设备驱动----之一 cdev
- Linux 设备驱动--- struct cdev
- linux字符设备驱动 cdev
- cdev设备驱动的使用
- 设备驱动-----字符驱动globalmem(cdev)
- cdev
- cdev
- 注册JDBC驱动的三种方式
- Jdbc注册驱动的三种方式
- window线程池
- Java常用并发容器(concurrent包)
- 【操作系统学习日记】1.环境安装(ubantu+bochs)
- derby数据库源码分析(三)–页面分析
- HDU
- cdev方式注册驱动
- Pointers on C——6 Pointers.5
- hdu4300 Clairewd’s message (字符串hash)
- Threejs开发笔记之四材质
- Pointers on C——6 Pointers.6
- Spring学习之IOC容器(二)
- 标题栏渐变效果
- Pointers on C——6 Pointers.7
- 推荐算法从入门、进阶到高级