驱动开发之 设备读写方式:缓冲区方式

1.

设备对象一共同拥有三种读写方式:缓冲区方式读写(Buffered方式);直接方式读写(Direct方式)。Neither方式。这三种方式的Flags分别相应DO_BUFFERED_IO,DO_DIRECT_IO,0

在buffered方式中。I/O管理器先创建一个与用户模式数据缓冲区大小相等的系统缓冲区。而你的驱动程序将使用这个系统缓冲区工作。I/O管理器负责在系统缓冲区和用户模式缓冲区之间复制数据。

 
在direct方式中,I/O管理器锁定了包括用户模式缓冲区的物理内存页。并创建一个称为MDL(内存描写叙述符表)的辅助数据结构来描写叙述锁定页。因此你的驱动程序将使用MDL工作。 
在neither方式中。I/O管理器仅简单地把用户模式的虚拟地址传递给你。

而使用用户模式地址的驱动程序应十分小心。


2.

以下介绍缓冲区方式读写。其长处是比較简单的攻克了将用户地址传入驱动的问题,缺点是须要用户模式和内核模式之间数据复制。可想而知。执行效率会受到影响。

适合少量内存操作时使用的一种方法。

创建好设备IoCreateDevice后。须要设置DO_BUFFERED_IO,  pDevObj->Flags |= DO_BUFFERED_IO.

如今以readfile为例,首先应用程序中须要提供一段缓冲区并把缓冲区大小作为參数传入,比如

UCHAR OutputBuffer[10];
DWORD RetLen = 0;
readfile(hDevice,OutputBuffer,sizeof(OutputBuffer),&RetLen,NULL);

OutputBuffer是提供的输出缓冲区。是用户模式的内存地址,操作系统将此缓冲区的数据拷贝到内核模式下的地址中,sizeof(OutputBuffer)是缓冲区的大小,而RetLen是真正的输出的字节数。


那么内核模式怎么得到此内核模式地址呢?怎么得到writefile或readfile的字节数呢?答案在以下。

此内核模式下的地址能够通过此readfile创建的IRP的AssociatedIrp.SystemBuffer得到。

假如请求的IRP为PIRP pIrp(通常是派遣函数的參数),那么UCHAR* OutputBuffer= (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;

而readfile请求的字节数为IO_STACK_LOCATION中的Parameters.Read.Length,writefilew为IO_STACK_LOCATION中的Parameters.Write.Length

//得到当前堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//得到readfile缓冲区大小
ULONG cbread = stack->Parameters..Read.Length;
//得到writefile缓冲区大小
ULONG cbwrite = stack->Parameters.Write.Length;


得到了内核模式下的缓冲区地址了就能够对此缓冲区操作了。比方:

UCHAR* OutputBuffer= (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;

ULONG cbread = stack->Parameters..Read.Length;

memcpy(OutputBuffer,0xBB,cbread);

这样用户模式下的缓冲区内得到的数据是0xBB。


另外还要设置实际操作的字节数,pIrp->IoStatus.Information = cbread;(实际操作的字节数不一定要设置为缓冲区的大小。但也不应该大于缓冲区的大小)

那么用户模式下readfile的RetLen被设置为cbread。


以下是IRP_MJ_READ的派遣函数:

NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) 
{KdPrint(("Enter DispatchRead\n"));//对一般IRP的简单操作。后面会介绍对IRP更复杂的操作NTSTATUS status = STATUS_SUCCESS;PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);ULONG ulReadLength = stack->Parameters.Read.Length;// 完毕IRP//设置IRP完毕状态pIrp->IoStatus.Status = status;//设置IRP操作了多少字节pIrp->IoStatus.Information = ulReadLength;	memset(pIrp->AssociatedIrp.SystemBuffer,0xAA,ulReadLength);//处理IRPIoCompleteRequest( pIrp, IO_NO_INCREMENT );KdPrint(("Leave DispatchRead\n"));return status;
}

设备读写方式:直接读取方式:http://blog.csdn.net/liyun123gx/article/details/38043849

Neither方式:http://blog.csdn.net/liyun123gx/article/details/38046865



转载于:https://www.cnblogs.com/gavanwanggw/p/6908009.html

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

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

相关文章

flask开启调试的四种模式

在app.run()中加一个参数, debugTrue就可以开启debug模式 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return Hello World!if __name__ __main__:app.run(debugTrue) 将app的debug属性赋值为True 1 from flask import Flask2 3 app Flas…

Python基础常见面试题总结

文章目录基础知识题看程序写结果题编程题以下是总结的一些常见的Python基础面试题,帮助大家回顾基础知识,了解面试套路。会一直保持更新状态。PS:加粗为需要注意的点。基础知识题 1、深拷贝和浅拷贝的区别是什么? 深拷贝是将对象…

2、nginx配置文件

2、nginx配置文件user [user] [group];//运行nginx的用户(组)(只能在全局设置)worker process number|auto;//允许生成的worker process数(只能在全局设置,通常设置成和cpu的数量相等 )pid file;//nginx进程的Pid存放路…

watir6.0 -selenium3新时代的watir-webdriver

很久没写博客了- - 记得几年前使用watir的时候还是1.x系列,个人感觉还是非常好用的,不过缺点也很明显,只支持ie,对于弹出框下载框等支持不是很好,经常需要结合autoit 一起使用。 中间有一段时间没有使用过watir&#x…

Flask-Script扩展命令行manager = Manager(app)

通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过python hello.py runserver --host ip地址,告诉服务器在哪个网络接口监听来自客户端的连…

Python基础总结之常用内置方法总结

文章目录前言1、str1.1、内置方法:1.2、常用的内置方法1.3、String模块的一些方法2、list2.1、内置方法2.2、常用内置方法3、tupple3.1、内置方法3.2、常用内置方法4、dict4.1、内置方法4.2、常用内置方法5、其他5.1、几个sort的使用5.2、enumerate(&…

线程的条件变量实例

情景1:Jack开着一辆出租车来到一个网站停车。看见没人就走了。过段时间。Susan来到网站准备乘车。可是没有来,于是就等着。过了一会Mike开着车来到了这个网站,Sunsan就上了Mike的车走了。如图所看到的:程序实现该情景:…

Flask 模板 之 变量和过滤器

1.模板 在前面的示例中,视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度…

架设证书服务器 及 让IIS启用HTTPS服务

http://blog.csdn.net/dier4836/article/details/7719532转载于:https://www.cnblogs.com/kunlunmountain/p/6428838.html

浅谈互联网寒冬与经济形势

文章目录前言:闲扯总结:前言: 作为刚进入职场一年多的小白来说,刚准备“猥琐发育涨经验”,却碰到这股互联网寒冬,也感到鸭梨山大。也许有人认为我在贩卖焦虑,但是现实真的很严峻。接下说下过去…

jenkins 配置

build periodically 周期进行项目构建poll scm 定时检查远吗变更,如果有更新就checkout最新code下来,然后执行构建动作日程表:H 9 *** : 每天9点固定构建一次H/30 8-17 *** : 每天的8-17点每隔三十分钟检查一次转载于:https://…

Java集合---LinkedList源码解析

一、源码解析1、 LinkedList类定义2、LinkedList数据结构原理3、私有属性4、构造方法5、元素添加add()及原理6、删除数据remove()7、数据获取get()8、数据复制clone()与toArray()9、遍历数据:Iterator()二、ListItr 一、源码解析 1、 LinkedList类定义。 public cla…

Mysql面试热身题集总结

文章目录前言1、热身题实践其他前言 一直有个想法:把面试需要的知识点全都总结一下,包括数据库,语言,算法,数据结构等知识,形成一个面试总结笔记,这样以后面试的时候只看这些文章回顾下就行了。…

Flask中的 url_for() 函数

最近在学Python Flask框架,并且学会做一些简单的项目,如做一个网站的登录页面等,其中学到了一个路由反向解析的函数 url_for(),这里做一个小结,供日后复习。 1.URL反转:根据视图函数…

Oracle执行计划解释

为什么80%的码农都做不了架构师?>>> 一.相关的概念 Rowid的概念:rowid是一个伪列,既然是伪列,那么这个列就不是用户定义,而是系统自己给加上的。 对每个表都有一个rowid的伪列,但是表…

邓迎春绘画201702作品10

转载于:https://www.cnblogs.com/hanxiangmin/p/6439376.html

解决:FLASK中Warning: (1366, Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...'

Flask项目中使用mysql数据库启动项目是发出警告: Warning: (1366, “Incorrect string value: ‘\xD6\xD0\xB9\xFA\xB1\xEA…’ for column ‘VARIABLE_VALUE’ at row 479/480/481”) 但是项目可以正常启动使用 如果想将次警告去掉需要导入一个模块 解决方法&…

Pandas常用操作总结

文章目录前言1、DF常用的两种创建方式方式一:通过np来生成方式二:通过字典来生成2、pandas常用的属性及方法3、Pandas Select(数据选择)4、Pandas Set_values设置值5、Pandas Nan处理缺失值方法一:剔除缺失值所在的行或列方法二:填…

jmeter跨线程组传值

在测试过程中,有时候需要jmeter跨线程组传值,jmeter本身又不具备此功能,那么,又该如何实现呢? 其实,我们可以通过BeanShell去实现。 实现过程如下: 1.线程组A中,使用正则表达式提取器…

BZOJ 3093: [Fdu校赛2012] A Famous Game

3093: [Fdu校赛2012] A Famous Game Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 248 Solved: 133[Submit][Status][Discuss]Description Mr. B and Mr. M like to play with balls. They have many balls colored in blue and red. Firstly, Mr. B randomly picks up N …