关于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 ...
随机推荐
- android101 获取、备份、插入短信
package com.itheima.getsms; import java.io.File; import java.io.FileNotFoundException; import java.i ...
- C# 以ThreadStart方式实现多线程
3.1 使用ThreadStart委托 这 里先以一个例子体现一下多线程带来的好处,首先在Message类中建立一个方法ShowMessage(),里面显示了当前运行线程的Id,并使用 Threa ...
- Nginx【第一篇】安装
一.简介 Nginx("engine x")是一款是由俄罗斯的程序设计师 Igor Sysoev 所开发高性能的 Web 和 反向代理 服务器,也是一个 IMAP/POP3/SMT ...
- Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View
一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...
- android activity启动的4种方式记录及打开其他应用的activity的坑
Android启动的四种方式分别为standard,singleTop,singleTask,singleInstence. standard是最常见的activity启动方式,也是默认的启动的方式. ...
- javascript进击(六)Jquery
引用 jQuery 如需测试 JavaScript 库,您需要在网页中引用它. 为了引用某个库,请使用 <script> 标签,其 src 属性设置为库的 URL: <!DOCTYP ...
- JS设置打印页面并调用本地打印机打印页面
<script type="text/javascript"> var hkey_key; var hkey_root = "HKEY_CURRENT_USE ...
- HDU-1018(简单数学)
Big Number Problem Description In many applications very large integers numbers are required. Some o ...
- sublime中使用markdown
#为知笔记##为知笔记###为知笔记 1. 列表12. 列表23. 列表35. 顺序错了不用担心3. 写错的列表,会自动纠正 为知笔记---------------------- ```cpp int ...
- Linq语法
希望能帮助一些linq新手. 开门见山 读这篇文章之前,我先说下,每一种搜索结果集,我都以三种方式变现出来,为啦更好的理解,希望不要嫌我啰嗦. 1.简单的linq语法 //1 var ss = fro ...