驱动学习(五)自动创建设备文件

驱动学习(五)自动创建设备文件

1. 创建设备文件的方式
1.1 手动创建
sudo mknod /dev/testchrdev0 c 200 0 上一节手动创建了字符设备文件
1.2 自动创建

linux内核为我们提供了一组函数,可以用来在模块加载时自动在/dev目录下创建设备对应的设备文件,并在模块卸载时删除该设备文件。

1.2.1 class_create
class_create(owner, name)
	作用:创建一个设备文件类
	owner:THIS_MODULE表示模块本身
	name:设备模块名
	返回值:struct class *指针(指向设备文件类)
1.2.2 device_create
struct device *device_create(struct class *class, struct device *parent,
	       dev_t devt, void *drvdata, const char *fmt, ...)
	作用:创建一个设备文件
	class:设备文件类指针(是class_create的返回值)
	parent:父设备,一般为NULL
	devt:设备号(主设备+次设备号)
	drvdata:指向私有数据的指针,若没有私有数据,给NULL
	fmt:设备文件名
	...:可变参数,可有可无
	返回值:成功,struct device类型的指针;失败,需要用ERR_PTR函数做判断
1.2.3 device_destroy
void device_destroy(struct class *class, dev_t devt)
 	作用:销毁设备文件
	class:设备文件类指针
	devt:设备号
1.2.4 class_destroy
void class_destroy(struct class *cls)
	cls:设备文件类指针
	作用:销毁设备文件类
2. 测试

测试环境:ubuntu 20.04

思路:在上一节代码的基础上添加:自动创建设备文件类(安装时)、自动创建设备文件(安装时)、自动删除代码(卸载时)。查看内核打印信息是否正确和查看字符设备文件是否创建成功来验证结果

 ###驱动代码
  1 #include <linux/module.h>           //模块驱动的头文件
  2 #include <linux/cdev.h>             //设备信息描述的头文件
  3 #include <linux/fs.h>               //静态申请设备号头文件
  4 #include <linux/kdev_t.h>           //设备号用到的头文件和宏函数
  5 #include <linux/uaccess.h>
  6 #include <linux/device.h>
  7 
  8 #define BUF_SIZE 100
  9 
 10 int major = 0;                      //主设备号
 11 int min = 0;                        //次设备号
 12 int deviceNum = 0;                  //完整设备号
 13 struct cdev* pCdev = NULL;          //描述设备信息的结构体
 14 char *deviceName = "autoCreateNode";//设备名
 15 char buff[BUF_SIZE] = "chrdev-test-2022-7-11";
 16 struct class *pClass = NULL;        //设备文件类指针
 17 int devNum = 2;                     //设备文件数量
 18 
 19 int testOpen(struct inode *pNode,struct file *pFile)
 20 {
 21         printk("------into test open------\n");
 22         printk("------leave test open------\n");
 23         return 0;
 24 }
 25 int testClose(struct inode *pNode,struct file *pFile)
 26 {
 27         printk("------into test close------\n");
 28         printk("------leave test close------\n");
 29         return 0;
 30 }
 31 ssize_t testRead(struct file *pFile,char __user *buf,size_t count,loff_t *pOffset)
 32 {
 33         int res = -1;
 34         printk("------into testRead------\n");
 35         if(count > BUF_SIZE-1)
 36         {
 37                 count = BUF_SIZE - 1;
 38         }
 39         res = copy_to_user(buf,buff,count);
 40         if(res)
 41         {
 42                 printk("copy_to_user error\n");
 43                 return -EFAULT;
 44         }
 45         printk("copy_to_user ok\n");
 46         printk("\t buff = %s\t\n",buff);
 47         printk("------leave testRead------\n");
 48         return count;
 49 }
 50 
 51 ssize_t testWrite(struct file *pFile,const char __user *buf,size_t count,loff_t *pOffset)
 52 {
 53         int res = -1;
 54         printk("------into testWrite------\n");
 55         if(count > BUF_SIZE-1)
 56         {
 57                 count = BUF_SIZE - 1;
 58         }
 59         res = copy_from_user(buff,buf,count);
 60         if(res)
 61         {
 62                 printk("copy_from_user error\n");
 63                 return -EFAULT;
 64         }
 65         printk("copy_from_user ok\n");
 66         printk("\t buff = %s\t\n",buff);
 67         printk("------leave testWrite------\n");
 68         return count;
 69 }
 70 
 71 struct file_operations fp_arr =
 72 {
 73         .owner = THIS_MODULE,
 74         .open = testOpen,
 75         .read = testRead,
 76         .write = testWrite,
 77         .release = testClose
 78 };
 79 
 80 int driverr_init(void)               //模块初始化函数
 81 {
 82         int res = 0;
 83         int i = 0;
 84         struct device *pDevTmp = NULL;
 85         printk("*********into driver init\n");
 86         //动态申请设备号
 87         res = alloc_chrdev_region(&deviceNum,min,devNum,deviceName);
 88         if(res)
 89         {
 90                 printk("alloc_chrdev_region error\n");
 91                 return res;
 92         }
 93         printk("alloc_chrdev_region OK!\n");
 94         printk("major = %d minor = %d \n",MAJOR(deviceNum),MINOR(deviceNum));
 95         major = MAJOR(deviceNum);
 96         //创建设备
 97         pCdev = cdev_alloc();
 98         if(NULL == pCdev)
 99         {
100                 printk("cdev_alloc error\n");
101                 unregister_chrdev_region(deviceNum,devNum);
102                 return -1;
103         }
104         printk("cdev_alloc ok\n");
105         //设备初始化
106         cdev_init(pCdev,&fp_arr);
107         printk("cdev_init ok\n");
108         //设备与设备号关联
109         res = cdev_add(pCdev,deviceNum,devNum);
110         if(res)
111         {
112                 printk("cdev_add error\n");
113                 cdev_del(pCdev);
114         }
115         printk("cdev_add ok\n");
116         //创建设备文件类
117         pClass = class_create(THIS_MODULE,"autoCreateNode");
118         if(NULL == pClass)
119         {
120                 printk("class_create error\n");
121                 cdev_del(pCdev);
122         }
123         printk("class_create ok\n");
124         //创建设备文件
125         for(;i < devNum;i++)
126         {
127                 pDevTmp = device_create(pClass,NULL,MKDEV(major,i),NULL,"autoCreateNode%d",i);
128                 if(IS_ERR(pDevTmp))
129                 {
130                         printk("device_create error\n");
131                         for(i = 0;i < devNum;i++)
132                         {
133                                 device_destroy(pClass,MKDEV(major,i));
134                         }
135                         class_destroy(pClass);
136                         return -2;
137                 }
138         }
139         printk("device_create ok\n");
140         printk("*********leave driver init\n");
141         return 0;
142 }
143 
144 void driver_clear(void)             //模块清除函数
145 {
146         int i = 0;
147         printk("*********into driver clear\n");
148         for(;i < devNum; i++)
149         {
150                 device_destroy(pClass,MKDEV(major,i));
151         }
152         class_destroy(pClass);
153         cdev_del(pCdev);
154         unregister_chrdev_region(deviceNum,devNum);
155         printk("*********leave driver clear\n");
156 }
157 
158 module_init(driverr_init);           //模块加载函数
159 module_exit(driver_clear);          //模块卸载函数
160 
161 
162 MODULE_LICENSE("GPL");
163 MODULE_AUTHOR("cfy");
164 MODULE_ALIAS("liangzai");
165 MODULE_DESCRIPTION("2022-7-11");

###测试autoCreateNode0代码
  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 
  8 #define BUF_SIZE 100
  9 
 10 int main()
 11 {
 12         int fd = open("/dev/autoCreateNode0",O_RDWR);
 13         if(fd < 0)
 14         {
 15                 printf("open autoCreateNode0 err\n");
 16                 return -1;
 17         }
 18         printf("open autoCreateNode0 ok\n");
 19 
 20         char buf[BUF_SIZE] = {0};
 21         //测试读
 22         read(fd,buf,BUF_SIZE-1);
 23         printf("read data:%s\n",buf);
 24         bzero(buf,sizeof(buf));
 25 
 26         //测试写
 27         printf(">> input:");
 28         scanf("%s",buf);
 29         write(fd,buf,sizeof(buf));
 30         bzero(buf,sizeof(buf));
 31         read(fd,buf,BUF_SIZE-1);
 32         printf("write end read data:%s\n",buf);
 33 
 34         close(fd);
 35         return 0;
 36 
 37 
 38 }
###测试autoCreateNode1代码
  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 
  8 #define BUF_SIZE 100
  9 
 10 int main()
 11 {
 12         int fd = open("/dev/autoCreateNode1",O_RDWR);
 13         if(fd < 0)
 14         {
 15                 printf("open autoCreateNode1 err\n");
 16                 return -1;
 17         }
 18         printf("open autoCreateNode1 ok\n");
 19 
 20         char buf[BUF_SIZE] = {0};
 21         //测试读
 22         read(fd,buf,BUF_SIZE-1);
 23         printf("read data:%s\n",buf);
 24         bzero(buf,sizeof(buf));
 25 
 26         //测试写
 27         printf(">> input:");
 28         scanf("%s",buf);
 29         write(fd,buf,sizeof(buf));
 30         bzero(buf,sizeof(buf));
 31         read(fd,buf,BUF_SIZE-1);
 32         printf("write end read data:%s\n",buf);
 33 
 34         close(fd);
 35         return 0;
 36 
 37 
 38 }

查看内核打印信息

在这里插入图片描述

创建设备文件类成功、创建设备文件成功,查看设备文件

在这里插入图片描述

设备文件创建成功,测试能否正常打开关闭

autoCreateNode0读写无误

在这里插入图片描述
完整内核打印信息,打开、读写、关闭,都没有问题

在这里插入图片描述

autoCreateNode1读写无误

在这里插入图片描述

所有打印信息,autoCreateNode0读写读、autoCreateNode1读写读
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值