驱动和应用层的三种通信方式

标 题: 【原创】【成果3.5】驱动和应用层的三种通信方式

作 者: sislcb

时 间: 2008-01-04,11:57

链 接: http://bbs.pediy.com/showthread.php?t=57666

驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。 驱动层和应用层通信,主要是靠DeviceIoControl函数,下面是该函数的原型: BOOL DeviceIoControl (

HANDLE hDevice, // 设备句柄

DWORD dwIoControlCode, // IOCTL请求操作代码

LPVOID lpInBuffer, // 输入缓冲区地址

DWORD nInBufferSize, // 输入缓冲区大小

LPVOID lpOutBuffer, // 输出缓冲区地址

DWORD nOutBufferSize, // 输出缓冲区大小

LPDWORD lpBytesReturned, // 存放返回字节数的指针

LPOVERLAPPED lpOverlapped // 用于同步操作的Overlapped结构体指针 );

dwIoControlCode

要进行操作的控制码。驱动程序可以通过CTL_CODE宏来组合定义一个控制码,并在IRP_MJ_DEVICE_CONTROL的实现中进行控制码的操作。在驱动层,irpStack->Parameters.DeviceIoControl.IoControlCode表示了这个控制码。

IOCTL请求有四种缓冲策略,下面一一介绍。

1、 输入输出缓冲I/O(METHOD_BUFFERED)

2、 直接输入缓冲输出I/O(METHOD_IN_DIRECT)

3、 缓冲输入直接输出I/O(METHOD_OUT_DIRECT)

4、 上面三种方法都不是(METHOD_NEITHER)

为了对这些类型更详细的描述,请看msdn上的解释,我抄录如下:

"缓冲"方法(METHOD_BUFFERED)

备注:在下面的讨论中,"输入"表示数据从用户模式的应用程序到驱动程序,"输出"表示数据从驱动程序到应用程序。

对于读取请求,I/O 管理器分配一个与用户模式的缓冲区大小相同的系统缓冲区。IRP 中的 SystemBuffer 字段包含系统地址。UserBuffer 字段包含初始的用户缓冲区地址。当完成请求时,I/O 管理器将驱动程序已经提供的数据从系统缓冲区复制到用户缓冲区。对于写入请求,会分配一个系统缓冲区并将 SystemBuffer 设置为地址。用户缓冲区的内容会被复制到系统缓冲区,但是不设置 UserBuffer。对于 IOCTL 请求,会分配一个容量大小足以包含输入缓冲区或输出缓冲区的系统缓冲区,并将 SystemBuffer 设置为分配的缓冲区地址。输入缓冲区中的数据复制到系统缓冲区。UserBuffer 字段设置为用户模式输出缓冲区地址。内核模式驱动程序应当只使用系统缓冲区,且不应使用 UserBuffer 中存储的地址。

对于 IOCTL,驱动程序应当从系统缓冲区获取输入并将输出写入到系统缓冲区。当完成请求时,I/O 系统将输出数据从系统缓冲区复制到用户缓冲区。

"直接"方法(METHOD_IN/OUT_DIRECT)

对于读取和写入请求,用户模式缓冲区会被锁定,并且会创建一个内存描述符列表 (MDL)。MDL 地址会存储在 IRP 的 MdlAddress 字段中。SystemBuffer 和 UserBuffer 均没有任何含义。但是,驱动程序不应当更改这些字段的值。

对于 IOCTL 请求,如果在 METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT 中同时有一个输出缓冲区,则分配一个系统缓冲区(SystemBuffer 又有了地址)并将输入数据复制到其中。如果有一个输出缓冲区,且它被锁定,则会创建 MDL 并设置 MdlAddress。UserBuffer 字段没有任何含义。

"两者都不"方法(METHOD_NEITHER)

对于读取和写入请求,UserBuffer 字段被设置为指向初始的用户缓冲区。不执行任何其他操作。SystemAddress 和 MdlAddress 没有任何含义。对于 IOCTL 请求,I/O 管理器将 UserBuffer 设置为初始的用户输出缓冲区,而且,它将当前 I/O 栈位置的 Parameters.DeviceIoControl.Type3InputBuffer 设置为用户输入缓冲区。利用该 I/O 方法,由驱动程序来确定如何处理缓冲区:分配系统缓冲区或创建 MDL。

通常,驱动程序在访问用户数据时不应当将 UserBuffer 字段用作地址,即使当用户缓冲区被锁定时也是如此。这是由于在调用驱动程序时,在系统中可能看不到调用用户的地址空间。(对于该规则的一个例外是,在最高层驱动程序将 IRP 向下传递到较低层的驱动程序之前,它可能需要使用 UserBuffer 来复制数据。)如果使用"直接"或"两者都不"方法,在创建 MDL 之后,驱动程序可以使用 MmGetSystemAddressForMdl 函数来获取有效的系统地址以访问用户缓冲区。

在驱动层,依传输类型的不同,输入缓冲区的位置亦不同,见下表。 传输类型 位置

METHOD_IN_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_OUT_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer

METHOD_NEITHER irpStack->Parameters.DeviceIoControl.Type3InputBuffer

在驱动层,依传输类型的不同,输出缓冲区的位置亦不同,见下表。 传输类型 位置

METHOD_IN_DIRECT irp->MdlAddress

METHOD_OUT_DIRECT irp->MdlAddress

METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer METHOD_NEITHER irp->UserBuffer

所以只要确定了传输方式后,就可以根据各自的位置来读取和写入数据,从而实现应用层和驱动的通信。

下面看驱动层对ioctl控制码的处理代码:

代码:

上面是进行发送和接受的过程。

需要通信,只要如下做:

代码:

标 题: 【原创】【成果3.5】驱动和应用层的三种通信方式

作 者: sislcb

时 间: 2008-01-04,11:57

链 接: http://bbs.pediy.com/showthread.php?t=57666

驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。 驱动层和应用层通信,主要是靠DeviceIoControl函数,下面是该函数的原型: BOOL DeviceIoControl (

HANDLE hDevice, // 设备句柄

DWORD dwIoControlCode, // IOCTL请求操作代码

LPVOID lpInBuffer, // 输入缓冲区地址

DWORD nInBufferSize, // 输入缓冲区大小

LPVOID lpOutBuffer, // 输出缓冲区地址

DWORD nOutBufferSize, // 输出缓冲区大小

LPDWORD lpBytesReturned, // 存放返回字节数的指针

LPOVERLAPPED lpOverlapped // 用于同步操作的Overlapped结构体指针 );

dwIoControlCode

要进行操作的控制码。驱动程序可以通过CTL_CODE宏来组合定义一个控制码,并在IRP_MJ_DEVICE_CONTROL的实现中进行控制码的操作。在驱动层,irpStack->Parameters.DeviceIoControl.IoControlCode表示了这个控制码。

IOCTL请求有四种缓冲策略,下面一一介绍。

1、 输入输出缓冲I/O(METHOD_BUFFERED)

2、 直接输入缓冲输出I/O(METHOD_IN_DIRECT)

3、 缓冲输入直接输出I/O(METHOD_OUT_DIRECT)

4、 上面三种方法都不是(METHOD_NEITHER)

为了对这些类型更详细的描述,请看msdn上的解释,我抄录如下:

"缓冲"方法(METHOD_BUFFERED)

备注:在下面的讨论中,"输入"表示数据从用户模式的应用程序到驱动程序,"输出"表示数据从驱动程序到应用程序。

对于读取请求,I/O 管理器分配一个与用户模式的缓冲区大小相同的系统缓冲区。IRP 中的 SystemBuffer 字段包含系统地址。UserBuffer 字段包含初始的用户缓冲区地址。当完成请求时,I/O 管理器将驱动程序已经提供的数据从系统缓冲区复制到用户缓冲区。对于写入请求,会分配一个系统缓冲区并将 SystemBuffer 设置为地址。用户缓冲区的内容会被复制到系统缓冲区,但是不设置 UserBuffer。对于 IOCTL 请求,会分配一个容量大小足以包含输入缓冲区或输出缓冲区的系统缓冲区,并将 SystemBuffer 设置为分配的缓冲区地址。输入缓冲区中的数据复制到系统缓冲区。UserBuffer 字段设置为用户模式输出缓冲区地址。内核模式驱动程序应当只使用系统缓冲区,且不应使用 UserBuffer 中存储的地址。

对于 IOCTL,驱动程序应当从系统缓冲区获取输入并将输出写入到系统缓冲区。当完成请求时,I/O 系统将输出数据从系统缓冲区复制到用户缓冲区。

"直接"方法(METHOD_IN/OUT_DIRECT)

对于读取和写入请求,用户模式缓冲区会被锁定,并且会创建一个内存描述符列表 (MDL)。MDL 地址会存储在 IRP 的 MdlAddress 字段中。SystemBuffer 和 UserBuffer 均没有任何含义。但是,驱动程序不应当更改这些字段的值。

对于 IOCTL 请求,如果在 METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT 中同时有一个输出缓冲区,则分配一个系统缓冲区(SystemBuffer 又有了地址)并将输入数据复制到其中。如果有一个输出缓冲区,且它被锁定,则会创建 MDL 并设置 MdlAddress。UserBuffer 字段没有任何含义。

"两者都不"方法(METHOD_NEITHER)

对于读取和写入请求,UserBuffer 字段被设置为指向初始的用户缓冲区。不执行任何其他操作。SystemAddress 和 MdlAddress 没有任何含义。对于 IOCTL 请求,I/O 管理器将 UserBuffer 设置为初始的用户输出缓冲区,而且,它将当前 I/O 栈位置的 Parameters.DeviceIoControl.Type3InputBuffer 设置为用户输入缓冲区。利用该 I/O 方法,由驱动程序来确定如何处理缓冲区:分配系统缓冲区或创建 MDL。

通常,驱动程序在访问用户数据时不应当将 UserBuffer 字段用作地址,即使当用户缓冲区被锁定时也是如此。这是由于在调用驱动程序时,在系统中可能看不到调用用户的地址空间。(对于该规则的一个例外是,在最高层驱动程序将 IRP 向下传递到较低层的驱动程序之前,它可能需要使用 UserBuffer 来复制数据。)如果使用"直接"或"两者都不"方法,在创建 MDL 之后,驱动程序可以使用 MmGetSystemAddressForMdl 函数来获取有效的系统地址以访问用户缓冲区。

在驱动层,依传输类型的不同,输入缓冲区的位置亦不同,见下表。 传输类型 位置

METHOD_IN_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_OUT_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer

METHOD_NEITHER irpStack->Parameters.DeviceIoControl.Type3InputBuffer

在驱动层,依传输类型的不同,输出缓冲区的位置亦不同,见下表。 传输类型 位置

METHOD_IN_DIRECT irp->MdlAddress

METHOD_OUT_DIRECT irp->MdlAddress

METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer METHOD_NEITHER irp->UserBuffer

所以只要确定了传输方式后,就可以根据各自的位置来读取和写入数据,从而实现应用层和驱动的通信。

下面看驱动层对ioctl控制码的处理代码:

代码:

上面是进行发送和接受的过程。

需要通信,只要如下做:

代码:


相关文章

  • 电子设计相关知识
  • 红外数据传输 一. 红外通信原理 红外遥控有发送和接收两个组成部分.发送端采用单片机将待发 送的二进制信号编码调制为一系列的脉冲串信号,通过红外发射管发 射红外信号.红外接收完成对红外信号的接收.放大.检波.整形, 并解调出遥控编码脉冲.为 ...查看


  • 蓝牙通用外接模块实例
  • 蓝牙是一种短距离无线通信技术.本文从蓝牙协议栈中的HCI 层入手,对该层的主要功能和工作机制进行了剖析,进而阐述了基于HCI 层的蓝牙应用开发方案,并设计了一个基于蓝牙技术开发的产品实例--蓝牙通用外接模块,最后,还对基于此模块的扩展应用- ...查看


  • 移动卫星应急通信系统解决方案XX
  • 移动卫星应急通信系统解决方案 -移动卫星车(船)载站 北京XXXXXXX 公司 目录 一.公司简介 . .................................................................... ...查看


  • 机械电子工程专业红外线遥控系统大学毕业论文外文文献翻译及原文
  • 毕 业 设 计(论文) 外 文 文 献 翻 译 文献.资料中文题目:红外线遥控系统 文献.资料英文题目: Infrared Remote Control System 文献.资料来源: 文献.资料发表(出版)日期: 院 (部): 专 业: ...查看


  • 步进电机绘图系统设计
  • 第25卷第2期2008年3月 河北工业科技 H ebei Jour nal of Industr ial Science and T echno log y V ol. 25, No. 2M ar. 2008 文章编号:1008-1534( ...查看


  • 光纤通信系统中常用的调制方法
  • 光纤通信系统中常用的调制方法 一. 光纤通信概况 1. 发展 1966年,美籍华人高锟(C.K.Kao)和霍克哈姆(C.A.Hockham)发表论文,预见了低损耗的光纤能够用于通信,敲开了光纤通信的大门,引起了人们的重视.1970年,美国康 ...查看


  • 串口通信基本接线方法
  • 串口通信基本接线方法 龚建伟 2001.6.20 目次:1.DB9和DB25的常用信号脚说明 2.RS232C 串口通信接线方法 3. 串口调试中要注意的几点 目前较为常用的串口有9针串口(DB9)和25针串口(DB25),通信距离较近时( ...查看


  • 交通诱导屏软件设计
  • 目 录 摘要 .........................................................0 0 引言 ................................................. ...查看


  • 室内LED可见光通信技术分析
  • 摘 要:本文主要分析了LED可见光通信的基本原理及关键技术,然后就LED可见光通信的未来应用进行展望,以期促进LED可见光通信技术的发展与完善. 关键词:室内LED:可见光通信:应用展望 中图分类号:TN929 文献标识码:A LED可见光 ...查看


热门内容