嵌入式开发记录-day21 字符驱动--2 注册字符类设备
1、在前面几节里也有注册设备,但是都是注册杂项设备,并且杂项设备的设备号都是固定的10;
2、应用的函数
// 函数在include/linux/slab.h // 分配内存空间 void *kmalloc(size_t s, gfp_t gfp) // 其中,gfp是枚举类,GFP_KERNEL取值表示内存不够可延迟分配 // 函数路径include/linux/cdev.h //字符设备初始化 void cdev_init(struct cdev *, const struct file_operations *); // 添加到内核中 int cdev_add(struct cdev *, dev_t, unsigned); //卸载设备 void cdev_del(struct cdev *); //cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; // 应用这个类型的参数 unsigned int count; };
3、实现registercdev.c
1 #include <linux/init.h> 2 /*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/ 3 #include <linux/module.h> 4 #include <linux/fs.h> // 申请设备号函数 5 #include <linux/kdev_t.h> // MKDEV宏定义的相关处理 6 #include <linux/cdev.h> 7 #include <linux/slab.h> 8 9 MODULE_LICENSE("Dual BSD/GPL"); 10 /*声明是开源的,没有内核版本限制*/ 11 MODULE_AUTHOR("iTOPEET_dz"); 12 /*声明作者*/ 13 14 #define DEVICE_NAME "ascdev" // 注册设备的名称 15 #define DEVICE_MINOR_NUM 2 // 次设备的个数 16 #define DEV_MAJOR 0 // 预定以主设备号为0,加载的时候在查询 静态设置设备号 17 #define DEV_MINOR 0 // 预设次设备号为0 cat /proc/devices 18 #define REGDEV_SIZE 3000 // 定义注册设备存储数据的大小 相当于读写操作时的缓冲大小 19 20 int numdev_major = DEV_MAJOR; 21 int numdev_minor = DEV_MINOR; 22 23 struct reg_dev 24 { 25 char *data; // 存放数据 用于读写设备时的缓冲 26 unsigned long size; // 定义数据长度 27 struct cdev cdev; // 包含的操作fops 28 }; 29 30 struct reg_dev *my_devices; 31 // 简单初始化结构体file_operations 32 struct file_operations my_fops = { 33 .owner = THIS_MODULE, 34 }; 35 36 /*输入主设备号*/ 37 module_param(numdev_major,int,S_IRUSR); 38 /*输入次设备号*/ 39 module_param(numdev_minor,int,S_IRUSR); 40 41 /// 单个设备初始化 42 static void reg_init_cdev(struct reg_dev* dev,int index) 43 { 44 int ret; 45 int devnum = MKDEV(numdev_major,numdev_minor+index); 46 47 // 设备单个结点初始化 48 cdev_init(&dev->cdev,&my_fops); 49 dev->cdev.owner = THIS_MODULE, 50 dev->cdev.ops = &my_fops, 51 // 将设备结点加载到内核中 52 ret = cdev_add(&dev->cdev,devnum,1); 53 if(ret){ 54 printk(KERN_EMERG "cdev_add %d is fail! %d\n",index,ret); 55 } 56 else{ 57 printk(KERN_EMERG "cdev_add %d is success!\n",index); 58 } 59 } 60 61 static int scdev_init(void) 62 { 63 int ret = 0,i; 64 dev_t num_dev; 65 66 printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); 67 printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); 68 69 if(numdev_major){ 70 // 将设备号转换成可以注册的格式 71 num_dev = MKDEV(numdev_major,numdev_minor); 72 // 将主次设备号注册到linux内核中 73 ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); 74 } 75 else{ // 动态申请设备号 76 // 设备号地址、次设备号、设备号数量、设备号名称 77 ret = alloc_chrdev_region(&num_dev, numdev_minor, DEVICE_MINOR_NUM,DEVICE_NAME); 78 if(ret < 0){ 79 printk(KERN_EMERG "func alloc_chrdev_region was failed!\n"); 80 } 81 printk(KERN_EMERG "adev_region numdev_major req %d !\n",MAJOR(num_dev)); 82 printk(KERN_EMERG "adev_region numdev_minor req %d !\n",MINOR(num_dev)); 83 } 84 if(ret<0){ 85 printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); 86 } 87 88 // 成功申请设备号,开始分配内存; 89 // 分配内存是在获取主设备号以后 90 my_devices = kmalloc(DEVICE_MINOR_NUM* sizeof(struct reg_dev), GFP_KERNEL); 91 if(!my_devices){ 92 ret = -ENOMEM; 93 goto fail; 94 } 95 // 分配内存完成后,清空内存 96 memset(my_devices,0,DEVICE_MINOR_NUM* sizeof(struct reg_dev)); 97 for(i=0;i<DEVICE_MINOR_NUM;i++){ 98 // 给缓冲区申请内存 99 my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL); 100 memset(my_devices[i].data,0,REGDEV_SIZE); // 清0 101 // 初始化单个设备 102 reg_init_cdev(&my_devices[i],i); 103 } 104 105 printk(KERN_EMERG "scdev_init!\n"); 106 /*打印信息,KERN_EMERG表示紧急信息*/ 107 return 0; 108 109 fail: 110 unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); 111 printk(KERN_EMERG "kmalloc is fail!\n"); 112 return ret; 113 } 114 115 static void scdev_exit(void) 116 { 117 int i=0; 118 printk(KERN_EMERG "hello exit...\n"); 119 // 注销注册好的设备号 120 unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); 121 } 122 123 // 模块的入口函数 124 module_init(scdev_init); 125 module_exit(scdev_exit);
4、加载结果
[root@iTOP-4412]# insmod /mnt/disk/registercdev.ko [ 52.639464] numdev_major is 0! [ 52.641156] numdev_minor is 0! [ 52.644130] adev_region numdev_major req 248 ! [ 52.648666] adev_region numdev_minor req 0 ! [ 52.652869] cdev_add 0 is success! [ 52.656259] cdev_add 1 is success! [ 52.659641] scdev_init!

浙公网安备 33010602011771号