除了在Win32下面可以调用ReadFile, WriteFile之类的函数打开设备对象, 在内核中也是可以的, 而且方法比用户态这边更多. 首先这种方法就是Win32上面相同的方式了, 直接打开设备. 内核也有一套函数类似Win32下面的CreateFile, WriteFile, ReadFile.
下面代码那个写入设备基本就没有什么好说的. 和Win32上面的套路差不多, Win32上面其实也有一个WriteFileEx. 就是可以设置回调函数那个. 内核里面的函数就合二为一了, 都是ZwWriteFile,看心情, 如果喜欢用回调函数那就用回调函数. 如果不喜欢用回调函数那么就NULL, 就OK了..
在打开设备的时候不但可以使用设备名称来打开,
也可以利用符号链接名称来打开, 总之Win32下面有的, 内核里面都有了,
而且更暴力!很好很强大!
主要说说这个读取设备这块, 读取设备的时候, 也用了事件对象,
不过这里的事件对象用的是设备句柄的文件句柄, 我倒. 有点绕啊, 其实是这样的, 每打开一个文件句柄,
都会伴随着存在一个关联的文件对象(File_Object). 利用内核函数ObReferenceObjectByHandle可以获取设备相关的文件句柄的指针.当IRP_MJ_READ请求被结束的时候,
文件对象的Event会被设置,
因此可以利用这个Event对象来做同步.下面的代码正是这样做的. 当然, 这个要记得在后面调用ObDereferenceObject,
来解引用.
我在调用ObReferenceObjectByHandle的时候老是返回失败, 后来google一下, 发现第3个参数设置为NULL就没有问题了, 所以我也就这样做了. 不知为何. 这里先留下这个问题. 回头再倒腾!
现在这套打开设备, 读写的函数. 其实和Win32下面是差不多的, 所以不说了. 直接上代码:首先是测试驱动:
/*
Windows 内核下驱动程序调用驱动程序 测试驱动
编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>
#define DEVICE_NAME L"\\Device\\DevTestDriver"
#define SYSLINK_NAME L"\\??\\SysLinkTestDriver"
typedef struct tagDeviceExt {
KDPC StDpc;
PIRP pIrp;
KTIMER StTimer;
PVOID pBuf;
PDEVICE_OBJECT pDeviceObj;
UNICODE_STRING USzDeviceName;
UNICODE_STRING USzSysLinkName;
} DEVICE_EXT, *PDEVICE_EXT;
//===========================================================================
//驱动卸载例程
//===========================================================================
#pragma code_seg( "PAGE" )
VOID DriverUnLoad( PDRIVER_OBJECT pDriverObj ) {
PDEVICE_EXT pDeviceExt = NULL;
PDEVICE_OBJECT pNextDeviceObj = NULL;
pNextDeviceObj = pDriverObj->DeviceObject;
while ( pNextDeviceObj != NULL ) {
pDeviceExt = pNextDeviceObj->DeviceExtension;
IoDeleteDevice( pDeviceExt->pDeviceObj );
IoDeleteSymbolicLink( &pDeviceExt->USzSysLinkName );
if ( pDeviceExt->pBuf != NULL ) {
ExFreePool( pDeviceExt->pBuf );
}
KdPrint( ( "删除设备%wZ成功!\n", &pDeviceExt->USzDeviceName ) );
pNextDeviceObj = pNextDeviceObj->NextDevice;
}
}
//===========================================================================
//所有不关系的Irp处理
//===========================================================================
NTSTATUS DispathRoutine( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
//===========================================================================
//超时Dpc例程
//===========================================================================
#pragma code_seg()
VOID OnTimerDpc( PKDPC pDpc, PVOID pContext, PVOID SysArg1, PVOID SysArg2 ) {
PIRP pIrp = NULL;
PCHAR pBuf = NULL;
ULONG ulBufLen, i;
NTSTATUS Status;
PDEVICE_EXT pDeviceExt = NULL;
PDEVICE_OBJECT pDeviceObj = NULL;
PIO_STACK_LOCATION Stack = NULL;
PAGED_CODE_LOCKED();
//---------------------------------------------------------------------------
pDeviceObj = ( PDEVICE_OBJECT )pContext;
pDeviceExt = pDeviceObj->DeviceExtension;
pIrp = pDeviceExt->pIrp;
ASSERT ( pIrp != NULL );
Stack = IoGetCurrentIrpStackLocation( pIrp );
Status = STATUS_SUCCESS;
do {
pBuf = pIrp->AssociatedIrp.SystemBuffer;
if ( pBuf == NULL ) {
ulBufLen = 0;
Status = STATUS_UNSUCCESSFUL;
break;
}
//---------------------------------------------------------------------------
if ( Stack->MajorFunction == IRP_MJ_WRITE ) {
ulBufLen = Stack->Parameters.Write.Length;
for( i = 0; i < ulBufLen; i++ ) {
KdPrint( ( "%c\t", *( pBuf + i ) ) );
}
KdPrint( ( "\n" ) );
pDeviceExt->pBuf = ExAllocatePool( NonPagedPool, ulBufLen );
ASSERT( pDeviceExt->pBuf );
RtlCopyMemory( pDeviceExt->pBuf, pBuf, ulBufLen );
KdPrint( ( "TestDriver: 超时Dpc例程IRP_MJ_WRITE离开!\n" ) );
//---------------------------------------------------------------------------
} else if( Stack->MajorFunction == IRP_MJ_READ ) {
ulBufLen = Stack->Parameters.Read.Length;
ASSERT( pDeviceExt->pBuf != NULL );
RtlCopyMemory( pBuf, pDeviceExt->pBuf, ulBufLen );
KdPrint( ( "TestDriver: 超时Dpc例程IRP_MJ_READ离开!\n" ) );
}
} while ( FALSE );
pIrp->IoStatus.Information = ulBufLen;
pIrp->IoStatus.Status = Status;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
}
//===========================================================================
//写入请求
//===========================================================================
#pragma code_seg( "PAGE" )
NTSTATUS DispatchWrite ( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
LARGE_INTEGER liTimeOut;
PDEVICE_EXT pDeviceExt = NULL;
pDeviceExt = pDeviceObj->DeviceExtension;
pDeviceExt->pIrp = pIrp;
//挂起Irp
IoMarkIrpPending( pIrp );
//设置超时时间为3S
liTimeOut = RtlConvertLongToLargeInteger( -10 * 3000 * 1000 );
//开启定时器
KeSetTimer( &pDeviceExt->StTimer, liTimeOut, &pDeviceExt->StDpc );
KdPrint( ( "TestDriver: DispatchWrite挂起!\n" ) );
return STATUS_PENDING;
}
//===========================================================================
//读取请求
//===========================================================================
NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
LARGE_INTEGER liTimeOut;
PDEVICE_EXT pDeviceExt = NULL;
pDeviceExt = pDeviceObj->DeviceExtension;
pDeviceExt->pIrp = pIrp;
//挂起Irp
IoMarkIrpPending( pIrp );
//设置超时时间为3S
liTimeOut = RtlConvertLongToLargeInteger( -10 * 3000 * 1000 );
//开启定时器
KeSetTimer( &pDeviceExt->StTimer, liTimeOut, &pDeviceExt->StDpc );
KdPrint( ( "TestDriver: DispatchRead 挂起!\n" ) );
return STATUS_PENDING;
}
//===========================================================================
//驱动入口
//===========================================================================
#pragma code_seg( "INIT" )
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
NTSTATUS Status;
ULONG i;
PDEVICE_OBJECT pDeviceObj = NULL;
PDEVICE_EXT pDeviceExt = NULL;
UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME );
UNICODE_STRING USzSysLinkName = RTL_CONSTANT_STRING( SYSLINK_NAME );
Status = IoCreateDevice( pDriverObj, sizeof( DEVICE_EXT ), &USzDeviceName,
FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint( ( "创建设备失败!\n" ) );
return Status;
}
// Status = IoCreateSymbolicLink( &USzSysLinkName, &USzDeviceName );
// if ( !NT_SUCCESS( Status ) ) {
// KdPrint( ( "创建符号链接失败!\n" ) );
// IoDeleteDevice( pDeviceObj );
// }
pDeviceObj->Flags |= DO_BUFFERED_IO;
pDeviceExt = pDeviceObj->DeviceExtension;
pDeviceExt->pDeviceObj = pDeviceObj;
pDeviceExt->USzDeviceName = USzDeviceName;
pDeviceExt->USzSysLinkName = USzSysLinkName;
pDeviceExt->pBuf = NULL;
//初始化Timer对象和定时器对象
KeInitializeTimer( &pDeviceExt->StTimer );
KeInitializeDpc( &pDeviceExt->StDpc, &OnTimerDpc, ( PVOID ) pDeviceObj );
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
pDriverObj->MajorFunction[i] = &DispathRoutine;
}
pDriverObj->MajorFunction[IRP_MJ_WRITE] = &DispatchWrite;
pDriverObj->MajorFunction[IRP_MJ_READ] = &DispatchRead;
pDriverObj->DriverUnload = &DriverUnLoad;
return Status;
}
原文地址:http://www.cnblogs.com/adylee/p/3714287.html