除了在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;
}
驱动程序调用驱动程序1