除了在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