- 浏览: 958143 次
- 性别:
- 来自: 珠海
文章分类
最新评论
-
Yunjey:
Yunjey 写道这样子的话、grid中的editable如何 ...
Flex创建可编辑以及分页的DataGrid -
Yunjey:
这样子的话、grid中的editable如何设置啊?!
Flex创建可编辑以及分页的DataGrid -
di1984HIT:
写的很好~~
JCalendar组件 -
sanny81:
此文真棒!感谢一路风尘的奉献!
但我有一疑 ...
Filter发送自定义数据详解 -
umgsai:
求完整demo umgsai@126.com
Flex和Jsp创建用户登入系统
作 者: sislcb
时 间: 2008-01-28,11:13:28
链 接: http://bbs.pediy.com/showthread.php?t=59015
这里来简单的讲解下驱动和应用层的异步通信,上次我写了驱动和应用层的三种基本通信方法,但是那三种方法都是通过同步的方法来实现的,就是说,在应用层向驱动层发送消息后,就堵死在那里等待驱动层的返回了,而异步的概念就是,应用层向驱动发送消息后,就马上返回了,而在驱动层的消息触发后,再将该消息反馈给应用层。
给个网上的例子:
同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。
其实在明白了三种通信方式后,很容易使用异步方式来通信。
在调用DeviceIoControl时,不指定FILE_FLAG_OVERLAPPED标志,表示以同步方式调用,调用线程将被阻塞直到控制操作完成.
当指定FILE_FLAG_OVERLAPPED标志调用DeviceIoControl,表示以异步方式调用,调用线程不立即阻塞,直到调用线程需要结果时,调用者调用事件等待函数,等待驱动发出事件.
在异步调用时,得使用事件(event)来通信.
下面看应用层的代码:
// 初始化时创建设备 procedure TfrmMain.FormCreate(Sender: TObject); begin //创建设备 try m_hCommDevice := CreateFile('\\.\Overlapp', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0); //执行异步I/O的设备必须用FILE_FLAG_OVERLAPPED标志打开 hEvent := CreateEvent( nil, False, False, nil); //创建自动重置的事件 except MessageBox(Handle, '创建设备失败', '驱动应用层通信', MB_OK + MB_ICONWARNING); end; end; //异步通信按钮,创建线程和驱动通信 procedure TfrmMain.btnBufferdClick(Sender: TObject); var hThread:THandle; dwThreadID:DWORD; begin hThread := CreateThread(nil, 0, @WaitForNotify, self, 0, dwThreadID); CloseHandle(hThread); end; //线程的处理代码 //初始化一个OVERLAPPED 结构,然后用DeviceIoControl来通信 //在WaitForSingleObject等待返回 procedure WaitForNotify; var dwReturn: DWORD; inData:array[0..1023] of char; outData:array[0..1023] of char; ol:OVERLAPPED ; begin StrPCopy(inData, Trim(frmMain.edtBufferd_in.Text)); //OVERLAPPED结构的Offset,OffsetHigh和hEvent成员必须被初始化。在这里初始化为0 FillMemory(@ol, sizeof(OVERLAPPED), 0); ol.hEvent := frmMain.hEvent; if frmMain.m_hCommDevice <> 0 then DeviceIoControl(frmMain.m_hCommDevice, IOCTL_OVERLAP_BUFFERED_IO, @inData, Length(inData), @outData, Length(outData), dwReturn, @ol); //调用WaitForSingleObject并传递设备内核对象的句柄。WaitForSingleObject会挂起调用线程直至内核对象变成有信号态。 //设备驱动在它完成I/O后使内核对象有信号。在WaitForSingleObject返回后,I/O被完成 . while WaitForSingleObject(frmMain.hEvent, 100) = WAIT_TIMEOUT do begin end; GetOverlappedResult(frmMain.m_hCommDevice, ol, dwReturn, TRUE); frmMain.edtBufferd_out.Text := outData; end; //这里触发驱动将数据传输回来,异步消息得以完成 procedure TfrmMain.btnNotifyClick(Sender: TObject); var dwReturn:DWORD; begin if m_hCommDevice <> 0 then DeviceIoControl(m_hCommDevice, IOCL_OVERLAP_NOTIFY, nil, 0, nil, 0, dwReturn, nil); end; //退出时,关闭句柄,这时候如果irp还未处理,即btnNotifyClick这个函数没有触发 //则驱动中会触发取消irp的请求。 procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); begin if(m_hCommDevice <> 0) then CloseHandle(m_hCommDevice); if (hEvent <> 0) then CloseHandle(hEvent); end;
驱动层代码
//接受到消息的处理函数 NTSTATUS Overlap_IoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status = STATUS_NOT_SUPPORTED; PIO_STACK_LOCATION irpStack = NULL; UINT sizeofWrite = 0; DbgPrint("Overlap_IoControl\r\n"); irpStack = IoGetCurrentIrpStackLocation(Irp); if(irpStack) { switch(irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_OVERLAP_BUFFERED_IO: //异步通信消息 status = Irp->IoStatus.Status = STATUS_PENDING; Irp->IoStatus.Information = 0; IoMarkIrpPending(Irp); gUserMessageIrp = Irp;//保存请求的irp IoSetCancelRoutine(Irp, DriverCancelIrp); //设置irp取消例程,在应用程序退出时,触发 return status; case IOCL_OVERLAP_NOTIFY: //获取数据事件 COMM_BufferedIo(gUserMessageIrp, irpStack); //处理原来的irp,将传进来的数据传输出去 return status; default: return status; } } return status; } //当通知要获取数据时,获得异步的irp,然后传输数据 NTSTATUS COMM_BufferedIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_BufferedIo\r\n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pOutputBuffer = Irp->AssociatedIrp.SystemBuffer; //输出缓冲区 pInputBuffer = Irp->AssociatedIrp.SystemBuffer; //输入缓冲区 if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_BufferedIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(pOutputBuffer); IoCompleteRequest(Irp,IO_NO_INCREMENT); //设置该irp已经完成 status = STATUS_SUCCESS; } return status; } //取消irp的例程 VOID DriverCancelIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { //UNREFERENCED_PARAMETER这个宏用于去掉一个函数的参数未用或函数中定义了一个局部变量却从未用过的编译警告 UNREFERENCED_PARAMETER(DeviceObject); KdPrint(("UserMessageCancelIrp....\n")); if ( Irp == gUserMessageIrp) gUserMessageIrp = NULL; Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp,IO_NO_INCREMENT); }
流程如下:
1、
应用层:
通知异步消息
等待返回
驱动层:
收到消息
设置irp取消例程
保存该irp
2、
应用层:
通知获取数据,即完成异步消息
驱动层:
拷贝数据到输出缓冲区,完成该irp
在这里我是通过手动的方式来触发异步消息的完成,而不是由系统的消息触发的。主要是为了演示的方便
发表评论
-
Filter驱动:过滤(修改)接受数据包
2010-04-20 16:18 9215Filter驱动可以实现简单的防火墙功能。它可以过滤所有接收到 ... -
Ndis过滤驱动:拷贝NetBufferList数据
2010-04-19 22:40 9449今天我们来看看如何拷贝NBL中的数据。有时候需要更改数据包中的 ... -
在Filter驱动内核中获取IP地址
2010-04-18 01:48 3845项目开发中有时候需要在Filter驱动中获取有效地Unic ... -
如何在内核中获得当前系统时间
2010-04-16 15:08 2660在 Windows NT 内核中你是无法使用 tim ... -
Filter发送自定义数据详解
2010-04-16 10:30 5683... -
DebugPrint 格式说明符
2010-04-13 19:46 17241) 直接打印字符串。 DbgPrint(“Hello ... -
WDK+Visual Studio 2008配置编译驱动
2010-04-12 23:36 5519Introduction As it is known, ... -
疑问:关于内存释放
2010-04-12 21:33 1408今天碰到一个比较棘手的内存处理问题。 首先来看一个数据结构: ... -
Windows NT 驱动程序开发人员提示 -- 应注意避免的事项
2010-04-10 11:32 2284原讨论链接: http://community.cs ... -
关于DeviceIoControl实现异步的笔记【2】
2010-04-09 23:17 5040前面我们谈到了关于异步I/O的实现:关于DeviceIoCon ... -
关于DeviceIoControl实现异步的笔记【1】
2010-04-08 22:26 11635一直所做的都是同步实现的。当然很多情况这并不是很好的解决问题。 ... -
Windows系统编程之异步I/O和完成端口
2010-04-08 19:40 2222一、 同步I/O和异步I/O ... -
纵横捭阖C++之从异步谈起
2010-04-08 19:31 3138一般来说,简单的异步(Asynchronous)调用是这样一种 ... -
使用DeviceIoControl通信
2010-04-04 22:53 7844在很多时候,某些用户需要与底层驱动有一个交互式的操作,所 ... -
在驱动中使用链表
2010-04-03 14:06 3238文章作者:grayfox 作 ... -
疑问:数据包Length增大的原因
2010-04-01 14:35 1326现象: 自己定义一个仅含有Ethernet Header的数 ... -
疑问:为何无线网卡无法发送数据?
2010-03-30 22:42 4481所有的测试流程表明,程序已经成功的创建新的数据包,然后调用Nd ... -
InsertHeadList和CONTAINING_RECORD
2010-03-29 16:36 3718LIST_ENTRY定义一个双向链表的数据结构: typed ... -
如何区分不同的Filter Module Instance
2010-03-29 14:50 1504前文 说到如何区分不同Filter Module Inst ... -
大数据是否需要封装在多个MDL中发送
2010-03-27 21:40 2463前段时间,我们已经解决如何发送自定义的网络数据。那么接下来要做 ...
相关推荐
应用程序和驱动通讯同步
要介绍Windows操作系统内核的基本概念,同时还介绍应用程序和驱动程序之间的通信方法。 2.1 Windows操作系统概述 2.1.1 Windows家族 2.1.2 Windows特性 2.1.3 用户模式和内核模式 2.1.4 操作系统与...
本章主要介绍Windows操作系统内核的基本概念,同时还介绍应用程序和驱动程序之间的通信方法。 2.1 Windows操作系统概述 2.1.1 Windows家族 2.1.2 Windows特性 2.1.3 用户模式和内核模式 2.1.4 操作...
网络驱动程序设计指南的向导 3 第二章 内核模式驱动程序的网络结构 6 2.1 Windows 2000 网络结构和OSI模型 6 2.2 NDIS驱动程序 7 2.2.1 NDIS微端口驱动程序 7 2.2.2 NDIS中间层驱动程序 8 2.2.3 ...
第三部分NDIS中间层驱动程序和TDI驱动程序 189 第一章 NDIS中间层驱动程序 189 1.1中间层驱动程序的DriverEntry函数 191 1.1.1 注册NDIS中间层驱动程序 191 1.1.1.1注册中间层驱动程序的Miniport 192 1.1.1.2注册...
总线、设备和驱动程序 类 各环节的整合 热插拔 处理固件 快速索引 第十五章 内存映射和DMA Linux的内存管理 mmap设备操作 执行直接I/O访问 直接内存访问 快速参考 第十六章 块设备驱动程序 注册 块...
11.2.1在virtualfifo驱动中增加异步通知 11.2.2在用户空间验证virtualfifo的异步通知 第12章Linux块设备驱动 12.1块设备的I/O操作特点 12.2 Linux块设备驱动结构 12.2.1 block_device_operations结构体 12.2.2 ...
8.5.4 端口驱动和类驱动之间的协作机制 129 8.5.5 找到关键的回调函数的条件 129 8.5.6 定义常数和数据结构 130 8.5.7 打开两种键盘端口驱动寻找设备 131 8.5.8 搜索在KbdClass类驱动中的地址 133 8.6 Hook键盘...
8.5.4 端口驱动和类驱动之间的协作机制 129 8.5.5 找到关键的回调函数的条件 129 8.5.6 定义常数和数据结构 130 8.5.7 打开两种键盘端口驱动寻找设备 131 8.5.8 搜索在KbdClass类驱动中的地址 133 8.6 Hook键盘...
6.1 PC机异步通信适配器8250及其编程操作 6.1.1 INS8250内部寄存器及其选择方式 6.1.2 波特率设置 6.1.3数据位、奇偶校验、停止位等数据格式设置 6.1.4 查询I/O方式相关设置 6.1.5 中断I/O通信方式相关...
6.1 pc机异步通信适配器8250及其编程操作 169 6.1.1 ins8250内部寄存器及其选择方式 169 6.1.2 波特率设置 169 6.1.3 数据位、奇偶校验、停止位等数据格式设置 170 6.1.4 查询i/o方式相关设置 171 6.1.5 中断i/...
6.1 PC机异步通信适配器8250及其编程操作 169 6.1.1 INS8250内部寄存器及其选择方式 169 6.1.2 波特率设置 169 6.1.3 数据位、奇偶校验、停止位等数据格式设置 170 6.1.4 查询I/O方式相关设置 171 6.1.5 中断I/O通信...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...
13.1.3 NDIS中间层驱动的应用 438 13.1.4 NDIS包描述符结构深究 439 13.2 中间层驱动的入口与绑定 442 13.2.1 中间层驱动的入口函数 442 13.2.2 动态绑定NIC设备 443 13.2.3 小端口初始化(MpInitialize) 445 13.3 ...