关于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 ...
随机推荐
- oepn sync
http://blog.csdn.net/cywosp/article/details/8767327 SYNOPSIS #include <sys/types.h> #include & ...
- Android SmsManager 发送短信
SmsManager可以在后台发送短信,无需用户操作,开发者就用这个SmsManager功能在后台偷偷给SP发短信,导致用户话费被扣.必须添加android.permission.SEND_SMS权限 ...
- VS C# 快捷键
解决VS2010中工具箱的的不见的问题:按快捷键Ctrl+Alt+X 全屏:Shift+Alt+Enter注释选定内容:Ctrl+E+C/Crtr+E+U代码格式化:ctrl+E+F ======== ...
- linux的nohup disown setsid screen
```nohup 可以将进程挂起 帐号退出时不受影响 nohup cp -r a b/ [>/~/cp.log] & setsid 作用类似于nohup swtsid cp -r a b ...
- cobbler部署
1.cobbler介绍 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的 ...
- Atom编辑器入门到精通(四) Atom使用进阶
在本节中将介绍Atom提供的更高级的使用技巧,通过这些技巧将会进一步提高你的代码编写效率 代码片段(Snippets) Snippets是一种在代码中快捷插入代码块的方式,下面是维基百科中对Snipp ...
- 百度编辑器1.4.3 .net版在vs2008的使用方法
由于在官方下载的ueditor包是在vs2012下开发的,可以在vs2010中使用,但在vs2008中就会报错.折腾了一翻,现将解决方法分享给需要的朋友,其实就是把里面包含.net4.0的元素换成.n ...
- PhotoView开源项目剖析
http://blog.csdn.net/wu928320442/article/details/43056731 介绍 上一节呢,我们介绍了怎么下载和编译Android源码,这节呢,我们来讨论Pho ...
- eclipse Ctrl+1 没反应
今天上午写代码,突然发现Ctrl+1没反应了,顿时无语.昨天还好好的,今天就不行了…… 无奈,只好在网上查了查,据说快捷键冲突的原因比较大. 于是我将Ctrl+1换成了Alt+1.在eclipse中测 ...
- CentOS 6.4安装OpenOffice
终端依次输入: (1)sudo yum install openoffice.org-writer (2) sudo yum install openoffice.org-calc (3) sudo ...