时钟 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 - Swift Dictionary 字典
前言 public struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConverti ...
- BUAA & ICT 夏令营之旅
我还只有二十几岁,总应该相信点什么吧. ================================ 7.10午后坐火车赶到北京.一路上火车行驶在茫茫云海里.车窗外的世界是这样子的:一片广袤的原野 ...
- 可重入锁 & 自旋锁 & Java里的AtomicReference和CAS操作 & Linux mutex不可重入
之前还是写过蛮多的关于锁的文章的: http://www.cnblogs.com/charlesblc/p/5994162.html <[转载]Java中的锁机制 synchronized &a ...
- 这个算asp.net的一个bug吗?
asp.net设置按钮Enabled="false"后OnClientClick中添加的验证脚本消失了 下面的确可以 <asp:Button ID="btnRegi ...
- android源码解析(十七)-->Activity布局加载流程
版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...
- Java Date与SimpleDateFormat
最近在弄一些涉及到时间处理的项目.本来自己写了一个时间转换函数,虽然能用但是过于麻烦而且不够规范,于是学习了下java自带的时间处理的类. public class Timechg { public ...
- 转:strcat与strcpy与strcmp与strlen
转自:http://blog.chinaunix.net/uid-24194439-id-90782.html strcat 原型:extern char *strcat(char *dest,cha ...
- 对List里的对象元素进行排序
public class Student { private int studentId; private String studentName; private int age; public St ...
- 是不是每个新手都要在samba那儿交足够的时间学费?
每次重新装了虚拟机都会在安装几个必要的服务器这个浪费不少时间, 这一次在Fedora20上装samba,这么配置都无法再windows上登陆,查看了各种配置文件,折腾的天昏地暗,最后终于找到原因: 在 ...
- ios开发者证书 签发者无效
2月14日以后,由于苹果更新安全证书:会导致本机制作的所有开发者证书无效: 钥匙串里的开发者证书无法使用 解决方式: 重新下载苹果公司的安全证书,并安装 1: 先在钥匙串里搜索到老的证书,如果有,请先 ...