用户层与驱动层通信

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475
备注:1.在下面的讨论中,"输入"表示数据从用户模式的应用程序到驱动程序,"输出"表示数据从驱动程序到应用程序。2.IRP 中的 SystemBuffer 字段包含系统地址。UserBuffer 字段包含初始的用户缓冲区地址。

参考文章链接:https://blog.csdn.net/endenvor/p/9057856.html/ ,个人觉得原文有些乱,并且代码不完整,在此做了整理和补充。


一、I/O设备控制操作

R3通过DeviceControl函数来写入和读取R0的数据。R0层通过一下几种方式读取R3发送的数据和向R3发送数据。

(1)"缓冲"内存IOCTL – METHOD_BUFFERED

对于 IOCTL 请求,会分配一个容量大小足以包含输入缓冲区或输出缓冲区的系统缓冲区,并将 SystemBuffer 设置为分配的缓冲区地址。输入缓冲区中的数据复制到系统缓冲区。UserBuffer 字段设置为用户模式输出缓冲区地址。内核模式驱动程序应当只使用系统缓冲区,且不应使用 UserBuffer 中存储的地址。

对于 IOCTL,驱动程序应当从系统缓冲区获取输入并将输出写入到系统缓冲区。当完成请求时,I/O 系统将输出数据从系统缓冲区复制到用户缓冲区。(ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。)

输入缓冲区大小:stack->Parameters.DeviceIoControl.InputBufferLength  输出缓冲区大小:stack->Parameters.DeviceIoControl.OutputBufferLength  输入缓冲区:pIrp->AssociatedIrp.SystemBuffer  输出缓冲区:pIrp->AssociatedIrp.SystemBuffer

2)"直接"方法IOCTL – METHOD_IN_DIRECT/METHOD_OUT_DIRECT

对于读取和写入请求,用户模式缓冲区会被锁定,并且会重新映射一个内存描述符列表 (MDL)。MDL 地址会存储在 IRP 的 MdlAddress 字段中。根据 Irp->MdlAddress 重新为这片物理地址映射一份虚拟地址。通过这份虚拟地址向R3层发送数据。

SystemBuffer 和 UserBuffer 均没有任何含义。但是,驱动程序不应当更改这些字段的值。

输入缓冲区大小:stack->Parameters.DeviceIoControl.InputBufferLength  输出缓冲区大小:stack->Parameters.DeviceIoControl.OutputBufferLength  **输入缓冲区:MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority)**输出缓冲区:pIrp->AssociatedIrp.SystemBuffer

METHOD_IN_DIRECT/METHOD_OUT_DIRECT区别:     1) 只读权限打开设备,METHOD_IN_DIRECT的IOCTL操作成功,而METHOD_OUT_DIRECT的IOCTL操作失败     2) 读写权限打开设备,METHOD_IN_DIRECT与METHOD_OUT_DIRECT的IOCTL操作都成功

(3)"两种都不"方法IOCTL(其他内存模式) – MEHTOD_NEITHER

对于 IOCTL 请求,I/O 管理器将 UserBuffer 设置为初始的用户输出缓冲区,而且,它将当前 I/O 栈位置的 Parameters.DeviceIoControl.Type3InputBuffer 设置为用户输入缓冲区。利用该 I/O 方法,由驱动程序来确定如何处理缓冲区:分配系统缓冲区或创建 MDL。

输入缓冲区大小:stack->Parameters.DeviceIoControl.InputBufferLength  输出缓冲区大小:stack->Parameters.DeviceIoControl.OutputBufferLength  **输入缓冲区:ProbeForRead(stack->Parameters.DeviceIoControl.Type3InputBuffer)**输出缓冲区:ProbeForWrite(pIrp->UserBuffer)


二、读写操作

分为一下三种,ReadFile,WirteFile方式的缓冲区设备读写,直接方式读写,和其他方式读写(DO_BUFFERED_IO、DO_DIRECT_IO、METHOD_NEITHER)。

在R3层通过 ReadFile,WriteFile 函数进行读写数据,在R0层通过 IRP_MJ_READ 与 IRP_MJ_WRITE 对应的派遣函数中处理以下三种缓存区来进行数据读写。

(1)缓冲区方式读写 – DO_BUFFERED_IO

在创建 Device 后,须要指定方式为 Device 的 Flags 有 DO_BUFFERED_IO。通过应用层 Api 函数 ReadFile,WriteFile 等函数。ntoskrnl.exe创建Irp后,ReadFile和WriteFile参数的缓冲区就在irp->AssociatedIrp.Systembuffer。

同时要求读写的偏移量,和长度都在 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp) 数据类型中的stack->Parameters.Read.Length,stack->Parameters.Read.ByteOffset(该类型为Large_Interge类型)。

对于读取请求,I/O 管理器分配一个与用户模式的缓冲区大小相同的系统缓冲区 SystemBuffer。当完成请求时,I/O 管理器将驱动程序已经提供的数据从系统缓冲区复制到用户缓冲区。

对于写入请求,会分配一个系统缓冲区并将 SystemBuffer 设置为地址。用户缓冲区的内容会被复制到系统缓冲区,但是不设置 UserBuffer。

ReadFile /WriteFile    读取/写入字节数:stack->Parameters.R

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值