0-ARM Linux驱动开发-字符设备

一、字符设备概述

Linux 系统中,设备被分为字符设备、块设备和网络设备等。字符设备以字节流的方式进行数据传输,数据的访问是按顺序的,一个字节一个字节地进行读取和写入操作,没有缓冲区。例如,终端(/dev/tty)、鼠标、键盘等设备都是典型的字符设备。

字符设备通过特殊的设备文件来表示。这些设备文件通常位于/dev​目录下。设备文件有主设备号(major number)和次设备号(minor number)。主设备号用于标识设备驱动程序,内核通过主设备号来查找对应的驱动程序;次设备号用于标识同一类型设备中的不同个体。例如,系统中可能有多个串口设备,它们的主设备号相同(表示使用相同的驱动程序),但次设备号不同,用于区分不同的串口。

image

image

二、字符设备驱动开发

1、驱动文件

//添加头文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ide.h>static char readbuf[100];  // 读缓冲区
static char writebuf[100]; // 写缓冲区
static char message[] = {"This message comes from kernel."};static int drive_major; //设备号
static struct class *KernelPrint_cls;//1.5.5 驱动程序的打开,读取,写入,关闭。
static int KernelPrint_open(struct inode *inode, struct file *filp) //打开函数
{//本DEMO无需申请资源,此处留白printk("-KernelPrint open-\n");return 0;
}
static ssize_t KernelPrint_read(struct file *filp, char __user *buf, size_t count, loff_t *fops) //用户读取,内核发送信息
{int flag = 0;memcpy(readbuf, message, sizeof(message)); //使用memcpy将内核中要发送的内容写入读缓冲区flag = copy_to_user(buf, readbuf, count);  //使用copy_to_user函数将读缓冲区的内容发送到用户态if (flag == 0)							   //返回0成功,否则失败{printk("Kernel send data success!\n");}else{printk("Kernel send data failed!\n");}printk("-KernelPrint read-\n");return 0;
}
static ssize_t KernelPrint_write(struct file *filp, const char __user *buf, size_t count, loff_t *fops) //用户发送,内核读取信息并打印
{int flag = 0;flag = copy_from_user(writebuf, buf, count); //使用copy_from_user读取用户态发送过来的数据if (flag == 0){printk(KERN_CRIT "Kernel receive data: %s\n", writebuf);}else{printk("Kernel receive data failed!\n");}printk("-KernelPrint write-\n");return 0;
}
static int KernelPrint_release(struct inode *inode, struct file *filp) //释放设备
{//由于open函数并没有占用什么资源,因此无需释放printk("-KernelPrint release-\n");return 0;
}//1.5.1 驱动文件描述集合
static struct file_operations drive_fops = {.owner = THIS_MODULE,.open = KernelPrint_open,.read = KernelPrint_read,.write = KernelPrint_write,.release = KernelPrint_release,
};//1.5.2 装载入口函数
static __init int KernelPrint_init(void)
{printk("-------^v^-------\n");printk("-KernelPrint init-\n");//1.5.3 设备的申请//申请主设备号//参数1----需要的主设备号,>0静态分配, ==0自动分配//参数2----设备的描述 信息,体现在cat /proc/devices, 一般自定义//参数3----文件描述集合//返回值,小于0报错drive_major = register_chrdev(0, "KernelPrint", &drive_fops);if (drive_major < 0) //判断是否申请成功{printk("register chrdev faile!\n");return drive_major;}else{printk("register chrdev ok!\n");}//1.5.4 //自动创建设备节点//创建设备的类别//参数1----设备的拥有者,当前模块,直接填THIS_MODULE//参数2----设备类别的名字,自定义//返回值:类别结构体指针,其实就是分配了一个结构体空间KernelPrint_cls = class_create(THIS_MODULE, "KernelPrint_class");printk("class create ok!\n");//创建设备//参数1----设备对应的类别//参数2----当前设备的父类,直接填NULL//参数3----设备节点关联的设备号//参数4----私有数据直接填NULL//参数5----设备节点的名字device_create(KernelPrint_cls, NULL, MKDEV(drive_major, 0), NULL, "KernelPrint_%d", 0);printk("device create ok!\n");return 0;
}//1.5.2 卸载入口函数
static __exit void KernelPrint_exit(void)
{//1.5.3 设备的注销device_destroy(KernelPrint_cls, MKDEV(drive_major, 0)); //删除设备class_destroy(KernelPrint_cls);							//删除类unregister_chrdev(drive_major, "KernelPrint");			//注销主设备号printk("-------^v^-------\n");printk("-KernelPrint exit-\n");
}//申明装载入口函数和卸载入口函数
module_init(KernelPrint_init);
module_exit(KernelPrint_exit);//添加各类信息
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Popeye");

2、应用文件

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char *argv[])
{int fd, retvalue;char *filename;char readbuf[100], writebuf[100];filename = argv[1];fd = open(filename, O_RDWR); //打开设备if (fd < 0){printf("Can't open file %s\n", filename);return -1;}switch (*argv[2]) //对操作数进行解析{case 'r':if (argc != 3) //进行鲁棒性检查{printf("Unknow operation, use the formate: ./APPNAME /dev/DRIVENAME r to read date from kernel.\n");return -1;}retvalue = read(fd, readbuf, 100);if (retvalue < 0) //检查是否读取成功{printf("Read file %s failed!\n", filename);}else{printf("User receive data: %s\n", readbuf);}break;case 'w':if (argc != 4) //进行鲁棒性检查{printf("Unknow operation, use the formate: ./APPNAME /dev/DRIVENAME w \"USERDATE\" to write date to kernel.\n");return -2;}memcpy(writebuf, argv[3], strlen(argv[3])); //将内容拷贝到缓冲区retvalue = write(fd, writebuf, 50);			//写数据if (retvalue < 0){printf("Write file %s failed!\n", filename);}else{printf("Write file success!\n");}break;default:printf("Unknow Operation: %d\n", *argv[2]);break;}retvalue = close(fd); //关闭设备if (retvalue < 0){printf("Can't close file %s\n", filename);return -1;}return 0;
}

三、上板验证

安装驱动insmod kernel_print.ko​,查看驱动安装是否成功ls /dev/​,kernel_print内核打印测试./kernel_print_app /dev/KernelPrint_0 w "Popeye"

image

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/463588.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openGauss数据库-头歌实验1-4 数据库及表的创建

一、创建数据库 &#xff08;一&#xff09;任务描述 本关任务&#xff1a;创建指定数据库。 &#xff08;二&#xff09;相关知识 数据库其实就是可以存放大量数据的仓库&#xff0c;学习数据库我们就从创建一个数据库开始吧。 为了完成本关任务&#xff0c;你需要掌握&a…

深入浅出 Spring Boot 与 Shiro:构建安全认证与权限管理框架

一、Shiro框架概念 &#xff08;一&#xff09;Shiro框架概念 1.概念&#xff1a; Shiro是apache旗下一个开源安全框架&#xff0c;它对软件系统中的安全认证相关功能进行了封装&#xff0c;实现了用户身份认证&#xff0c;权限授权、加密、会话管理等功能&#xff0c;组成一…

重学SpringBoot3-整合 Elasticsearch 8.x (一)客户端方式

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 这里写目录标题 1. 为什么选择 Elasticsearch&#xff1f;2. Spring Boot 3 和 Elasticsearch 8.x 的集成概述2.1 准备工作2.2 添加依赖 3. Elasticsearch 客户端配置方式…

MyBaitsPlus 基本用法简单整理

MyBaitsPlus 基本用法整理 查询单表查询查询单条数据写法一&#xff1a;&#xff08;this.getOne&#xff09;写法二&#xff1a;&#xff08;XxxMapper.selectById&#xff09;写法三&#xff1a;&#xff08;this.getById&#xff09; 查询 list 集合&#xff08;this.list&a…

基于MATLAB的战术手势识别

手势识别的研究起步于20世纪末&#xff0c;由于计算机技术的发展&#xff0c;特别是近年来虚拟现实技术的发展&#xff0c;手势识别的研究也到达一个新的高度。熵分析法是韩国的李金石、李振恩等人通过从背景复杂的视频数据中分割出人的手势形状&#xff0c;然后计算手型的质心…

Mac 配置SourceTree集成云效

1、背景 工作使用的是自己的笔记本&#xff0c;一个是比较卡&#xff0c;在一个是敏感信息比较多还是使用公司的电脑&#xff0c;但是系统是Mac就很麻烦&#xff0c;在网上找了帖子记录一下 2、配置 打开终端 ssh-keygen -t rsa #一直回车就行 cd .ssh cat id_rsa.pub #查…

【快速上手】pyspark 集群环境下的搭建(Yarn模式)

目录 前言&#xff1a; 一、安装步骤 安装前准备 1.第一步&#xff1a;安装python 2.第二步&#xff1a;在bigdata01上安装spark 3.第三步&#xff1a;同步bigdata01中的spark到bigdata02和03上 二、启动 三、可打开yarn界面查看任务 前言&#xff1a; 上一篇介绍的是…

使用Python多线程抓取某图网数据并下载图片

前言 在互联网开发领域&#xff0c;数据抓取是一项非常实用的技术。通过数据抓取&#xff0c;我们可以从网页上获取所需的信息&#xff0c;并将其转化为结构化数据&#xff0c;以便进一步分析或使用。本文将介绍如何利用Python编写一个多线程程序来抓取网页上的图片数据&#…

《IMM交互式多模型滤波MATLAB实践》专栏目录,持续更新……

专栏链接&#xff1a;https://blog.csdn.net/callmeup/category_12816762.html 专栏介绍 关于IMM的例程 双模型EKF&#xff1a; 【逐行注释】基于CV/CT模型的IMM|MATLAB程序|源代码复制后即可运行&#xff0c;无需下载三模型EKF&#xff1a; 【matlab代码】3个模型的IMM例程&…

鸿蒙开发案例:指南针

【1】引言&#xff08;完整代码在最后面&#xff09; 在本文中&#xff0c;我们将介绍如何使用鸿蒙系统&#xff08;HarmonyOS&#xff09;开发一个简单的指南针应用。通过这个案例&#xff0c;你可以学习如何使用传感器服务、状态管理以及UI构建等基本技能。 【2】环境准备 …

人工智能的发展与未来:从Yann LeCun的观点谈起

引言 在当今的人工智能&#xff08;AI&#xff09;领域&#xff0c;AGI&#xff08;通用人工智能&#xff09;已成为热门话题。许多专家认为&#xff0c;随着技术的不断发展&#xff0c;AGI的实现只是时间问题。然而&#xff0c;Yann LeCun——图灵奖得主、Meta首席AI科学家&a…

【The Art of Unit Testing 3_自学笔记06】3.4 + 3.5 单元测试核心技能之:函数式注入与模块化注入的解决方案简介

文章目录 3.4 函数式依赖注入技术 Functional injection techniques3.5 模块化依赖注入技术 Modular injection techniques 写在前面 上一篇的最后部分对第三章后续内容做了一个概括性的梳理&#xff0c;并给出了断开依赖项的最简单的实现方案&#xff0c;函数参数值注入法。本…

电磁兼容(EMC):整改案例(六)Y电容过大导致雷击浪涌炸机

目录 1. 异常现象 2. 原因分析 3. 整改方案 4. 总结 1. 异常现象 某金属外壳带接地线的产品按GB/T 17626.5进行雷击浪涌测试&#xff0c;在L&#xff0c;N线对PE进行4kV浪涌电压测试时&#xff0c;出现炸机现象&#xff0c;AC-DC电源芯片损坏。而在L&#xff0c;N线间进行2…

代码之眼,陈欣的xml解密之路

第一章 在未来的世界里&#xff0c;科技已经发展到了令人难以想象的地步。人工智能、量子计算和生物技术交织在一起&#xff0c;创造了一个全新的社会形态。在这个世界中&#xff0c;有一个名为“代码守护者”的组织&#xff0c;专门负责维护全球信息系统的安全和稳定。 陈欣是…

L0G1000:Linux+InternStudio 闯关作业

1. 配置基础环境 首先&#xff0c;打开 Intern Studio 界面&#xff0c;点击 创建开发机 配置开发机系统。 InternStudio 填写 开发机名称 后&#xff0c;点击 选择镜像 使用 Cuda11.7-conda 镜像&#xff0c;然后在资源配置中&#xff0c;使用 10% A100 * 1 的选项&#xff…

爬虫笔记22——当当网图书详情页静、动态数据爬取

当当网动态数据爬取 静态数据爬取动态数据爬取接口参数的获取 静态数据爬取 进入图书详情&#xff0c;这里的图书数据信息比如标题、价格、图片都是非结构化数据&#xff0c;可以使用xpath语法提取。是很简单的数据采集了&#xff0c;就不细说了。 动态数据爬取 滑到下面这里的…

使用pathview在线渲染KEGG Pathway Map,给感兴趣的基因、化合物添加颜色

导读&#xff1a; 通过将用户提供的基因表达定量数据&#xff0c;化合物定量数据映射并渲染到相关的KEGG通路图上&#xff0c;能够帮助我们直观且系统地研究基因、酶、化合物间的关系。 KEGG通路图简介 KEGG PATHWAY数据库是一系列手动绘制的图形图谱的集合&#xff0c;称为…

自动化测试工具Ranorex Studio(二十一)-适配一个已存在的对象库

通过录制一个手工测试场景我们创建了一个对象库。录制期间用到的每个UI元素都在库中创建了一个新的条目。默认情况下&#xff0c;一个新的Ranorex Studio项目包含一个库文件(*.rxrep)&#xff0c;这个文件可以被多个录制模块或代码模块使用。 图&#xff1a;一个库的文件视图…

OpenSLL下载,环境变量配置

https://slproweb.com/products/Win32OpenSSL.html 环境变量 新建一个path为安装选择的目录的bin路径

【MyBatis】【基于轻量型架构的WEB开发】课程 课后习题 章节测试

mybatis关联查询、缓存、注解 一. 单选题 1. 下列关于 <collection> 元素的描述正确的是&#xff08;&#xff09;。 A. MyBatis 就是通过 <collection> 元素来处理一对多关联关系的 B. <collection> 元素的属性与 <association> 元素完全相同 C.…