驱动和应用层的三种通信方式_第1页
驱动和应用层的三种通信方式_第2页
驱动和应用层的三种通信方式_第3页
驱动和应用层的三种通信方式_第4页
驱动和应用层的三种通信方式_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、标 题: 【原创】【成果3.5】驱动和应用层的三种通信方式作 者: sislcb时 间: 2008-01-04,11:57链 接:驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。驱动层和应用层通信,主要是靠DeviceIoControl函数,下面是该函数的原型:BOOLDeviceIoControl(HANDLEhDevice,/设备句柄DWORDdwIoControlCode,/IOCTL请求操作代码LPVOIDlpInBuffer,/输入缓冲区地址DWORDnInBufferSize,/输入缓冲区大

2、小LPVOIDlpOutBuffer,/输出缓冲区地址DWORDnOutBufferSize,/输出缓冲区大小LPDWORDlpBytesReturned,/存放返回字节数的指针LPOVERLAPPEDlpOverlapped/用于异步操作的Overlapped结构体指针1、输入输出缓冲I/O(METHOD_BUFFERED)2、直接输入缓冲输出I/O(METHOD_IN_DIRECT)3、缓冲输入直接输出I/O(METHOD_OUT_DIRECT)4、上面三种方法都不是(METHOD_NEITHER)为了对这些类型更详细的描述,请看msdn上的解释,我抄录如下:缓冲方法(METHOD_BUF

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

4、ystemBuffer设置为分配的缓冲区地址。输入缓冲区中的数据复制到系统缓冲区。UserBuffer字段设置为用户模式输出缓冲区地址。内核模式驱动程序应当只使用系统缓冲区,且不应使用UserBuffer中存储的地址。对于IOCTL,驱动程序应当从系统缓冲区获取输入并将输出写入到系统缓冲区。当完成请求时,I/O系统将输出数据从系统缓冲区复制到用户缓冲区。直接方法(METHOD_IN/OUT_DIRECT)对于读取和写入请求,用户模式缓冲区会被锁定,并且会创建一个内存描述符列表(MDL)。MDL地址会存储在IRP的MdlAddress字段中。SystemBuffer和UserBuffer均没有任

5、何含义。但是,驱动程序不应当更改这些字段的值。对于IOCTL请求,如果在METHOD_IN_DIRECT和METHOD_OUT_DIRECT中同时有一个输出缓冲区,则分配一个系统缓冲区(SystemBuffer又有了地址)并将输入数据复制到其中。如果有一个输出缓冲区,且它被锁定,则会创建MDL并设置MdlAddress。UserBuffer字段没有任何含义。两者都不方法(METHOD_NEITHER)对于读取和写入请求,UserBuffer字段被设置为指向初始的用户缓冲区。不执行任何其他操作。SystemAddress和MdlAddress没有任何含义。对于IOCTL请求,I/O管理器将Use

6、rBuffer设置为初始的用户输出缓冲区,而且,它将当前I/O栈位置的设置为用户输入缓冲区。利用该I/O方法,由驱动程序来确定如何处理缓冲区:分配系统缓冲区或创建MDL。通常,驱动程序在访问用户数据时不应当将UserBuffer字段用作地址,即使当用户缓冲区被锁定时也是如此。这是由于在调用驱动程序时,在系统中可能看不到调用用户的地址空间。(对于该规则的一个例外是,在最高层驱动程序将IRP向下传递到较低层的驱动程序之前,它可能需要使用UserBuffer来复制数据。)如果使用直接或两者都不方法,在创建MDL之后,驱动程序可以使用MmGetSystemAddressForMdl函数来获取有效的系统

7、地址以访问用户缓冲区。在驱动层,依传输类型的不同,输入缓冲区的位置亦不同,见下表。传输类型位置METHOD_IN_DIRECTirp-AssociatedIrp.SystemBufferMETHOD_OUT_DIRECTirp-AssociatedIrp.SystemBufferMETHOD_BUFFEREDirp-AssociatedIrp.SystemBufferMETHOD_NEITHER位置METHOD_IN_DIRECTirp-MdlAddressMETHOD_OUT_DIRECTirp-MdlAddressMETHOD_BUFFEREDirp-AssociatedIrp.Syste

8、mBufferMETHOD_NEITHERirp-UserBuffer所以只要确定了传输方式后,就可以根据各自的位置来读取和写入数据,从而实现应用层和驱动的通信。下面看驱动层对ioctl控制码的处理代码:代码:/METHOD_OUT_DIREC方式NTSTATUSCOMM_DirectOutIo(PIRPIrp,PIO_STACK_LOCATIONpIoStackIrp,UINT*sizeofWrite)NTSTATUSstatus=STATUS_UNSUCCESSFUL;PVOIDpInputBuffer,pOutputBuffer;ULONGoutputLength,inputLength

9、;DbgPrint(COMM_DirectOutIorn);outputLength=inputLength=pInputBuffer=Irp-AssociatedIrp.SystemBuffer;pOutputBuffer=NULL;if(Irp-MdlAddress)pOutputBuffer=MmGetSystemAddressForMdlSafe(Irp-MdlAddress,NormalPagePriority);if(pInputBuffer&pOutputBuffer)DbgPrint(COMM_DirectOutIoUserModeMessage=%s,pInputBuffer

10、);RtlCopyMemory(pOutputBuffer,pInputBuffer,outputLength);*sizeofWrite=outputLength;status=STATUS_SUCCESS;returnstatus;/METHOD_IN_DIRECTNTSTATUSCOMM_DirectInIo(PIRPIrp,PIO_STACK_LOCATIONpIoStackIrp,UINT*sizeofWrite)NTSTATUSstatus=STATUS_UNSUCCESSFUL;PVOIDpInputBuffer,pOutputBuffer;ULONGoutputLength,i

11、nputLength;DbgPrint(COMM_DirectInIorn);outputLength=inputLength=pInputBuffer=Irp-AssociatedIrp.SystemBuffer;pOutputBuffer=NULL;if(Irp-MdlAddress)pOutputBuffer=MmGetSystemAddressForMdlSafe(Irp-MdlAddress,NormalPagePriority);if(pInputBuffer&pOutputBuffer)DbgPrint(COMM_DirectInIoUserModeMessage=%s,pInp

12、utBuffer);RtlCopyMemory(pOutputBuffer,pInputBuffer,outputLength);*sizeofWrite=outputLength;status=STATUS_SUCCESS;returnstatus;/METHOD_BUFFEREDNTSTATUSCOMM_BufferedIo(PIRPIrp,PIO_STACK_LOCATIONpIoStackIrp,UINT*sizeofWrite)NTSTATUSstatus=STATUS_UNSUCCESSFUL;PVOIDpInputBuffer,pOutputBuffer;ULONGoutputL

13、ength,inputLength;DbgPrint(COMM_BufferedIorn);outputLength=inputLength=pInputBuffer=Irp-AssociatedIrp.SystemBuffer;pOutputBuffer=Irp-AssociatedIrp.SystemBuffer;if(pInputBuffer&pOutputBuffer)DbgPrint(COMM_BufferedIoUserModeMessage=%s,pInputBuffer);RtlCopyMemory(pOutputBuffer,pInputBuffer,outputLength

14、);*sizeofWrite=outputLength;status=STATUS_SUCCESS;returnstatus;/METHOD_NEITHERNTSTATUSCOMM_NeitherIo(PIRPIrp,PIO_STACK_LOCATIONpIoStackIrp,UINT*sizeofWrite)NTSTATUSstatus=STATUS_UNSUCCESSFUL;PVOIDpInputBuffer,pOutputBuffer;ULONGoutputLength,inputLength;DbgPrint(COMM_NeitherIorn);outputLength=inputLe

15、ngth=pInputBuffer=pOutputBuffer=Irp-UserBuffer;if(pInputBuffer&pOutputBuffer)DbgPrint(COMM_NeitherIoUserModeMessage=%s,pInputBuffer);RtlCopyMemory(pOutputBuffer,pInputBuffer,outputLength);*sizeofWrite=outputLength;status=STATUS_SUCCESS;returnstatus;代码比较简单,都是取得输入的数据,然后把数据直接拷贝到输出,传输给应用层。应用层的代码:procedureTfrmMain.Send_Recv_Data(AInData:String;varAOutData:String;IoctlCode:DWORD);vardwReturn:DWORD;inData:array0.1023ofchar;outData:array0.1023ofchar;beginStrPCopy(inData,AInData);ifm_hCommDevice0thenbeginDeviceIoControl(m_hCommDevice,IoctlCode,inData,Length(inData),outData,Length(outData),dwReturn,nil

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论