驱动和应用层的三种通信方式Word格式文档下载.docx

上传人:b****6 文档编号:21114950 上传时间:2023-01-27 格式:DOCX 页数:6 大小:17.16KB
下载 相关 举报
驱动和应用层的三种通信方式Word格式文档下载.docx_第1页
第1页 / 共6页
驱动和应用层的三种通信方式Word格式文档下载.docx_第2页
第2页 / 共6页
驱动和应用层的三种通信方式Word格式文档下载.docx_第3页
第3页 / 共6页
驱动和应用层的三种通信方式Word格式文档下载.docx_第4页
第4页 / 共6页
驱动和应用层的三种通信方式Word格式文档下载.docx_第5页
第5页 / 共6页
点击查看更多>>
下载资源
资源描述

驱动和应用层的三种通信方式Word格式文档下载.docx

《驱动和应用层的三种通信方式Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《驱动和应用层的三种通信方式Word格式文档下载.docx(6页珍藏版)》请在冰豆网上搜索。

驱动和应用层的三种通信方式Word格式文档下载.docx

输入缓冲区大小 

lpOutBuffer, 

输出缓冲区地址 

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 

管理器将驱动程序已经提供的数据从系统缓冲区复制到用户缓冲区。

对于写入请求,会分配一个系统缓冲区并将 

设置为地址。

用户缓冲区的内容会被复制到系统缓冲区,但是不设置 

UserBuffer。

对于 

IOCTL 

请求,会分配一个容量大小足以包含输入缓冲区或输出缓冲区的系统缓冲区,并将 

设置为分配的缓冲区地址。

输入缓冲区中的数据复制到系统缓冲区。

字段设置为用户模式输出缓冲区地址。

内核模式驱动程序应当只使用系统缓冲区,且不应使用 

中存储的地址。

IOCTL,驱动程序应当从系统缓冲区获取输入并将输出写入到系统缓冲区。

系统将输出数据从系统缓冲区复制到用户缓冲区。

直接"

方法(METHOD_IN/OUT_DIRECT)

对于读取和写入请求,用户模式缓冲区会被锁定,并且会创建一个内存描述符列表 

(MDL)。

MDL 

地址会存储在 

的 

MdlAddress 

字段中。

和 

均没有任何含义。

但是,驱动程序不应当更改这些字段的值。

请求,如果在 

METHOD_IN_DIRECT 

METHOD_OUT_DIRECT 

中同时有一个输出缓冲区,则分配一个系统缓冲区(SystemBuffer 

又有了地址)并将输入数据复制到其中。

如果有一个输出缓冲区,且它被锁定,则会创建 

并设置 

MdlAddress。

字段没有任何含义。

两者都不"

方法(METHOD_NEITHER)

对于读取和写入请求,UserBuffer 

字段被设置为指向初始的用户缓冲区。

不执行任何其他操作。

SystemAddress 

没有任何含义。

请求,I/O 

管理器将 

设置为初始的用户输出缓冲区,而且,它将当前 

I/O 

栈位置的 

Parameters.DeviceIoControl.Type3InputBuffer 

设置为用户输入缓冲区。

利用该 

方法,由驱动程序来确定如何处理缓冲区:

分配系统缓冲区或创建 

MDL。

通常,驱动程序在访问用户数据时不应当将 

字段用作地址,即使当用户缓冲区被锁定时也是如此。

这是由于在调用驱动程序时,在系统中可能看不到调用用户的地址空间。

(对于该规则的一个例外是,在最高层驱动程序将 

向下传递到较低层的驱动程序之前,它可能需要使用 

来复制数据。

)如果使用"

或"

方法,在创建 

之后,驱动程序可以使用 

MmGetSystemAddressForMdl 

函数来获取有效的系统地址以访问用户缓冲区。

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

传输类型 

位置

irp->

AssociatedIrp.SystemBuffer

METHOD_BUFFERED 

METHOD_NEITHER 

irpStack->

Parameters.DeviceIoControl.Type3InputBuffer

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

MdlAddress

UserBuffer

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

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

代码:

//METHOD_OUT_DIREC方式

NTSTATUS 

COMM_DirectOutIo(PIRP 

Irp, 

PIO_STACK_LOCATION 

pIoStackIrp, 

UINT 

*sizeofWrite)

{

status 

STATUS_UNSUCCESSFUL;

PVOID 

pInputBuffer, 

pOutputBuffer;

ULONG 

outputLength, 

inputLength;

DbgPrint("

COMM_DirectOutIo\r\n"

outputLength 

pIoStackIrp->

Parameters.DeviceIoControl.OutputBufferLength;

inputLength 

Parameters.DeviceIoControl.InputBufferLength;

pInputBuffer 

Irp->

AssociatedIrp.SystemBuffer;

pOutputBuffer 

NULL;

if(Irp->

MdlAddress)

MmGetSystemAddressForMdlSafe(Irp->

MdlAddress, 

NormalPagePriority);

if(pInputBuffer 

&

pOutputBuffer)

COMM_DirectOutIo 

UserModeMessage 

'

%s'

 

pInputBuffer);

RtlCopyMemory(pOutputBuffer, 

outputLength);

*sizeofWrite 

outputLength;

STATUS_SUCCESS;

}

return 

status;

METHOD_IN_DIRECT

COMM_DirectInIo(PIRP 

COMM_DirectInIo\r\n"

COMM_DirectInIo 

METHOD_BUFFERED

COMM_BufferedIo(PIRP 

COMM_BufferedIo\r\n"

COMM_BufferedIo 

METHOD_NEITHER

COMM_NeitherIo(PIRP 

COMM_NeitherIo\r\n"

Parameters.DeviceIoControl.Type3InputBuffer;

UserBuffer;

COMM_NeitherIo 

代码比较简单,都是取得输入的数据,然后把数据直接拷贝到输出,传输给应用层。

应用层的代码:

procedure 

TfrmMain.Send_Recv_Data(AInData:

String;

var 

AOutData:

IoctlCode:

DWORD);

var

dwReturn:

DWORD;

inData:

array[0..1023] 

of 

char;

outData:

begin

StrPCopy(inData, 

AInData);

if 

m_hCommDevice 

<

>

then

DeviceIoControl(m_hCommDevice, 

IoctlCode, 

@inData, 

Length(inData), 

@outData, 

Length(outData), 

dwReturn, 

nil);

AOutData 

:

StrPas(@outData);

end;

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

需要通信,只要如下做:

TfrmMain. 

btnDirect_IN_IOClick 

(Sender:

TObject);

Send_Recv_Data(Trim(edtDirect_in_in.Text), 

outData, 

IOCTL_COMM_DIRECT_IN_IO);

edtDirect_in_out.Text 

outData;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 法语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1