关于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 ...
随机推荐
- 蘑菇街IM
https://github.com/mogutt TTServer 蘑菇街TeamTalk之消息服务器 Updated 2 days ago Shell 122 208 TTAutoDeploy ...
- Android软键盘调用及隐藏,以及获得点击软键盘输入的字母信息
在Android提供的EditText中单击的时候,会自动的弹出软键盘,其实对于软键盘的控制我们可以通过InputMethodManager这个类来实现.我们需要控制软键盘的方式就是两种一个是像Edi ...
- $GLOBALS['HTTP_RAW_POST_DATA'] 和$_POST的区别(转)
---恢复内容开始--- $_POST:通过 HTTP POST 方法传递的变量组成的数组.是自动全局变量. $GLOBALS['HTTP_RAW_POST_DATA'] :总是产生 $HTTP_RA ...
- 使用HttpURLConnection实现在android客户端和服务器之间传递对象
一般情况下,客户端和服务端的数据交互都是使用json和XML,相比于XML,json更加轻量级,并且省流量,但是,无论我们用json还是用xml,都需要我们先将数据封装成json字符串或者是一个xml ...
- NIO学习:使用Channel、Buffer写入文件
NIO的效率要高于标准IO,因为NIO将最耗时的IO操作(填充和提取缓冲区)转移会操作系统.NIO以块为单位传输数据,相比标准IO的以字节为单位效率要高很多. 通道和缓冲时NIO的核心对象,每个NIO ...
- Objective-c中autorelease的释放时机
如果你使用过MRR,autorelease这个关键字应该是太熟悉了,每次在我们生成一个新的对象返回时,都需要向这个对象发送autorelease消息,目的是为了延时释放创建的对象.那到底是在什么时候, ...
- Asp.net上传出现“超过了最大请求长度”的问题解决方法
在开发ASP.NET网站后台管理系统时,我们可能会遇到这样的问题:上传大于4M的文件时,会提示错误:错误信息如下: 1.异常详细信息:超过了最大请求长度. 2.引发异常的方法:Byte[] GetEn ...
- 怎么用js代码改变单选框的选中状态
今天突然有一个需求要用到,使用js代码改变单选框的选中状态.当时想也不想直接 function doGender(gender) { if (gender == "男") { ge ...
- 使用ICSharpZipLib将文件夹压缩为zip文件
序言: 在我接触Git和SVN之前,我最常用的保存数据的办法就是把文件夹压缩成一个zip文件,添加上时间戳.下面是我在学习C#的文件操作之后做的一个练习,使用开源的ICSharpZipLib来 ...
- nyoj89 汉诺塔(二)
题目网址 :http://acm.nyist.net/JudgeOnline/problem.php?pid=89 汉诺塔问题的经典结论: 把i个盘子从一个柱子整体移到另一个柱子最少需要步数是 2的i ...