嵌入式开发记录-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!

 

posted @ 2020-07-12 11:37  笑不出花的旦旦  阅读(175)  评论(0)    收藏  举报