[转帖]驱动程序怎样和应用程序通信?

yaos yaos 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
[转帖]驱动程序怎样和应用程序通信?
驱动程序怎样和应用程序通信?
作者:Huyg

1、内核通知应用层方法:
a、如果是vxd,使用shell_postmessage是最简单的方法,但是只能传递两个DWORD。walter oney的
那本关于vxd的书中有更详细的描述,该书的中文版可以在侯俊杰的网站上下载。还有一本关于vxd得好书,
《windows vxd与设备驱动权威指南》,孙喜明译,作者名字太怪,我记不住,但是个msj上的牛人。这本
书翻译的不错,孙喜明是98/99活跃在tsinghua bbs上的vxd高手。
b、如果是sys,思路如下:首先在driver中IoCreateDevice,然后让应用层创建一个线程,调用deviceioctl,
异步调用,然后等待事件。驱动程序到了需要通知应用层的时候,iocompleteirp,应用层的那个事件就
变成有信号的,然后就可以得到通知的数据。你可以参考我的代码(附件1,附件2)。该方法同样适用于
vxd,但是由于vxd没有系统队列的概念,因此你需要使用自定义队列管理应用层请求。稍稍费劲,可以参考
98ddk\src\net\ndis\vpacket目录下的实现。


附件1、
请注意看notifyevent函数。
当驱动程序需要通知应用层的时候,调用notifyevent函数。

/*++

Copyright (c) 2001

Module Name:

devctrl.c

Abstract:


Author:

Environment:


Revision History:


--*/


#include "ioctl.h"


NTSTATUS
IM_CTRL_Open(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)

/*++

Routine Description:

This is the dispatch routine for create/open and close requests.
These requests complete successfully.

Arguments:

DeviceObject - Pointer to the device object.

Irp - Pointer to the request packet.

Return value:

Status is returned.

--*/

{
NTSTATUS status = STATUS_SUCCESS;

DBGPRINT(("OpenAdapter\n"));

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;

}


NTSTATUS
IM_CTRL_Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)

/*++

Routine Description:

This is the dispatch routine for create/open and close requests.
These requests complete successfully.

Arguments:

DeviceObject - Pointer to the device object.

Irp - Pointer to the request packet.

Return value:

Status is returned.

--*/

{

NTSTATUS status = STATUS_SUCCESS;

DBGPRINT(("CloseAdapter \n"));

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}

NTSTATUS
IM_CTRL_Cleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)

/*++

Routine Description:

This is the dispatch routine for cleanup requests.
This routine is called whenever a handle to the device
is closed.

Arguments:

DeviceObject - Pointer to the device object.

Irp - Pointer to the request packet.

Return value:

Status is returned.

--*/

{

NTSTATUS status = STATUS_SUCCESS;

DBGPRINT(("Packet: Cleanup\n"));

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
/*
VOID
IM_CTRL_Unload(
IN PDRIVER_OBJECT DriverObject
)
{

UNICODE_STRING win32DeviceName;

DBGPRINT(("Unload Enter\n"));

//
// First delete the Control deviceobject and the corresponding
// symbolicLink
//

RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.ControlDeviceObject)
IoDeleteDevice(Globals.ControlDeviceObject);

DBGPRINT(("Unload Exit\n"));

}
*/

NTSTATUS
IM_CTRL_IoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
ULONG RequireLength=0;
PADAPT pAdapt;
UINT AdapterNum;
PDEVICE_EXTENSION pDevExt;
KIRQL OldIRQL;

pDevExt = DeviceObject->DeviceExtension;

irpStack = IoGetCurrentIrpStackLocation(Irp);

ioControlCode= irpStack->Parameters.DeviceIoControl.IoControlCode;

ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
Status = NDIS_STATUS_SUCCESS;

KeAcquireSpinLock(&ImdGlobals.SpinLock,&OldIRQL);

switch (ioControlCode)
{
case GET_EVENT_MSG:
if(outputBufferLength<sizeof(EVENTMSG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}

IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject,Irp,NULL,CancelIrp);
Status = STATUS_PENDING;
KeReleaseSpinLock(&ImdGlobals.SpinLock,OldIRQL);
return Status;
case SET_OPTION :
// ............ more case
default:
Status = STATUS_INVALID_PARAMETER;
break;
}

KeReleaseSpinLock(&ImdGlobals.SpinLock,OldIRQL);

Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = outputBufferLength;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

return Status;
}

VOID
CancelIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
if(Irp == DeviceObject->CurrentIrp)
{
IoReleaseCancelSpinLock(Irp->CancelIrql);
IoStartNextPacket(DeviceObject,TRUE);
}
else
{
KeRemoveEntryDeviceQueue(
&DeviceObject->DeviceQueue,
&Irp->Tail.Overlay.DeviceQueueEntry
);
IoReleaseCancelSpinLock(Irp->CancelIrql);
}
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return;
}

VOID
StartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
return;
}

BOOLEAN
NotifyEvent(
IN PEVENTMSG EventMsg
)
{
PDEVICE_OBJECT DeviceObject = ImdGlobals.ControlDeviceObject ;
PIRP Irp ;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
KIRQL CancelIrql;

Irp = DeviceObject->CurrentIrp;

if(!Irp) return FALSE;

IoAcquireCancelSpinLock(&CancelIrql);
if(Irp->Cancel)
{
IoReleaseCancelSpinLock(CancelIrql);
return FALSE;
}
IoSetCancelRoutine(Irp,NULL);
IoReleaseCancelSpinLock(CancelIrql);
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

if(outputBufferLength<sizeof(EVENTMSG))
{
outputBufferLength = 0;
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
RtlCopyMemory(ioBuffer,EventMsg,sizeof(EVENTMSG));
outputBufferLength = sizeof(EVENTMSG);
}

Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = outputBufferLength;

IoStartNextPacket(DeviceObject,TRUE);

IoCompleteRequest(Irp,IO_NO_INCREMENT);

return TRUE;

}


...全文

相关推荐

windows wdm驱动的例子,采用异步完成的方式实现驱动程序和应用程序通信的程序

WDM驱动程序是可扩展的,能够支持各种类型的硬件设备,从简单的输入设备到复杂的网络适配器。在这个例子中,我们将探讨如何通过异步完成来实现驱动程序和应用程序之间的通信。

lj_70596

CancelSample_familiarfjb_twicenyf_驱动程序和应用程序通信_

标题“CancelSample_familiarfjb_twicenyf_驱动程序和应用程序通信_”涉及的是一个关于驱动程序与应用程序间通信的示例,特别是在IO操作中如何处理取消请求的主题。

肝博士杨明博大夫

应用程序与驱动程序应用程序与驱动程序

### 应用程序与驱动程序详解#### 一、什么是应用程序?在计算机系统中,操作系统可以被视为电脑的大脑,负责管理整个系统的资源和各种服务。

yupaomoweiwu

如何建立应用程序和驱动程序间的通信.ring3的exe怎么调用ring0的驱动程序

本文将深入探讨在Windows环境下如何实现应用程序(Ring 3级别)与驱动程序(Ring 0级别)之间的通信,特别关注Ring 3级别的EXE(可执行文件)调用Ring 0级别的设备驱动程序的具体

lj_70596

IMX6Q EIM接口和FPGA通信驱动及应用程序

接着,我们将讨论如何编写Linux驱动程序。驱动程序是操作系统与硬件之间的桥梁,它负责初始化硬件,管理中断处理,并提供给应用程序的接口。

who8023me
评论 4
收藏 已收藏
分享
返回顶部
yaos
驱动开发/核心开发 21,620 成员 21,709 内容