《天书夜读:从汇编语言到windows内核编程》九 时间与定时器
1)使用如下自定义函数获取自系统启动后经历的毫秒数:KeQueryTimeIncrement、KeQueryTickCount
void MyGetTickCount(PULONG msec) { LARGE_INTEGER tick_count; ULONG myinc = KeQueryTimeIncrement(); //返回每次时钟中断,系统时间增加的纳秒数 KeQueryTickCount(&tick_count); //返回自系统启动以来经历的定时器中断次数 tick_count.QuadPart *= myinc; //计算从系统启动来经历多的总纳秒数(纳秒为一个单位) tick_count.QuadPart /= ; //转换为毫秒数(/10则取微秒) *msec = tick_count.LowPart; //取低字节(也可以取整个LAGER_INTEGER,改变传入参数) }
测试代码:
DbgPrint("first: Hello,my salary!"); ULONG msec1 = 0L; ULONG msec2 = 0L; MyGetTickCount(&msec1); KdPrint(("msec1:%d ms",msec1)); ; i< ; i++) { MyGetTickCount(&msec2); } MyGetTickCount(&msec2); KdPrint(("msec2:%d ms",msec2)); KdPrint((,(msec2-msec1)%));
输出结果:
2)获取当前系统时间:KeQuerySystemTime、ExSystemTimeToLocalTime、RtlTimeToTimeFields
PWCHAR MyCurTimeStr() { LARGE_INTEGER snow,now; TIME_FIELDS now_fileds; //定义静态变量缓冲区,这里先不考虑多线程隐患 ] = {}; //获取标准时间(格林威治时间) KeQuerySystemTime(&snow); //转换为当地时间 ExSystemTimeToLocalTime(&snow,&now); //转换为可理解要素 RtlTimeToTimeFields(&now,&now_fileds); //格式化到字符串 RtlStringCchPrintfW(time_str,//缓冲区 *,//缓冲区长度 L"%04d-%02d-%02d %02d:%02d:%02d", now_fileds.Year,now_fileds.Month,now_fileds.Day, now_fileds.Hour,now_fileds.Minute,now_fileds.Second); return time_str; }
测试代码:KdPrint(("%ws",MyCurTimeStr()));
输出结果:
3)中断级:内核代码都运行在一定的中断级上,从微观上看代码的运行并不连续(异常发生、中断发生、线程切换等)。在高中断级运行的代码不会被在低中断级运行的代码打断,帮助文档对每个API应该在什么中断级范围内使用均有说明,中断级高低为:Dispatch>APC>Passive。
4)使用定时器:KeSetTimer、KeInitializeTimer、KeInitializeDpc、CustomDpc、KeCancelTimer
定时器的CustomDpc运行在APC中断级,所以定时器并不是可以用来定时做任何事情。
//内部时钟结构 typedef struct MY_TIMER_ { KDPC dpc;//dpc KTIMER timer;//定时器 LARGE_INTEGER due;//定时毫秒数 PKDEFERRED_ROUTINE func;//用户回调函数 PVOID privete_context;//用户上下文 }MY_TIMER,*PMY_TIMER; BOOLEAN MyTimerInit(PMY_TIMER timer,PKDEFERRED_ROUTINE func); BOOLEAN MyTimerSet(PMY_TIMER timer,ULONG msec,PVOID context); BOOLEAN MyTimerDestroy(PMY_TIMER timer); KDEFERRED_ROUTINE MyOnTimer; //初始化内部时钟结构:PMY_TIMER,用户回调函数func BOOLEAN MyTimerInit(PMY_TIMER pTimer,PKDEFERRED_ROUTINE func) { if( !pTimer ) return FALSE; //初始化dpc:使用timer->dpc,回调函数TimerProc(内核回调函数) //上下文设置为timer(用于传给用户回调函数) KeInitializeDpc(&pTimer->dpc,(PKDEFERRED_ROUTINE)TimerProc,pTimer); pTimer->func = func;//设置用户自定义回调函数 //初始化定时器 KeInitializeTimer(&pTimer->timer); return TRUE; } //让内部时钟结构体的回调函数在n毫秒后执行:PMY_TIMER,定时毫秒数msec,用户上下文context BOOLEAN MyTimerSet(PMY_TIMER timer,ULONG msec,PVOID context) { //定时时间值转换 //为正时指定相对系统的间隔时间:受系统时间设置影响 //为负则指定绝对系统时间:为纳秒数,不受系统时间设置影响 timer->due.QuadPart = -*(LONG)msec;//必须转为有符号类型 //用户私有上下文 timer->privete_context = context; //添加定时器到系统定时器队列 return KeSetTimer(&timer->timer,timer->due,&timer->dpc); } //停止执行 BOOLEAN MyTimerDestroy(PMY_TIMER pTimer) { if(pTimer) return KeCancelTimer(&pTimer->timer); else return FALSE; } //定时器回调函数:内核使用 void TimerProc(struct _KDPC *Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2) { //这里传入的上下文是timer结构,用来下次再启动延时调用 PMY_TIMER pTimer = (PMY_TIMER)DeferredContext; if(pTimer->func)//用户回调函数 { PKDEFERRED_ROUTINE pFunc = (PKDEFERRED_ROUTINE)pTimer->func;//取得用户定义回调函数指针 pFunc(Dpc,(PVOID)pTimer->privete_context,SystemArgument1,SystemArgument2);//调用用户定义的回调函数 } else KdPrint(("No callback function !\n")); KeSetTimer(&pTimer->timer,pTimer->due,&pTimer->dpc);//再次设置定时器 }
测试代码:
#define SIZE 30 //用户上下文(自定义结构体) typedef struct { WCHAR message[SIZE]; ULONG times; }USER_CONTENT,*PUSER_CONTENT; //用户回调函数 KDEFERRED_ROUTINE TimerProc; //定时器回调函数:用户实现(函数名可更改) void MyOnTimer(struct _KDPC *Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2) { //在这里做OnTimer中要做的事,封装的好处就是编码时只关注自己想关注的东西 PUSER_CONTENT pMyContext = (PUSER_CONTENT)DeferredContext; pMyContext->times++; KdPrint(("第%d次调用定时器:%ws",pMyContext->times,pMyContext->message)); }
过程:
MY_TIMER timer; USER_CONTENT MyContent; ULONG i = ; //用户自定义结构 RtlStringCbPrintfW((NTSTRSAFE_PWSTR)&MyContent.message,SIZE*sizeof(WCHAR),L"Hello Timer!");//格式串 MyContent.times = ;//计数值 //初始化定时器 MyTimerInit(&timer,(PKDEFERRED_ROUTINE)MyOnTimer); //启动定时器 MyTimerSet(&timer,,(PVOID)&MyContent); //等待一段时间 *10E8 ); //关闭定时器 MyTimerDestroy(&timer); KdPrint(("定时器已经停止!"));
效果图:
《天书夜读:从汇编语言到windows内核编程》九 时间与定时器的更多相关文章
- 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建
(原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...
- 《天书夜读:从汇编语言到windows内核编程》八 文件操作与注册表操作
1)Windows运用程序的文件与注册表操作进入R0层之后,都有对应的内核函数实现.在windows内核中,无论打开的是文件.注册表或者设备,都需要使用InitializeObjectAttribut ...
- 《天书夜读:从汇编语言到windows内核编程》六 驱动、设备、与请求
1)跳入到基础篇的内核编程第7章,驱动入口函数DriverEnter的返回值决定驱动程序是否加载成功,当打算反汇编阅读驱动内核程序时,可寻找该位置. 2)DRIVER_OBJECT下的派遣函数(分发函 ...
- 《天书夜读:从汇编语言到windows内核编程》十一 用C++编写内核程序
---恢复内容开始--- 1) C++的"高级"特性,是它的优点也是它的缺点,微软对于使用C++写内核程序即不推崇也不排斥,使用C++写驱动需注意: a)New等操作符不能直接使用 ...
- 《天书夜读:从汇编语言到windows内核编程》四 windows内核调试环境搭建
1) 基础篇是讲理论的,先跳过去,看不到代码运行的效果要去记代码是一个痛苦的事情.这里先跳入探索篇.其实今天的确也很痛苦,这作者对驱动开发的编译与调试环境介绍得太模糊了,我是各种尝试,对这个环境的搭建 ...
- 《天书夜读:从汇编语言到windows内核编程》十 线程与事件
1)驱动中使用到的线程是系统线程,在system进程中.创建线程API函数:PsCreateSystemThread:结束线程(线程内自行调用)API函数:PsTerminateSystemThrea ...
- 《天书夜读:从汇编语言到windows内核编程》七 内核字符串与内存
1)驱动中的字符串使用如下结构: typedef struct _UNICODE_STRING{ USHORT Length; //字符串的长度(字节数) USHORT MaximumLength; ...
- 《天书夜读:从汇编语言到windows内核编程》三 练习反汇编C语言程序
1) Debug版本算法反汇编,现有如下3×3矩阵相乘的程序: #define SIZE 3 int MyFunction(int a[SIZE][SIZE],int b[SIZE][SIZE],in ...
- 《天书夜读:从汇编语言到windows内核编程》二 C语言的流程与处理
1) Debug与Release的区别:前者称调试版,后者称发行版.调试版基本不优化,而发行版会经过编译器的极致优化,往往与优化前的高级语言执行流程会大相径庭,但是实现的功能是等价的. 2) 如下fo ...
随机推荐
- Google Authenticator 如何集成(U盾的实现原理相同)
Google Authenticator是一个类似U盾的二次验证工具,Google提供了它的开源客户端(https://github.com/google/google-authenticator)里 ...
- vs 或 Sql server2012连接Sql server时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误
以前连接是正常的,就这两天连不上了.(没有耐心的直接看末尾解决办法) 错误消息如下: 1.尝试读取或写入受保护的内存.这通常指示其他内存已损坏.(System.Data) 2.已成功与服务器建立连接, ...
- HDU2048 HDU2049 组合数系列 错排
HDU1465HDU2048HDU2049#include<cstdio> #include<cstdlib> #include<iostream> #includ ...
- Win10系统下安装Ubuntu16.04.3教程与设置
在Win10上刚刚装好Ubuntu16.04.3,装了不下于10次,期间出现很多问题,趁着还有记忆,写下这篇教程,里面还有Ubuntu系统的优化与Win10的一些设置. Part 1 制作Ubuntu ...
- mac 通过brew安装php70 +php-fpm+ phalcon3.0.3
安装php7.0.15 brew install homebrew/php/php70 brew install homebrew/php/php70-mcrypt brew install home ...
- VisualStudio 合并代码文件
如果有相同的类,一般可以使用 partial 让他写在多个文件,那么如何把多个文件合并?请看 MainWindow.xaml 和 MainWindow.xaml.cs 其中 代码文件被折叠,那么如何做 ...
- CSS3动画 transition和animation的用法和区别
transition和animation都是CSS3新增的特性,使用时需要加内核 浏览器 内核名称 W3C IE -ms- Chrome/Safari -webkit- Firefoc - ...
- mysql单独可连接,php连接mysql失败之 Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
此种解决方案使用场景: 1,mysql单独可以启动而且远程工具也可以连接 2,php无法连接. 3,find / -name mysql.sock 可以找到文件路径 4,报错 Can't connec ...
- Python装饰器,json,pickle
装饰器 定义:本质是函数,装饰其它函数是为了给其添加新功能: 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器知识储备: 1.函数即变量: 2.高阶函数 3.嵌套 ...
- hack查询地址
悲催的IE! http://browserhacks.com/