泰山派3M-RK3576-Linux内核驱动教程-Linux驱动基础-字符驱动设备-应用程序访问字符设备
06.应用程序访问字符设备在上一个章节中我们编写了一个驱动程序这里我们要编写一个APP应用程序实现在应用层调用驱动底层的open和write函数。一、APP和驱动程序的区别与分工1. 驱动程序Driver工作在内核空间是操作系统和硬件之间的桥梁。直接控制硬件、管理硬件资源对上层如APP屏蔽硬件细节。只能通过内核API与其他内核部分通信一般不能直接和用户交互。典型功能收发数据、寄存器读写、中断处理等。例子你之前写的chrdev_test字符设备驱动。2. 应用程序APP工作在用户空间直接与用户交互。调用系统调用如 open、read、write、close来间接访问硬件真正操作硬件时请求会流转到驱动程序。负责编写界面、业务逻辑而不是底层硬件细节。例子你即将写的测试程序调用/dev/device_test完成 open 和 write。分工理解应用程序像“司机”提出“我要开车open、加油write、看仪表盘read”这种需求。驱动程序像“发动机技术员”根据指令完成车的具体操作但不关心是谁让它做的。二、APP的编写1、c源码APP应用使用的是标准的C库就是和我们之前刚学习C语言的时候用的一个风格。在05_char_device/文件夹下创建一个test_chrdev_app.c文件编写下面的代码#include stdio.h #include fcntl.h #include unistd.h #include string.h int main() { int fd; const char *devname /dev/device_test; const char *data hello, driver!; // 1. 打开设备 fd open(devname, O_WRONLY); if(fd 0) { printf(test_chrdev_app: open device failed.\n); return -1; } printf(test_chrdev_app: Device opened successfully.\n); // 2. 写数据到驱动 int ret write(fd, data, strlen(data)); if(ret 0) { printf(test_chrdev_app: write device failed.\n); close(fd); return -1; } printf(test_chrdev_app: Device write successfully.\n); // 3. 关闭设备 close(fd); printf(test_chrdev_app: Device closed.\n); return 0; }2、源码讲解这个应用程序负责 “打开” 在/dev/下挂载好的device_test字符设备并尝试将一串数据hello, driver!写入设备。它不会直接操作硬件也无法直接调用内核代码只能通过标准的系统调用间接与设备驱动交互。int main() { int fd; const char *devname /dev/device_test; const char *data hello, driver!;主函数开始。fd文件描述符存放open()的返回值。devname指定要访问的设备节点路径和前面驱动创建的/dev/device_test保持一致。data要写入到设备的数据字符串。// 1. 打开设备 fd open(devname, O_WRONLY); if(fd 0) { printf(test_chrdev_app: open device failed.\n); return -1; } printf(test_chrdev_app: Device opened successfully.\n);使用系统调用open打开设备文件第二个参数O_WRONLY表明只写模式。如果返回值 0说明打开失败比如没有驱动、节点不存在、无权限此时打印错误并退出。成功则打印“打开成功”。原理说明用户空间的open()其实会被内核转换成对/dev/device_test这个设备节点的操作。内核通过设备号查表定位到对应的驱动并最终调用你写的驱动函数chrdev_open。// 2. 写数据到驱动 int ret write(fd, data, strlen(data)); if(ret 0) { printf(test_chrdev_app: write device failed.\n); close(fd); return -1; } printf(test_chrdev_app: Device write successfully.\n);调用write()向打开的设备文件写入数据返回值是实际写入的字节数0则是错误。如果失败如驱动没有实现write、权限问题等则报错并提前关闭文件退出。成功则提示“写入成功”。原理说明这里的write()会被内核拦截通过设备号查找你的驱动最终会调用驱动代码中的chrdev_write()。实测时你可通过dmesg查看驱动日志信息验证两者的调用关系。// 3. 关闭设备 close(fd); printf(test_chrdev_app: Device closed.\n); return 0;用标准close()释放之前打开的文件描述符。关闭后会触发驱动的chrdev_release()如果有实现。最后返回0表示程序顺利结束。三、APP编译使用下面的命令进行编译/home/lckfb/TaishanPi-3-Linux/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc test_chrdev_app.c -o test_chrdev_app命令格式是SDK的gcc交叉编译器 源码.c文件 -o 最终生成的可执行文件名字-o重名的意思后面紧跟着最终想要生成的名字。SDK的gcc交叉编译器这个就和之前我们在Makefile中编写的路径一致只不过变为了aarch64-none-linux-gnu-gcc不单单是只有前缀了。最终就是这样的四、测试将这个test_chrdev_app复制到开发板中U盘、TF卡、SSH都可以并运行sudo ./test_chrdev_app最终的效果是这样的APP程序依次运行了open、write和close这三个函数操作而我们的驱动也相应的做出了三个一样的动作openwriterelease所以我们在APP的调用中通过/dev/device_test这个设备实现了APP的open、write和close三个函数和驱动的三个openwriterelease函数的对应调用。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2596525.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!