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

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.

下面介绍缓冲区方式读写。其优点是比较简单的解决了将用户地址传入驱动的问题,缺点是需要用户模式和内核模式之间数据复制,可想而知,运行效率会受到影响。适合少量内存操作时使用的一种方法。

现在以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。

3.

附加说明:如果用户模式调用DeviceIoControl的话,缓冲区的信息获得方式如下:

//得到当前堆栈

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

//得到输入缓冲区大小

ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;

//得到输出缓冲区大小

ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;

//输入缓冲区数据

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

//操作输出缓冲区

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

pIrp->IoStatus.Information = 实际操作字节数。

时间: 2025-01-01 10:42:41

驱动开发之 设备读写方式:缓冲区方式的相关文章

驱动开发之 设备读写方式:直接方式

上一节介绍了缓冲区方式读写,这一节咱们来看看直接方式读写设备. 1. 直接方式读写设备,操作系统会将用户模式下的缓冲区锁住,然后操作系统将这段缓冲区在内核模式地址再次映射一遍.这样,用户模式的缓冲区和内核模式的缓冲区指向的是同一区域的物理内存.无论操作系统如何切换进程,内核模式地址都保持不变. 创建好设备IoCreateDevice后,需要设置DO_DIRECT_IO,  pDevObj->Flags |= DO_DIRECT_IO. 2. 这里涉及到内存描述符表(MDL) MDL结构的声明如下

Linux 设备驱动开发 —— platform设备驱动应用实例解析

前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 -- platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platform模型驱动编程,platform 驱动只是在字符设备驱动外套一层platform_driver 的外壳. 在一般情况下,2.6内核中已经初始化并挂载了一条platform总线在sysfs文件系统中.那么我们编写platform模型驱动时,需要完成两个工作: a -- 实现platform驱动 架构就

Linux设备驱动开发 - 平台设备驱动

Linux2.6的内核中引入了一种新的设备驱动模型-平台(platform)设备驱动,平台设备驱动分为平台设备(platform_device)和平台驱动(platform_driver),平台设备的引入使得Linux设备驱动更加便于移植. 一.平台设备平台设备结构体: 1 struct platform_device { 2 const char * name; /* 设备名 */ 3 int id; 4 struct device dev; /* 设备结构体 */ 5 u32 num_res

驱动开发--【字符设备、块设备简介】【sky原创】

驱动开发   字符设备,块设备,网络设备 字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问 EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是直接访问硬件的 flash 擦写次数有限,一百万次,容易有坏块 块设备 能随机访问 以”块“为单位进行访问 块大小一般为512字节 块的大小由硬件决定 是内核进行数据传输的基本单位 硬盘结构: 格式化分区是以柱面为单位的,即硬盘的柱面 如果有10个盘面,就有十个柱面 对于嵌入式设备 如果是flash的话,结

Andriod驱动开发与系统移植概述读后感

本章通过介绍android系统架构->介绍android系统移植的主要工作->查看linux内核版本->linux内核版本号的定义规则->如何学习linux驱动开发->linux设备驱动    给linux驱动举例的方式来对于Andriod系统移植与驱动开发的工作做出一个基本的概述. 首先,android移植可以分为:应用移植和系统移植,应用移植是将程序移植到某一个特定硬件平台上:系统移植是指让android是指让android操作系统支持硬件平台上运行.那么对于嵌入式系统来

Windows驱动开发-设备读写方式

设备读写方式共三种: 方式 Flag 特点 缓冲区方式读写 DO_BUFFERED_IO I/O管理器先创建一个与用户模式数据缓冲区大小相等的系统缓冲区.而你的驱动程序将使用这个系统缓冲区工作.I/O管理器负责在系统缓冲区和用户模式缓冲区之间复制数据. 直接方式读写 DO_DIRECT_IO I/O管理器锁定了包含用户模式缓冲区的物理内存页,并创建一个称为MDL(内存描述符表)的辅助数据结构来描述锁定页.因此你的驱动程序将使用MDL工作. Neither方式 0 I/O管理器仅简单地把用户模式的

NX二次开发-基于NX开发向导模板的NX对Excel读写操作(OLE方式(COM组件))

在看这个博客前,请读者先去完整看完:NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))https://ufun-nxopen.blog.csdn.net/article/details/88922030 这篇博客,要不然你听不懂我下面在说什么. 版本NX11+VS2013+office2016 首先我们通过NX开发向导创建了一个模板. 先把项目属性改成多字节.下面我们把前面做的MFC项目里的几个EXCAL头文件和stdafx一块拷过来,加到NX的项目里. 在NX的

NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))

NX二次开发API里没有对EXCAL读写操作的相关函数,市面上有很多种方法去实现,比如UFUN调KF,ODBC,OLE(COM组件)等等.这里我是用的OLE(COM组件)方式去做的,这种在VC上创建的方法,无论C++还是C#还是VB方式思路都是一样的.先介绍用MFC去做,然后在写一篇博客介绍怎么在NX的二次开发的向导模板里去做.NX二次开发-基于NX开发向导模板的NX对Excel读写操作(OLE方式(COM组件))https://ufun-nxopen.blog.csdn.net/article

《Linux设备驱动开发详解(第3版)》海量更新总结

本博实时更新<Linux设备驱动开发详解(第3版)>的最新进展. 2015.2.26 几乎完成初稿. [F]是修正或升级:[N]是新增知识点:[D]是删除的内容 第1章 <Linux设备驱动概述及开发环境构建>[D]删除关于LDD6410开发板的介绍[F]更新新的Ubuntu虚拟机[N]添加关于QEMU模拟vexpress板的描述 第2章 <驱动设计的硬件基础> [N]增加关于SoC的介绍:[N]增加关于eFuse的内容:[D]删除ISA总线的内容了:[N]增加关于SP