字符设备驱动(内核态用户态内存交互)
前言
内核驱动:运行在内核态的动态模块,遵循内核模块框架接口,更倾向于插件。
应用程序:运行在用户态的进程。
应用程序与内核驱动交互通过既定接口,内核态和用户态访问依然遵循内核既定接口。
环境搭建
系统:openEuler-20.03-LTS-SP3
yum install gcc kernel-devel
编写源码
- char_module.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/device.h> //下面这三个头文件是由于动态创建需要加的
#include <linux/device.h>
#include <linux/cdev.h>MODULE_LICENSE("GPL");#define DEVICE_NAME "char_module"
#define BUF_SIZE 32static struct class *cdev_class;
dev_t dev_num = 0; // 这里是动态分配设备号和动态创建设备结点需要用到的
struct cdev dev_c;static char context_buf[BUF_SIZE]={"this a test context buffer\0"};static ssize_t read(struct file *, char *, size_t, loff_t *);
static ssize_t write(struct file *, const char *, size_t, loff_t *);
static int open(struct inode *, struct file *);
static int release(struct inode *, struct file *);// 初始化字符设备驱动的 file_operations 结构体
struct file_operations fops = {.read = read,.write = write,.open = open,.release = release
};static int __init demo_init(void)
{int ret, err;printk(KERN_INFO "%s: %s", DEVICE_NAME , __func__);// 注册设备驱动ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); // 动态分配设备号if (ret){printk("demo_init register failure\n");unregister_chrdev_region(dev_num, 1);return ret;}printk("demo_init register success\n");// 初始化设备操作cdev_init(&dev_c, &fops);err = cdev_add(&dev_c, dev_num, 1);if (err){printk(KERN_NOTICE "error %d adding cdev\n", err);unregister_chrdev_region(dev_num, 1);return err;}// 动态创建设备结点cdev_class = class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(cdev_class)){printk("ERR:cannot create a cdev_class\n");unregister_chrdev_region(dev_num, 1);return -1;}device_create(cdev_class, NULL, dev_num, 0, DEVICE_NAME);return ret;
}static void __exit demo_exit(void)
{printk(KERN_INFO "%s: %s", DEVICE_NAME , __func__);// 注销设备驱动device_destroy(cdev_class, dev_num);class_destroy(cdev_class);unregister_chrdev_region(dev_num, 1);
}static ssize_t read(struct file *filp, char *buf, size_t len, loff_t *off)
{// 内核空间到用户空间copyprintk(KERN_INFO "%s: %s", DEVICE_NAME , __func__);if (raw_copy_to_user(buf, &context_buf, sizeof(context_buf))){return -EFAULT;}printk(KERN_INFO "user space: %pF", buf);printk(KERN_INFO "read: %pF; size: %ld; data: %s", &context_buf, sizeof(context_buf), context_buf);return BUF_SIZE;
}static ssize_t write (struct file *filp, const char __user *buf, size_t len, loff_t *off)
{// 用户空间到内核空间copyprintk(KERN_INFO "%s: %s", DEVICE_NAME , __func__);if (raw_copy_from_user(&context_buf, buf, sizeof(context_buf))){return -EFAULT;}printk(KERN_INFO "user space: %pF", buf);printk(KERN_INFO "write: %pF; size: %ld; data: %s", &context_buf, sizeof(context_buf), context_buf);return BUF_SIZE;
}static int open(struct inode *inodp, struct file *filp)
{printk(KERN_INFO "%s: %s", DEVICE_NAME , __func__);return 0;
}static int release(struct inode *inodp, struct file *filp)
{printk(KERN_INFO "%s: %s", DEVICE_NAME, __func__);return 0;
}module_init(demo_init);
module_exit(demo_exit);
- Makefile
ifneq ($(KERNELRELEASE),)
obj-m := char_module.oelse
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:$(MAKE) -C $(KDIR) M=$(PWD) modules modules_install
clean:rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.*
endif
app.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define CHAR_DEV_NAME "/dev/char_module"int main()
{int ret;int fd;char buf[32];fd = open(CHAR_DEV_NAME, O_RDWR | O_NDELAY);if(fd < 0){printf("open failed!\n");return -1;}int size = read(fd, buf, 32);printf("read size: %d;\nbuffer:[%s]\n", size, buf);char *write_buf = "use a application wirte to driver buffer";int w_size = write(fd, write_buf, strlen(write_buf));printf("write size: %d;\nbuffer:[%s]\n", w_size, write_buf);close(fd);return 0;
}
构建并测试
- 驱动构建
make && insmod char_module.ko - 驱动信息确认

- 应用程序构建
gcc app.c -o app ./app - 应用程序运行结果

- 查看驱动日志
dmesg
相关文章:
字符设备驱动(内核态用户态内存交互)
前言 内核驱动:运行在内核态的动态模块,遵循内核模块框架接口,更倾向于插件。 应用程序:运行在用户态的进程。 应用程序与内核驱动交互通过既定接口,内核态和用户态访问依然遵循内核既定接口。 环境搭建 系统&#…...
Qt基础 线程池
目录 QThreadPool类 QRunnable类 应用场景示例 QThreadPool类 主要属性: 1、activeThreadCount: 此属性表示线程池中的活动线程数,通过activeThreadCount() 调用。 2、expiryTimeout: 线程活着的时间。没有设置expiryTimeout毫秒的线程会自动退出&am…...
Django(8)-静态资源引用CSS和图片
除了服务端生成的 HTML 以外,网络应用通常需要一些额外的文件——比如图片,脚本和样式表——来帮助渲染网络页面。在 Django 中,我们把这些文件统称为“静态文件”。 我们使用static文件来存放静态资源,django会在每个 INSTALLED…...
C++ list模拟实现
list模拟实现代码: namespace djx {template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x T()):_data(x),_prev(nullptr),_next(nullptr){}};template<class T,class Ref,class Pt…...
中国建筑出版传媒许少辉博士八一新书乡村振兴战略下传统村落文化旅游设计日京东当当畅销榜自由营九三学
中国建筑出版传媒许少辉博士八一新书乡村振兴战略下传统村落文化旅游设计日京东当当畅销榜自由营九三学...
C语言(第三十二天)
1. 递归是什么? 递归是学习C语言函数绕不开的一个话题,那什么是递归呢? 递归其实是一种解决问题的方法,在C语言中,递归就是函数自己调用自己。 写一个史上最简单的C语言递归代码: #include <stdio.h>…...
arcgis+postgresql+postgis使用介绍
关于arcgis在postgresql创建地理数据库我分享一下自己的经历: 众所周知,arcgis如果在oracle中创建地理数据库,必须要使用ArcToolbox里面的地理数据库工具去创建,在里面发现它还可以创建sql_server, postgresql数据库类型…...
机器视觉之开运算和闭运算
开运算(Opening)和闭运算(Closing)是数学形态学中常用的图像处理操作,通常用于去除图像中的噪声、连接物体、分离物体等操作。它们分别由两个基本操作组成:腐蚀(Erosion)和膨胀&…...
【python爬虫】—URL管理器的实现
python爬虫-url管理器 url管理器的作用python实现 url管理器的作用 在Python爬虫中,URL管理器(URL Manager)是一个重要的组件,用于有效管理爬取过程中所涉及的URL。它主要负责以下几个方面的任务: URL去重(…...
Oracle 19C RAC安装PSU oui-patch.xml权限错误
Oracle 19C RAC安装PSU时,节点2安装失败,经排查错误原因为oui-patch.xml文件权限错误。 Oracle官方建议oui-patch.xml文件权限,改成660或者666: chmod 660 oui-patch.xml权限修改完成后,安装psu还是失败,…...
华为数通方向HCIP-DataCom H12-821题库(单选题:161-180)
第161题 以下关于 URPF(Unicast Reverse Path Forwarding) 的描述, 正确的是哪一项 A、部署了严格模式的 URPF,也能够可以同时部署允许匹配缺省路由模式 B、如果部署松散模式的 URPF,默认情况下不需要匹配明细路由 C、如果部署松散模式的…...
ResNet详解:网络结构解读与PyTorch实现教程
目录 一、深度残差网络(Deep Residual Networks)简介深度学习与网络深度的挑战残差学习的提出为什么ResNet有效? 二、深度学习与梯度消失问题梯度消失问题定义为什么会出现梯度消失?激活函数初始化方法网络深度 如何解决梯度消失问…...
ChatGPT 随机动态可视化图表分析
动态可视化图表分析实例如下图: 这样的动态可视化图表可以使用ChatGPT OpenAI 来实现。 给ChatGPT发送指令: 你现在是一个数据分析师,请使用HTML,JS,Echarts,来完成一个动态条形图,条形图方向横向,数据可以随机生成,并且随机生成10个不同的商品名称,每个类别分别用…...
国标视频融合云平台EasyCVR视频汇聚平台的应用场景及其功能说明
一、平台简介 EasyCVR国标视频融合云平台是一款基于端-边-云一体化架构的视频融合AI智能分析网关平台。EasyCVR平台支持视频汇聚、融合管理,兼容多类型设备、多协议接入。其提供的视频功能包括:视频监控、无插件直播录像、云存储、检索回放、智能告警、…...
后端面试话术集锦第三篇:spring cloud 面试话术
🚗后端面试集锦目录 💖后端面试话术集锦第 1 篇:spring面试话术💖 💖后端面试话术集锦第 2 篇:spring boot面试话术💖 💖后端面试话术集锦第 3 篇:spring cloud面试话术💖 💖后端面试话术集锦第 4 篇:ElasticSearch面试话术💖 💖后端面试话术集锦第 5 …...
React 18 选择 State 结构
参考文章 选择 State 结构 构建良好的 state 可以让组件变得易于修改和调试,而不会经常出错。以下是在构建 state 时应该考虑的一些建议。 构建 state 的原则 当编写一个存有 state 的组件时,需要选择使用多少个 state 变量以及它们都是怎样的数据格…...
LNMT与动静分离
目录 一、LNMT 一、部署tomcat 二、部署nginx 三、部署mariadb 四、配置nginx 二、操作流程及步骤 一、在第一台机器上进入 vim /etc/nginx/nginx.conf 更改配置文件 二、并查看端口是否成功启动 三、验证 四、再次来到网页验证 五、动静分离(修改配置…...
【java】LinkedList 和 ArrayList的简介与对比
Java LinkedList和 ArrayList 在使用上,几乎是一样的。由于LinkedList是基于双向链表的,会多出list.getFirst();获取头部元素等方法 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按…...
机器学习基础14-算法调参(基于印第安糖尿病Pima数据集)
机器学习的模型都是参数化的,可以通过调参来提高模型的准确度。 模型有很多参数,如何找到最佳的参数组合,可以把它当作一个查询问题来处理,但是调整参数到何时为止呢?应该遵循偏差和方差协调的原则。 接下来将介绍在 s…...
ASUS华硕天选4笔记本电脑FA507XV原厂Windows11系统22H2
天选四FA507X原装系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件 华硕电脑管家、奥创控制中心等预装程序,恢复出厂状态W11 链接:https://pan.baidu.com/s/1SPoFW7wR5KawGu-yMckNzg?pwdayxd 提取码:ayxd...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
