ARM Linux 驱动开发篇----字符设备驱动开发(5)--- 编写测试chrdevbase 字符设备驱动开发APP程序--- Ubuntu20.04

🎬 渡水无言个人主页渡水无言

专栏传送门linux专栏

⭐️流水不争先,争的是滔滔不绝

目录

前言

[一、C 库文件操作基本函数](#一、C 库文件操作基本函数)

[1.1、open 函数](#1.1、open 函数)

[1.2read 函数](#1.2read 函数)

[1.3write 函数](#1.3write 函数)

[1.4、close 函数](#1.4、close 函数)

[二、编写测试 APP 程序](#二、编写测试 APP 程序)

[三、编译驱动程序和测试 APP](#三、编译驱动程序和测试 APP)

1、编译驱动程序

[2、编译测试 APP](#2、编译测试 APP)

总结


前言

上一期博客我们编写完成了chrdevbase 字符设备驱动开发实验的代码,这一期博客,我们开始编写测试 APP的代码。


一、C库文件操作基本函数

编写测试 APP 就是编写 Linux 应用,需要用到 C 库里面和文件操作有关的一些函数,比如open、read、write 和 close 这四个函数。

1.1、open函数

open 函数原型如下:

复制代码
int open(const char *pathname, int flags)

open 函数参数含义如下:

pathname:要打开的设备或者文件名。

flags**:**文件打开模式,以下三种模式必选其一:

O_RDONLY 只读模式

O_WRONLY 只写模式

O_RDWR 读写模式

因为我们要对 chrdevbase 这个设备进行读写操作,所以选择 O_RDWR。除了上述三种模式以外还有其他的可选模式,通过逻辑或来选择多种模式

返回值:如果文件打开成功的话返回文件的文件描述符。
在 Ubuntu 中输入" man 2 open "即可查看 open 函数的详细内容,如下图 所示:

1.2read****函数

read 函数原型如下:

复制代码
ssize_t read(int fd, void *buf, size_t count)

read 函数参数含义如下:

fd:要读取的文件描述符,读取文件之前要先用 open 函数打开文件,open 函数打开文件成

功以后会得到文件描述符。

buf**:**数据读取到此 buf 中。

count**:**要读取的数据长度,也就是字节数。

**返回值:**读取成功的话返回读取到的字节数;如果返回 0 表示读取到了文件末尾;如果返回负值,表示读取失败。在 Ubuntu 中输入"man 2 read"命令即可查看 read 函数的详细内容。

1.3write****函数

write 函数原型如下:

复制代码
ssize_t write(int fd, const void *buf, size_t count);

write 函数参数含义如下:

fd:要进行写操作的文件描述符,写文件之前要先用 open 函数打开文件,open 函数打开文

件成功以后会得到文件描述符。

buf**:**要写入的数据。

count**:**要写入的数据长度,也就是字节数。

**返回值:**写入成功的话返回写入的字节数;如果返回 0 表示没有写入任何数据;如果返回

负值,表示写入失败。在 Ubuntu 中输入"man 2 write"命令即可查看 write 函数的详细内容。

1.4、close****函数

close 函数原型如下:

int close(int fd);

close 函数参数含义如下:

fd:要关闭的文件描述符。

**返回值:**0 表示关闭成功,负值表示关闭失败。在 Ubuntu 中输入"man 2 close"命令即可

查看 close 函数的详细内容。

二、编写测试APP程序

驱动编写好以后是需要测试的,一般编写一个简单的测试 APP,测试 APP 运行在用户空

间。测试 APP 很简单通过输入相应的指令来对 chrdevbase 设备执行读或者写操作。在 1_chrdevbase 目录中新建 chrdevbaseApp.c 文件,在此文件中输入如下内容:

复制代码
1  #include "stdio.h"
2  #include "unistd.h"
3  #include "sys/types.h"
4  #include "sys/stat.h"
5  #include "fcntl.h"
6  #include "stdlib.h"
7  #include "string.h"
8  
9  /********************************************
11 文件名     : chrdevbaseApp.c
13 版本       : V1.0
14 描述       : chrdevbase 驱动测试APP。
15 其他       : 使用方法: ./chrdevbaseApp /dev/chrdevbase <1>|<2>
16 ********************************************/
17  
18 static char usrdata[] = {"usr data!"};
19  
20 /*
21  * @description : main 主程序
22  * @param - argc : argv 数组元素个数
23  * @param - argv : 具体参数
24  * @return      : 0 成功;其他 失败
25  */
26 int main(int argc, char *argv[])
27 {
28     int fd, retval;
29     char readbuf[100], writebuf[100];
30     static char usrdata[] = {"usr data!"};
31  
32     if(argc != 3){
33         printf("Error Usage!\r\n");
34         return -1;
35     }
36  
37     char *filename = argv[1];
38  
39     /* 打开驱动文件 */
40     fd = open(filename, O_RDWR);
41     if(fd < 0){
42         printf("Can't open file %s\r\n", filename);
43         return -1;
44     }
45  
46     if(atoi(argv[2]) == 1){ /* 从驱动文件读取数据 */
47         retval = read(fd, readbuf, 50);
48         if(retval < 0){
49             printf("read file %s failed!\r\n", filename);
50         }else{
51             /* 读取成功,打印出读取成功的数据 */
52             printf("read data:%s\r\n",readbuf);
53         }
54     }
55  
56     if(atoi(argv[2]) == 2){ /* 向设备驱动写数据 */
57         memcpy(writebuf, usrdata, sizeof(usrdata));
58         retval = write(fd, writebuf, 50);
59         if(retval < 0){
60             printf("write file %s failed!\r\n", filename);
61         }
62     }
63  
64     /* 关闭设备 */
65     retval = close(fd);
66     if(retval < 0){
67         printf("Can't close file %s\r\n", filename);
68         return -1;
69     }
70  
71     return 0;
72 }

第 18 行,数组 usrdata 是测试 APP 要向 chrdevbase 设备写入的数据。

第 32行,判断运行测试 APP 的时候输入的参数是不是为 3 个,main 函数的 argc 参数表示参数数量,argv[]保存着具体的参数,如果参数不为 3 个的话就表示测试 APP 用法错误。比如,现在要从 chrdevbase 设备中读取数据,需要输入如下命令:

复制代码
./chrdevbaseApp /dev/chrdevbase 1

上述命令一共有三个参数"./chrdevbaseApp"、"/dev/chrdevbase"和"1",这三个参数分别

对应 argv[0]、argv[1]和 argv[2]。第一个参数表示运行 chrdevbaseAPP 这个软件,第二个参数表

示测试APP要打开/dev/chrdevbase这个设备。第三个参数就是要执行的操作,1表示从chrdevbase

中读取数据,2 表示向 chrdevbase 写数据。

第 37行,获取要打开的设备文件名字,argv[1]保存着设备名字。

第 40行,调用 C 库中的 open 函数打开设备文件:/dev/chrdevbase。

第 46行,判断 argv[2]参数的值是 1 还是 2,因为输入命令的时候其参数都是字符串格式的,因此需要借助 atoi 函数将字符串格式的数字转换为真实的数字。

第 47 行,当 argv[2]为 1 的时候表示要从 chrdevbase 设备中读取数据,一共读取 50 字节的数据,读取到的数据保存在 readbuf 中,读取成功以后就在终端上打印出读取到的数据。

第 56 行,当 argv[2]为 2 的时候表示要向 chrdevbase 设备写数据。

第 65 行,对 chrdevbase 设备操作完成以后就关闭设备。

chrdevbaseApp.c 内容还是很简单的,就是最普通的文件打开、关闭和读写操作。

三、编译驱动程序和测试****APP

1**、编译驱动程序**

首先编译驱动程序,也就是 chrdevbase.c 这个文件,我们需要将其编译为.ko 模块,创建 Makefile 文件,然后在其中输入如下内容:

复制代码
1 KERNELDIR := /home/duan/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
2 CURRENT_PATH := $(shell pwd)
3 obj-m := chrdevbase.o
4 
5 build: kernel_modules
6 
7 kernel_modules:
8 	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
9 clean:
10 	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

第 1 行,KERNELDIR 表示开发板所使用的 Linux 内核源码目录,使用绝对路径(需要自己修改)。

第 2 行,CURRENT_PATH 表示当前路径,直接通过运行"pwd"命令来获取当前所处路径。

第 3 行,obj-m 表示将 chrdevbase.c 这个文件编译为 chrdevbase.ko 模块。

第 8 行,具体的编译命令,后面的 modules 表示编译模块,-C 表示将当前的工作目录切

换到指定目录中,也就是 KERNERLDIR 目录。M 表示模块源码目录,"make modules"命令

中加入 M=dir 以后程序会自动到指定的 dir 目录中读取模块的源码并将其编译为.ko 文件。

Makefile 编写好以后输入"make"命令编译驱动模块,编译过程如图 所示:

编译成功以后就会生成一个叫做 chrdevbaes.ko 的文件,此文件就是 chrdevbase 设备的驱动

模块。至此,chrdevbase 设备的驱动就编译成功。

2**、编译测试****APP**

测试 APP 比较简单,只有一个文件,因此就不需要编写 Makefile 了,直接输入命令编译。

因为测试 APP 是要在 ARM 开发板上运行的,所以需要使用 arm-linux-gnueabihf-gcc 来编译,

输入如下命令:

复制代码
arm-linux-gnueabihf-gcc chrdevbaseApp.c -o chrdevbaseApp

编译完成以后会生成一个叫做 chrdevbaseApp 的可执行程序,输入如下命令查看

复制代码
chrdevbaseAPP 

结果如下图所示:


总结

相关推荐
小白同学_C8 小时前
Lab4-Lab: traps && MIT6.1810操作系统工程【持续更新】 _
linux·c/c++·操作系统os
今天只学一颗糖8 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
2601_949146539 小时前
Shell语音通知接口使用指南:运维自动化中的语音告警集成方案
运维·自动化
儒雅的晴天9 小时前
大模型幻觉问题
运维·服务器
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
通信大师10 小时前
深度解析PCC策略计费控制:核心网产品与应用价值
运维·服务器·网络·5g
dixiuapp10 小时前
智能工单系统如何选,实现自动化与预测性维护
运维·自动化
不做无法实现的梦~10 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
Elastic 中国社区官方博客10 小时前
如何防御你的 RAG 系统免受上下文投毒攻击
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索
小锋学长生活大爆炸10 小时前
【教程】免Root在Termux上安装Docker
运维·docker·容器