关于DPC和workitem的简单用法
这个随笔是记录我半个月左右的时间,从想法到查资料请教,以及到实践的成果。
我想实现的是,隔定时时间写文件,本以为调用写的函数就可以实现了,结果各种BSOD,IRQL_NOT_LESS_OR_EQUAL,这个蓝屏提示,结果是函数的IRQL导致的,内核函数都有IRQL,我是想在DISPATCH_LEVEL中运行低级别的PASSIVE_LEVEL,因为写函数就是在PASSIVE_LEVEL上运行的。解决方法是,使用DPC,IoQueueWorkItem。下面的代码是我简单的测试了我的想法,给文件中只写入了时间和简单的数据结构信息,只适合新手,全部代码如下(注意红色标记代码):
#include<stdio.h>
#include<stdlib.h>
#include "ntddk.h" #define WRITE_FILE_INTERVAL -10000 * 1000 * 10
typedef struct my_info{
int age;
int weight;
char* name;
}myInfo, *PmyInfo;
VOID ThreadStart(IN PVOID StartContext); VOID CustomDpc(IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2); VOID SyncTechUnload(IN PDRIVER_OBJECT DriverObject);
//VOID workItem();
NTSTATUS GetLocalTime( OUT PTIME_FIELDS timeFields );
VOID TestFile(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context); KTIMER Timer; //?????????????????
PDEVICE_OBJECT DeviceObject;
PIO_WORKITEM pIoWorkItem;
LARGE_INTEGER DueTime;
KDPC Dpc;
HANDLE hThread; NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{ OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID CID;
NTSTATUS status;
UNICODE_STRING DeviceName, Win32Device; KdPrint(("dpc:DriverEntry Cur Process:%s Cur IRQL:%d\n",
(char*)((ULONG)PsGetCurrentProcess()+0x174), KeGetCurrentIrql())); RtlInitUnicodeString(&DeviceName, L"\\Device\\jay0");
RtlInitUnicodeString(&Win32Device, L"\\DosDevices\\jay0");
status = IoCreateDevice(DriverObject,
,
&DeviceName,
FILE_DEVICE_UNKNOWN,
,
FALSE,
&DeviceObject);
if(!NT_SUCCESS(status))
return status;
if(!DeviceObject)
{
KdPrint(("dpc:DeviceObject is failure\n"));
return STATUS_UNEXPECTED_IO_ERROR;
}
//初始化定时器
KeInitializeTimer(&Timer);
DriverObject->DriverUnload = SyncTechUnload;
InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
//创建一个系统线程
status = PsCreateSystemThread(
&hThread,
GENERIC_READ|GENERIC_WRITE,
&ObjectAttributes,
NtCurrentProcess(),
&CID,
(PKSTART_ROUTINE)ThreadStart,
NULL
);
if (!NT_SUCCESS(status))
{
KdPrint(("dpc:PsCreateSystemThread failure!\n"));
return ;
}
ZwClose(hThread);
KdPrint(("dpc:Exit\n"));
return STATUS_SUCCESS;
} VOID ThreadStart(IN PVOID StartContext)
{ PmyInfo pmyInfo;
KdPrint(("dpc:Cur Process: %s IRQL:%d\n",
(char*)((ULONG)PsGetCurrentProcess()+0x174), KeGetCurrentIrql()));
pmyInfo = ExAllocatePool(NonPagedPool, sizeof(myInfo));
pmyInfo->age = ;
pmyInfo->weight = ;
pmyInfo->name = "zc";
//KdPrint(("dpc: my age is %d , my weight is %d \n", context->age, context->weight));
DueTime = RtlConvertLongToLargeInteger(WRITE_FILE_INTERVAL);
//初始化一个Dpc
//这个CustomDpc是自定义的函数,运行在DISPATCH_LEVEL上,后面的参数myInfo是该函数的参数
KeInitializeDpc(&Dpc, (PKDEFERRED_ROUTINE)CustomDpc, pmyInfo);
//设置DPC定时器
KeSetTimer(&Timer, DueTime, &Dpc);
//等待定时器
KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL);
KdPrint(("dpc:ThreadStart time expire"));
return;
} //简单输出进程名和当前的IRQL,注意该函数运行在dispatch级别 VOID CustomDpc(IN struct _KDPC *Dpc,
IN PmyInfo pmyInfo,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{ KdPrint(("dpc:CustomDpc Process: %s IRQL:%d\n",
(char*)((ULONG)PsGetCurrentProcess()+0x174), KeGetCurrentIrql()));
// KdPrint(("dpc: my age is %d , my weight is %d, my name is %s\n",
// pmyInfo->age, pmyInfo->weight, pmyInfo->name)); //使用IoAllocateWorkItem分配一个ioworkitem
pIoWorkItem = IoAllocateWorkItem(DeviceObject);
// IoInitializeWorkItem(DeviceObject,pIoWorkItem); if(pIoWorkItem)
{
//插入一个workitem, 其中TestFile就是我要写文件的函数,第四个参数也是该函数的参数
IoQueueWorkItem(pIoWorkItem, (PIO_WORKITEM_ROUTINE)TestFile, DelayedWorkQueue, pmyInfo);
}
//由于要定时写,因此再次设置定时器,如果不设置只写一次
KeSetTimer(&Timer, DueTime, Dpc);
} NTSTATUS
GetLocalTime( OUT PTIME_FIELDS timeFields )
/*++
--*/
{
NTSTATUS status = STATUS_SUCCESS;
LARGE_INTEGER sysTime,locTime; KeQuerySystemTime( &sysTime );
ExSystemTimeToLocalTime( &sysTime,&locTime );
RtlTimeToTimeFields( &locTime,timeFields ); return STATUS_SUCCESS; } VOID TestFile(IN PDEVICE_OBJECT DeviceObject,
IN PmyInfo pmyInfo) {
TIME_FIELDS time;
UNICODE_STRING string;
HANDLE hFile;
IO_STATUS_BLOCK iostatus;
NTSTATUS status;
WCHAR pBuffer[];
OBJECT_ATTRIBUTES objattr;
LARGE_INTEGER ByteOffset;
KIRQL irql; RtlInitUnicodeString(&string, L"\\??\\C:\\Log\\1.log");
InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);
GetLocalTime(&time);
irql = KeGetCurrentIrql();
KdPrint(("dpc: cur irql=%d", irql));
//打开文件
status = ZwCreateFile(&hFile, FILE_APPEND_DATA,
&objattr, &iostatus,
NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, ); swprintf( pBuffer,L"[%d-%d-%d-%d-%d-%d]",
time.Year,
time.Month,
time.Day,
time.Hour,
time.Minute,
time.Second);
KdPrint(("dpc: %S", pBuffer));
KdPrint(("dpc: my age is %d , my weight is %d, my name is %s\n",
pmyInfo->age, pmyInfo->weight, pmyInfo->name));
//写文件
status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,
pBuffer, wcslen(pBuffer)*sizeof(WCHAR), NULL, NULL);
//写入换行符
status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,
L"\n", sizeof(WCHAR), NULL, NULL); //关闭文件句柄
ZwClose(hFile);
//释放内存
// ExFreePool(pBuffer); } VOID SyncTechUnload(IN PDRIVER_OBJECT DriverObject)
{ KeCancelTimer(&Timer);
IoFreeWorkItem(pIoWorkItem);
IoDeleteDevice(DriverObject->DeviceObject);
KdPrint(("dpc:DpcTest unload!\n")); }
代码赋值粘贴,编译后安装.sys,可直接运行。
关于DPC和workitem的简单用法的更多相关文章
- CATransition(os开发之画面切换) 的简单用法
CATransition 的简单用法 //引进CATransition 时要添加包“QuartzCore.framework”,然后引进“#import <QuartzCore/QuartzCo ...
- jquery.validate.js 表单验证简单用法
引入jquery.validate.js插件以及Jquery,在最后加上这个插件的方法名来引用.$('form').validate(); <!DOCTYPE html PUBLIC " ...
- NSCharacterSet 简单用法
NSCharacterSet 简单用法 NSCharacterSet其实是许多字符或者数字或者符号的组合,在网络处理的时候会用到 NSMutableCharacterSet *base = [NSMu ...
- [转]Valgrind简单用法
[转]Valgrind简单用法 http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html Valgrind的主要作者Julian S ...
- Oracle的substr函数简单用法
substr(字符串,截取开始位置,截取长度) //返回截取的字 substr('Hello World',0,1) //返回结果为 'H' *从字符串第一个字符开始截取长度为1的字符串 subst ...
- Ext.Net学习笔记19:Ext.Net FormPanel 简单用法
Ext.Net学习笔记19:Ext.Net FormPanel 简单用法 FormPanel是一个常用的控件,Ext.Net中的FormPanel控件同样具有非常丰富的功能,在接下来的笔记中我们将一起 ...
- TransactionScope简单用法
记录TransactionScope简单用法,示例如下: void Test() { using (TransactionScope scope = new TransactionScope()) { ...
- WPF之Treeview控件简单用法
TreeView:表示显示在树结构中分层数据具有项目可展开和折叠的控件 TreeView 的内容是可以包含丰富内容的 TreeViewItem 控件,如 Button 和 Image 控件.TreeV ...
- listActivity和ExpandableListActivity的简单用法
http://www.cnblogs.com/limingblogs/archive/2011/10/09/2204866.html 今天自己简单的总结了listActivity和Expandable ...
随机推荐
- 【转】http响应状态代码含义及跳转的类型
转自:http://www.west263.com/info/html/caozuoxitong/FreeBSD/20090513/123479.html 当我们在因特网遨游的时候,每天都会看到诸如5 ...
- Android软键盘调用及隐藏,以及获得点击软键盘输入的字母信息
在Android提供的EditText中单击的时候,会自动的弹出软键盘,其实对于软键盘的控制我们可以通过InputMethodManager这个类来实现.我们需要控制软键盘的方式就是两种一个是像Edi ...
- android优化(json工具,message新建/传递,avtivity深入学习视频)
1,在线json校验工具:www.bejson.com 2, 在handler中经常使用的 message的传递上,message.what使用静态量 . private static final i ...
- Building and setting up QT environment for BeagleBone
There are too few information available on how to easily setup QT environment for building Beaglebon ...
- 分享asp.net学习交流社区
亲们 最近发现一个很好的asp.net学习交流的QQ群——237221223.爱好asp.net的亲们可以加入到大家庭中去哈.大家在一起交流学习
- 【Unicode】字符编码表信息
UTF-8有点类似于Haffman编码,它将Unicode编码为:0x00-0x7F的字符,用单个字节来表示:0x80-0x7FF的字符用两个字节表示:0x800-0xFFFF的字符用3字节表示: ...
- WINDOWS Server2003上部署一个Asp.Net的网站
对于许多新手来说,如何在服务器上部署网站并不了解,这个教程希望对新手有帮助. 1.IIS服务器 2..Net Framework3.5 (方便起见,我们这里Framework说的都是指的这个版本) 这 ...
- redhat 6.4 双网卡绑定
linux系统配置 1.redhat 6.4 双网卡绑定 1)#ethtool eth* //在服务器网口接网线至笔记本,确定各网口的配置文件: 2)切换目录 #cd /etc/sysconfig/n ...
- jquery操作iframe中的js函数
关键字:jquery操作iframe中的js函数 1.jquery操作iframe中的元素(2种方式) var tha = $(window.frames["core_content&quo ...
- 调试环境部署续:vs远程调试
原文http://www.bitscn.com/weixin/464994.html 第一步 IIS的配置 进入iis,点击网址,选择你的网站,在窗口的右边编辑网站中点击绑定,如图所示. 进入网站绑 ...