时钟 IoTimer
/*
例程是在运行在DISPATCH_LEVEL的IRQL级别
例程中不能使用分页内存
另外在函数首部使用 #pragma LOCKEDCODE
*/ #include "Driver.h" #define DeviceName L"\\Device\\MyDDKDevice" #pragma INITCODE
extern "C" NTSTATUS DriverEntry (
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status;
KdPrint(("Enter DriverEntry\n")); pDriverObject->DriverUnload = UnloadDriver; //设置派遣函数 /*
ARRAY_SIZE 定义设备结构体的个数
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]) + __must_be_array(arr)) */ for (int i = ; i < arraysize(pDriverObject->MajorFunction); ++i) //ARRAY_SIZE 定义设备结构体的个数
pDriverObject->MajorFunction[i] = DispatchFunction; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIoControl; //创建驱动设备对象
status = CreateDevice(pDriverObject); KdPrint(("Leave DriverEntry\n"));
return status;
} #pragma LOCKEDCODE
VOID OnTimer(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
DeviceObject->DeviceExtension;
KdPrint(("Enter OnTimer!\n")); //将计数器自锁减一
InterlockedDecrement(&pDevExt->lTimerCount); /*如果计数器减到0,重新编程TIMER_OUT,整个过程是互锁运算
LONG __cdecl InterlockedCompareExchange( __inout LONG volatile *Destination, //当前值 __in LONG Exchange, //当比较值与当前值相同时 替换当前值 __in LONG Comparand //比较值 PVOID __cdecl InterlockedCompareExchangePointer( __inout PVOID volatile *Destination, __in PVOID Exchange, __in PVOID Comparand 这两个函数以原子方式执行一个测试和设置操作。对32位应用程序来说,这两个函数都对32位值进行操作;
在64位应用程序中,InterlockedCompareExchange对32位值进行操作而InterlockedCompareExchangePointer对64位值进行操作。
函数会将当前值(Destination指向的)与参数Comparand进行比较,如果两个值相同,那么函数会将*Destination修改为Exchange参数指定的值。
若不等,则*Destination保持不变。函数会返回*Destination原来的值。所有这些操作都是一个原子执行单元来完成的。 */
LONG previousCount = InterlockedCompareExchange(&pDevExt->lTimerCount,TIMER_OUT,); //每隔三秒,计数器一个循环,输出以下log
if (previousCount==)
{
KdPrint(("%d seconds time out!\n",TIMER_OUT));
} //证明该线程运行在任意线程上下文的
/*
PEPROCESS pEProcess = IoGetCurrentProcess();
PTSTR ProcessName = (PTSTR) ((ULONG)pEProcess + 0x174);
*/
PEPROCESS pEProcess = IoGetCurrentProcess(); PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);//即可得到用户进程 KdPrint(("The current process is %s\n",ProcessName));
} /************************************************************************
* 函数名称:CreateDevice
* 功能描述:初始化设备对象
* 参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
* 返回 值:返回初始化状态
*************************************************************************/
#pragma INITCODE
NTSTATUS CreateDevice (
IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt; //创建设备名称
UNICODE_STRING devName;
RtlInitUnicodeString(&devName,DeviceName); //创建设备
status = IoCreateDevice( pDriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
, TRUE,
&pDevObj );
if (!NT_SUCCESS(status))
return status; pDevObj->Flags |= DO_DIRECT_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName; IoInitializeTimer(pDevObj,OnTimer,NULL); // 初始化IoTimer //创建符号链接
// 不进行Ring3层的交互 则不需要进行创建符号链接
NICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink( &symLinkName,&devName );
if (!NT_SUCCESS(status))
{
IoDeleteDevice( pDevObj );
return status;
}
return STATUS_SUCCESS;
} /************************************************************************
* 函数名称:HelloDDKUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
pDriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
VOID UnloadDriver (IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
KdPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject;
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pNextObj->DeviceExtension;
//删除符号链接
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName);
pNextObj = pNextObj->NextDevice;
IoDeleteDevice( pDevExt->pDevice );
}
} /************************************************************************
* 函数名称:HelloDDKDispatchRoutin
* 功能描述:对读IRP进行处理
* 参数列表:
pDevObj:功能设备对象
pIrp:从IO请求包 默认派遣例程
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS DispatchFunction(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{ KdPrint(("Enter HelloDDKDispatchRoutin\n")); PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//建立一个字符串数组与IRP类型对应起来
static char* irpname[] =
{
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
}; UCHAR type = stack->MajorFunction;
if (type >= arraysize(irpname))
KdPrint((" - Unknown IRP, major type %X\n", type));
else
KdPrint(("\t%s\n", irpname[type])); NTSTATUS status = STATUS_SUCCESS;
// 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = ; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKDispatchRoutin\n")); return status;
} #pragma PAGEDCODE
NTSTATUS DeviceIOControl(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("Enter HelloDDKDeviceIOControl\n")); //获得当前IRP堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//得到输入缓冲区大小
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//得到输出缓冲区大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL码
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension; ULONG info = ; switch (code)
{ // process request
case IOCTL_START_TIMER:
{
KdPrint(("IOCTL_START_TIMER\n"));
pDevExt->lTimerCount = TIMER_OUT;
IoStartTimer(pDevObj); //激活时钟
break;
}
case IOCTL_STOP:
{
KdPrint(("IOCTL_STOP\n"));
IoStopTimer(pDevObj); // 停止时钟
break;
}
default:
status = STATUS_INVALID_VARIANT;
} // 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = info; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKDeviceIOControl\n")); return status;
}
代码
时钟 IoTimer的更多相关文章
- 驱动开发:内核枚举IoTimer定时器
今天继续分享内核枚举系列知识,这次我们来学习如何通过代码的方式枚举内核IoTimer定时器,内核定时器其实就是在内核中实现的时钟,该定时器的枚举非常简单,因为在IoInitializeTimer初始化 ...
- [转] STM32各种时钟的区别
[原创]:http://m.oschina.net/blog/129357 我在原创的基础又从另一位博主处引用了一些内容. 时钟系统是处理器的核心,所以在学习STM32所有外设之前,认真学习时钟系统是 ...
- [转载]:STM32为什么必须先配置时钟再配置GPIO
转载来源 :http://blog.csdn.net/fushiqianxun/article/details/7926442 [原创]:我来添两句,就是很多同学(包括我)之前搞低端单片机,到了stm ...
- 理解Java对象的交互:时钟显示程序
实现: 结构: 对象:时钟 - 对象:小时 - 对象:分钟 小时和分钟具有相同属性(值,上限),可以用一个类Display来定义这两个对象: 但是两者之间又具有联系( ...
- [JS,Canvas]日历时钟
[JS,Canvas]日历时钟 Html: <!doctype html> <html> <head> <meta charset="UTF-8&q ...
- 浅谈时钟的生成(js手写代码)
在生成时钟的过程中自己想到布置表盘的写法由这么几种: 当然利用那种模式都可以实现,所以我们要用一个最好理解,代码有相对简便的方法实现 1.利用三角函数 用js在三角函数布置表盘的过程中有遇见到这种情况 ...
- Linux(Unix)时钟同步ntpd服务配置方法
http://xu20cn.blog.51cto.com/274020/69689 假定时钟服务器IP地址为:192.168.0.1 服务器端配置: 1:置/etc/ntp.conf文件内容为: se ...
- S5PV210_时钟系统
1.S5PV210的时钟获得:外部晶振+内部时钟发生器+内部PLL产生高频时钟+内部分频器分频 S5PV210外部有4个W晶振接口,可以根据需要来决定在哪里接晶振.接了晶振之后上电相应的模块就能产生振 ...
- Canvas绘制时钟
①首先在HTML的body标签中添加一个canvas标签,用于绘制时钟. <canvas id="myCanvas" width="600" height ...
随机推荐
- iOS - Xib
前言 xib 文件可以被 Xcode 编译成 nib 文件,xib 文件本质上是一个 xml 文件,而 nib 文件就是编译后的二进制文件,该文件将视图等控件对象封装了起来,而在程序运行起来后,这些对 ...
- XML 解析器
所有现代浏览器都内建了供读取和操作 XML 的 XML 解析器.解析器把 XML 转换为 XML DOM 对象 - 可通过 JavaScript 操作的对象. 解析 XML 文档为DOM对象 方法一: ...
- jQuery扩展插件和拓展函数的写法
<script type="text/JavaScript"> //jQuery插件的写法(需要传入操作对象) ;(function ...
- 巧妙的实现 CSS 斜线(炫酷的小效果)
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果 ...
- vi编辑器简单应用(摘抄)
摘抄于 vi编辑器的使用 (2) (3) 1 vi编辑器的基本使用 1.1 vi的启动 打开: $ vi example.c 只读打开 $ vi –R example.c 1.2 vi的工作模式 1. ...
- centos 解压rar文件
默认情况下centos是不支持winrar的解压与打包的,需要安装winrar的linux版本程序 首先得下载解压软件 wget http://www.rarsoft.com/rar/rarlinux ...
- Embed对象
1.EMBED 元素 | embed 对象 http://www.jb51.net/shouce/dhtml/objects/EMBED.html 2. 3.
- 20160805_CentOS6_键盘快捷键
1. 系统 -->首选项 --> 键盘快捷键 2. 3.
- python语法笔记(二)
1. 循环对象 循环对象是一类特殊的对象,它包含一个next()方法(在python3中是 __next__()方法),该方法的目的是进行到下一个结果,而在结束一系列结果之后,举出 StopItera ...
- perl中->和=>作用
-> 用法 -> 有两种用法,都和解引用有关. 第一种用法,就是解引用. 根据 -> 后面跟的符号的不同,解不同类型的引用, ->[] 表示解数组引用,->{} 表示解散 ...