嵌入式开发记录-day20 字符驱动--1 申请设备号
1、设备号包括主、次设备号;杂项设备主设备号固定为10.但是对于字符类的主设备号,需要自己申请;
2、申请设备号包含的头文件
#include <linux/fs.h> // 申请设备号函数 int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); // 动态申请设备号 int register_chrdev_region(dev_t, unsigned, const char *) // 静态申请设备号 int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops); // linux2.6版本以前支持比较,比较老的用的少 #include <linux/kdev_t.h> // MKDEV宏定义的相关处理 /*Some programs want their definitions of MAJOR and MINOR and MKDEV from the kernel sources. These must be the externally visible ones.*/ // linux源码中的解释 #define MAJOR(dev) ((dev)>>8) // 获取主设备号 #define MINOR(dev) ((dev) & 0xff) // 获取次设备号 #define MKDEV(ma,mi) ((ma)<<8 | (mi)) // 转换成可以注册的设备号 #include <linux/cdev.h> struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; // 应用这个类型的参数 unsigned int count; };
3、静态申请设备号schrdev.c
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/fs.h> // 申请设备号函数 4 #include <linux/kdev_t.h> // MKDEV宏定义的相关处理 5 #include <linux/cdev.h> 6 7 MODULE_LICENSE("Dual BSD/GPL"); 8 /*声明是开源的,没有内核版本限制*/ 9 MODULE_AUTHOR("iTOPEET_dz"); 10 /*声明作者*/ 11 12 #define DEVICE_NAME "sscdev" // 注册的设备名称 13 #define DEVICE_MINOR_NUM 2 // 包含设备号的数量 14 #define DEV_MAJOR 0 // 预定以主设备号为0,加载的时候在查询 15 #define DEV_MINOR 0 // 预设次设备号为0 cat /proc/devices 16 17 int numdev_major = DEV_MAJOR; 18 int numdev_minor = DEV_MINOR; 19 20 /*输入主设备号 传递参数*/ 21 module_param(numdev_major,int,S_IRUSR); 22 /*输入次设备号*/ 23 module_param(numdev_minor,int,S_IRUSR); 24 25 static int hello_init(void) 26 { 27 int ret = 0; 28 dev_t num_dev; 29 30 printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); 31 printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); 32 33 if(numdev_major){ 34 // 将设备号转换成可以注册的格式 35 num_dev = MKDEV(numdev_major,numdev_minor); 36 // 在内核中注册主次设备号 37 ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); 38 } 39 else{ 40 printk(KERN_EMERG "numdev_major %d is failed!\n",numdev_major); 41 } 42 if(ret<0){ 43 printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); 44 } 45 46 printk(KERN_EMERG "scdev_init!\n"); 47 /*打印信息,KERN_EMERG表示紧急信息*/ 48 return 0; 49 } 50 51 static int hello_exit(void) 52 { 53 printk(KERN_EMERG "hello exit...\n"); 54 // 注销注册好的设备号 55 unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); 56 return 0; 57 } 58 59 // 模块的入口函数 60 module_init(hello_init); 61 module_exit(hello_exit);
4、编译成模块
insmod /mnt/disk/schrdev.ko numdev_major=9 numdev_minor=0 [ 3314.010306] numdev_major is 9! [ 3314.011981] numdev_minor is 0! [ 3314.015031] scdev_init! cat /proc/devices
5、动态申请设备号achrdev.c
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/fs.h> // 申请设备号函数 4 #include <linux/kdev_t.h> // MKDEV宏定义的相关处理 5 #include <linux/cdev.h> 6 7 MODULE_LICENSE("Dual BSD/GPL"); 8 /*声明是开源的,没有内核版本限制*/ 9 MODULE_AUTHOR("iTOPEET_dz"); 10 /*声明作者*/ 11 12 #define DEVICE_NAME "ascdev" // 注册的设备名称 13 #define DEVICE_MINOR_NUM 2 // 包含设备号的数量 14 #define DEV_MAJOR 0 // 预定以主设备号为0,加载的时候在查询 15 #define DEV_MINOR 0 // 预设次设备号为0 cat /proc/devices 16 17 int numdev_major = DEV_MAJOR; 18 int numdev_minor = DEV_MINOR; 19 20 /*输入主设备号*/ 21 module_param(numdev_major,int,S_IRUSR); 22 /*输入次设备号*/ 23 module_param(numdev_minor,int,S_IRUSR); 24 25 static int hello_init(void) 26 { 27 int ret = 0; 28 dev_t num_dev; 29 30 printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); 31 printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); 32 33 if(numdev_major){ 34 // 将设备号转换成可以注册的格式 35 num_dev = MKDEV(numdev_major,numdev_minor); 36 // 在内核中注册主次设备号 37 ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); 38 } 39 else{ // 动态申请设备号 设备号地址、次设备号、设备号数量、设备号名称 40 ret = alloc_chrdev_region(&num_dev, numdev_minor, DEVICE_MINOR_NUM,DEVICE_NAME); 41 if(ret < 0){ 42 printk(KERN_EMERG "func alloc_chrdev_region was failed!\n"); 43 } 44 printk(KERN_EMERG "adev_region numdev_major req %d !\n",MAJOR(num_dev)); 45 printk(KERN_EMERG "adev_region numdev_minor req %d !\n",MINOR(num_dev)); 46 } 47 if(ret<0){ 48 printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); 49 } 50 51 printk(KERN_EMERG "scdev_init!\n"); 52 /*打印信息,KERN_EMERG表示紧急信息*/ 53 return 0; 54 } 55 56 static int hello_exit(void) 57 { 58 printk(KERN_EMERG "hello exit...\n"); 59 // 注销注册好的设备号 60 unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); 61 return 0; 62 } 63 64 // 模块的入口函数 65 module_init(hello_init); 66 module_exit(hello_exit);
6、编译成模块
[root@iTOP-4412]# insmod /mnt/disk/achrdev.ko [ 106.984155] numdev_major is 0! [ 106.985744] numdev_minor is 0! [ 106.988768] adev_region numdev_major req 248 ! [ 106.993214] adev_region numdev_minor req 0 ! [ 106.997455] scdev_init!

浙公网安备 33010602011771号