Windows驱动开发(三)—— 驱动和应用层通信的几种方式

目的

在Windows系统中,驱动程序想要正常工作,往往离不开和用户态进程间的交互。因此,驱动和用户态进程的通信就成为了必不可少的手段。

方式

1. 进程间通信

由于Windows 操作系统中,内核线程运行于某个进程的地址空间中。因此,内核线程和用户进程的通信可以通过进程间通信的方式实现,例如文件映射、共享内存、管道等方式。这里就不一一展开了。

2. I/O请求

通过实现IRP_MJ_READIRP_MJ_WRITE的请求,用户态进程直接通过设备读写的方式与驱动程序通信。

// 应用层读写事件
HANDLE hDevice = ::CreateFile(DRIVER_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (FALSE == ReadFile(hDevice, buffer, sizeof(buffer), &dwOutput, NULL)) {if (GetLastError() == ERROR_IO_PENDING) {WaitForSingleObject(hDevice, INFINITE);}
}
WriteFile(hDevice, buffer, sizeof(buffer), &dwOutput, NULL);
CloseHandle(hDevice);

驱动程序在接收到IRP时,根据具体需求选择直接返回数据;或者通过IoMarkIrpPending设置挂起状态,异步处理请求。

// 异步IRP处理
VOID ThreadProc(PVOID StartContext)
{PIRP pIrp = (PIRP)StartContext;pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;IoCompleteRequest(pIrp, IO_NO_INCREMENT);PsTerminateSystemThread(STATUS_SUCCESS);
}// 挂起IRP
PsCreateSystemThread(&hThread, 0, NULL, NtCurrentProcess(), NULL, ThreadProc, pIrp);
IoMarkIrpPending(pIrp);
pIrp->IoStatus.Status = STATUS_PENDING;
return STATUS_PENDING;
3. I/O 控制

通过调用DeviceIoControl发送设备控制代码,等待驱动层返回。
从本质上来说,这种方式与通过IRP_MJ_READIRP_MJ_WRITE类似,都是通过封装IRP来实现。
但是,DeviceIoControl允许用户自定义设备控制代码,使用上更加灵活。

// 定义设备控制代码
#define IOCTL_HELLOWORLD_TEST CTL_CODE(0x8000, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
// 执行设备控制
DeviceIoControl(hDevice, IOCTL_HELLOWORLD_TEST, buffer, sizeof(buffer), buffer, sizeof(buffer), &dwOutput, NULL);
4. MiniFilter通信服务端口

在微软的文件过滤器框架MiniFilter中,提供了一种独立的通信方式——CommunicationPort

// 驱动
// 创建通信端口
FltCreateCommunicationPort(pFilter, &pServerPort, &oa, NULL, ConnectNotifyCb, DisconnectNotifyCb, MessageNotifyCb, 1);
// 发送消息
FltSendMessage(pFilter, &pClientPort,inbuffer, inlength, outbuffer, outlength, &liTimeout);
// 接收消息回调
NTSTATUS MessageNotifyCb(PVOID PortCookie,PVOID InputBuffer,ULONG InputBufferLength,PVOID OutputBuffer,ULONG OutputBufferLength,PULONG ReturnOutputBufferLength
)
{...}
// 关闭客户端连接
FltCloseClientPort(pFilter, &pClientPort);
// 关闭端口
FltCloseCommunicationPort(pServerPort);// 应用态
// 连接通信端口
FilterConnectCommunicationPort(c_sPortName, 0, NULL, 0, NULL, &m_pConnectionPort);
// 接收消息
FilterGetMessage(m_pConnectionPort,lpMessageBuffer, dwMessageBufferSize, NULL);
// 回复消息
FilterReplyMessage(m_pConnectionPort, lpReplyBuffer, dwReplyBufferSize);
// 发送消息
FilterSendMessage(m_pConnectionPort, inbuffer, inlength, outbuffer, outlength, &outlength);
5. 本地过程调用(LPC, Local Procedure Call)

LPC 是 Windows 中的一种轻量级的进程间通信机制,允许在同一台计算机上的不同进程之间进行高效的消息传递。它主要用于用户模式与内核模式之间的交互。
由于LPC是Windows系统内部使用的一种通信机制,微软没有提供任何的公开文档,因此在实际使用中可能存在一定风险。
但是,相比于其他方式而言,LPC可以从驱动连接应用层创建的通信端口,使用上更为灵活。

// 服务端
// 创建端口
ZwCreatePort(&hPort, &objectAttributes, sizeof(PORT_MESSAGE), MAX_LPC_MESSAGE_LENGTH, 0);
// 等待客户端连接
ZwReplyWaitReceivePort(hPort, &lpc_client, NULL, (PPORT_MESSAGE)pRequest);
// 接收客户端连接
ZwAcceptConnectPort(&hConnectionPort, NULL,(PPORT_MESSAGE)pRequest, TRUE, &ServerView, &ClientView);
// 完成客户端连接
ZwCompleteConnectPort(hConnectionPort);
// 响应消息
ZwReplyPort(hConnectionPort, (PPORT_MESSAGE)replyBuffer);
// 关闭端口
ZwClose(hConnectionPort);
ZwClose(hPort);// 客户端
// 连接端口
ZwConnectPort(&hConnectionPort, &LpcPortName, &sqos, &ClientView, &ServerView, (PULONG)&MaxMessageLength, NULL,NULL);
// 发送消息等待响应
ZwRequestWaitReplyPort(hConnectionPort, (PPORT_MESSAGE)pRequest, (PPORT_MESSAGE)pResponse);
// 关闭端口
ZwClose(hConnectionPort);

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

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

相关文章

初学者指南:软件测试

目录 初学者软件开发流程中的测试指南一、什么是软件测试?二、软件测试的重要性三、软件测试的类型四、软件测试的流程五、软件测试工具六、软件测试工程师的技能要求七、如何上手软件测试八、结语 初学者软件开发流程中的测试指南 欢迎来到软件测试的世界&#xf…

公司章程拟定,定制公司章程

公司章程是指公司依法制定的、规定公司名称、住所、经营范围、经营管理制度等重大事项的基本文件,也是公司必要的规定公司组织及活动基本规则的书面文件。公司章程是股东共同一致的意思表示,载明了公司组织和活动的基本准则,是公司的宪章。关…

基于HEC-Ras及ArcGIS的泥石流数值模拟与灾害风险评估典型案例

泥石流是一种破坏性极强的自然灾害,对人类社会和自然环境都构成了巨大的威胁。由于泥石流的发生通常突然且难以预测,因此,采取有效的预防措施和进行科学的风险评估显得尤为重要。为了减少泥石流可能带来的损害,可以建立高效的监测…

LVGL第二篇-组件创建与显示(以slider为例)

一、LVGL 中组件加载步骤 分配内存与初始化: 首先,通过调用相应组件的创建函数来分配内存并初始化组件对象。例如,若要创建一个按钮组件,可使用lv_XXX_create函数。这些创建函数会返回一个指向新创建组件对象(lv_obj_t…

百度文心一言接入流程-java版

百度文心一言接入流程-java版 一、准备工作二、API接口调用-java三、百度Prompt工程参考资料: 百度文心一言:https://yiyan.baidu.com/百度千帆大模型:https://qianfan.cloud.baidu.com/百度千帆大模型文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/index.html千tokens…

Modbus TCP报错:Response length is only 0 bytes

问题描述: 使用modbus_tk库,通过Modbus tcp连接PLC时,python中的一个报错信息: Response length is only 0 bytes报错原因: 与Modbus TCP 服务端建立连接后没有断开,继续作为长连接使用,客户端…

时序数据库 TDengine 支持集成开源的物联网平台 ThingsBoard

Thingsboard 中“设备配置”和“设备”的关系是一对多的关系,通过设备配置为每个设备设置不同的配置,每个设备都会有一个与其关联的设备配置文件。等等,这不就是TDengine 中超级表的概念: 超级表是一种特殊的表结构,用…

Unity3D学习FPS游戏(4)重力模拟和角色跳跃

前言:前面两篇文章,已经实现了角色的移动和视角转动,但是角色并没有办法跳跃,有时候还会随着视角移动跑到天上。这是因为缺少重力系统,本篇将实现重力和角色跳跃功能。觉得有帮助的话可以点赞收藏支持一下!…

Spring Cloud:构建高可用分布式系统的利器

摘要:本文将介绍Spring Cloud,一个基于Spring Boot的开源微服务架构工具集。我们将探讨Spring Cloud的核心组件、特性以及如何使用Spring Cloud构建高可用、分布式系统。通过本文,读者将了解到Spring Cloud在实现微服务架构中的应用和优势。 …

ResNet-RS 乳腺癌识别

一、模型结构 1.1 模型思路 ResNet-RS是一种改进的ResNet架构,它在2021年由谷歌大脑和UC Berkeley的研究者们提出。ResNet-RS的提出基于对现有ResNet架构的深入研究,研究者们重新审视了ResNet的结构、训练方法以及缩放策略,并提出了一些改进…

git入门操作(2)

文章目录 git入门操作(2)git diff 查看差异git diff gitignore忽略文件1.在代码仓库创建这个文件2.添加对 log 文件过滤 连接远程仓库与ssh配置远程仓库和本地仓库关联步骤分支基本操作步骤命令: 合并冲突分支合并逻辑1.新建分支 dev&#xf…

MySQL查看当前客户端连接数的方法

每当有客户端连接到 MySQL 时,MySQL 会为该连接创建一个新的线程来处理所有与该连接相关的查询和操作。所以通过查看MySQL当前的连接线程数量就可以知道有多少客户端连接到MySQL。 方法一 Threads_connected 仅显示活跃的客户端连接数 SHOW STATUS LIKE Threads_…

H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)

LUA脚本的好处是用户可以根据自己注册的一批API(当前TOOL已经提供了几百个函数供大家使用),实现各种小程序,不再限制Flash里面已经下载的程序,就跟手机安装APP差不多,所以在H7-TOOL里面被广泛使用&#xff…

Go语言中三个输入函数(scanf,scan,scanln)的区别

Go语言中三个输入函数(scanf,scan,scanln)的区别 在 Go 语言中,fmt 包提供了三种输入函数:Scanf、Scan 和 Scanln。这三个函数都是用于从标准输入读取数据并存储到变量中,但是它们在处理输入的方式上有所不同。下面详细解读每个函数的特点和…

网站被浏览器提示“不安全”,如何快速解决

当网站被浏览器提示“不安全”时,这通常意味着网站存在某些安全隐患,需要立即采取措施进行解决。 一、具体原因如下: 1.如果网站使用的是HTTP协议,应立即升级HTTPS。HTTPS通过使用SSL证书加密来保护数据传输,提高了网…

CSS设置层叠样式时报红(identifier expected css/selector expected css)

不规范语法 如上图所示,在一个 css 文件中添加层叠样式时报红:at-rule or selector expected,意思就是说我们的语句不符合 css 的语法书写规范,虽然不会导致启动报错并且还能达到预期的样式效果,但是对于有强迫症的同学…

养狗为什么需要宠物空气净化器?宠物空气净化器排行榜公布!

刚开始养狗时候怎么没人跟我说要买宠物空气净化器呢?那时候什么都不懂,只买了狗粮、喂食碗、狗笼、狗窝、便盆、牵引绳以及一些狗狗玩具。结果一个星期就家里就被搞得狗毛乱飞、臭味熏天。最后在养狗博主的建议下买了一台宠物空气净化器,开了…

ffmpeg视频滤镜:压缩-deflate

滤镜简述 deflate 官网链接 > https://ffmpeg.org/ffmpeg-filters.html#deflate 压缩滤镜可以降低视频的质量&#xff0c;从而减少视频的大小&#xff0c;虽然一定程度上影响了观看体验&#xff0c;但是方便传输。 滤镜使用 参数 threshold0 <int> …

函数的力量:掌握C语言的基石

目录 前言 标准库&#xff1a;C语言的百宝箱 头文件&#xff1a;库函数的藏宝图 实例分析&#xff1a;计算平方根的sqrt函数 功能描述 头文件包含的重要性 库函数文档的一般格式 自定义函数&#xff1a;释放你的编程创造力 函数的语法形式 函数的比喻 函数的举例 简化…

FreeSSl 申请免费证书,ACME实现自动化续期(https证书自动续期)

网站&#xff1a;https://freessl.cn/ 参考&#xff1a;ACME自动化快速入门 注册/登录后 1 添加域名 2 申请证书 安装acme.sh curl https://get.acme.sh | sh -s emailmyexample.com执行ACME.sh 申请证书命令 cd ~/.acme.sh/ # 直接拷贝上面步骤生成的命令 ./acme.sh …