关于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 ...
随机推荐
- 【solr基础教程之九】client
一.Java Script 1.因为Solr本身能够返回Json格式的结果,而JavaScript对于处理Json数据具有天然的优势,因此使用JavaScript实现Solrclient是一个非常好的 ...
- C++ ComboBox基础
关键点 实现过程 //添加 //添加字符串 m_cbo1.AddString("AAA"); m_cbo1.AddString("BBB"); m_cbo1.A ...
- dubbo与spring mvc
安装 一.本地服务 1.定义服务接口: (该接口需单独打包,在服务提供方和消费方共享) public interface CustomerService { public String get ...
- qt QSqlQuery
QT数据库QSqlQuery SQL执行操作 QSqlQuery提供了对数据库记录的Select.Insert.Update.Delete操作. SELECT操作: QSqlQuery query ...
- oralce表空间自增长占满磁盘
取消表空间自动增长 SELECT FILE_NAME,TABLESPACE_NAME,AUTOEXTENSIBLE,bytes/1024/1024/1024 FROM dba_data_files; ...
- 安卓UI美化_drawable
UI美化 drawable资源 ------------------------------------------state drawable资源在不同状态下显示不同的图片在<selector ...
- ArcGIS Server JavaScript API 各命名空间的含义【转】
1.esri 命名空间 所有的对象都是在 esri 命名空间下的,esri 有自己的属性和方法. 如 esri.version 返回当前 JavaScript API 的版本号.e ...
- CentOS6.3挂载读写NTFS分区
CentOS不像Fedora,默认是没有自动挂载NTFS的,而它可以利用NTFS-3G来实现挂载及读写. NTFS-3G 是一个开源的软件,可以实现 Linux.Free BSD.Mac OSX.Ne ...
- css实现基础几何图形
我们知道,css3通过border-radius.animation.transform等“新”特性可以绘制很多精致的图形.比如腾讯企鹅Logo.超能陆战队中的大白机器人.太阳系.小黄人.叮当猫.安卓 ...
- Linux云主机安装JDK,配置hadoop的详细方式
云主机我使用的是青云的,还有好多其他品牌,比如阿里云 unitedstack 等等. 注册完青云后,会有试用券发到账户,可以利用此券试用其服务. 1 首先创建好一个主机,按照提示选择好系统,创建好一个 ...