完整的程序在下载:http://download.csdn.net/detail/dijkstar/7913249

用户层创建的事件Event是一个Handle句柄,和内核中的创建的内核模式下的KEVENT是一个东西。因此,在应用层创建的事件,可以在内核层获得并使用。这一部分的原理,见张帆编著的《Windows驱动技术详解》章节8.5.4,P237页;

程序是来自于《Windows驱动技术详解》章节8.5.4(驱动程序和应用程序交互事件对象)和章节10.2.1(DPC定时器)。

首先,在应用层创建一个等待事件Event,创建监控这个等待事件的线程,并把等待事件Event传递给内核:

  1.  
    //
  2.  
    // 1. 创建用户层的等待事件,传入内核
  3.  
    // 2. 创建线程,用于监测内核事件的到来
  4.  
    //
  5.  
    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  6.  
    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, Thread1, &hEvent, 0, NULL);
  7.  
     
  8.  
    //先将用户层的等待Event传入内核
  9.  
    DeviceIoControl(hDevice, IOCTL_SET_EVENT, &hEvent, sizeof(hEvent), NULL, 0, &dwOutput, NULL);

监控线程的内容:(里面用了查询指令周期数,可以测试每次等待WaitFor××的时间)

  1.  
    UINT WINAPI Thread1(LPVOID para)
  2.  
    {
  3.  
    HANDLE *phEvent = (HANDLE *)para;
  4.  
    while(1)
  5.  
    {
  6.  
    //获得初始值
  7.  
    QueryPerformanceCounter(&litmp);
  8.  
    qt1=litmp.QuadPart;
  9.  
     
  10.  
    //等待
  11.  
    WaitForSingleObject(*phEvent, INFINITE);
  12.  
     
  13.  
     
  14.  
    //获得终止值
  15.  
    QueryPerformanceCounter(&litmp);
  16.  
    qt2=litmp.QuadPart;
  17.  
    //获得对应的时间值,转到毫秒单位上
  18.  
    dfm=(double)(qt2-qt1);
  19.  
    dft=dfm/dff;
  20.  
     
  21.  
     
  22.  
    printf("本次等待用时: %.3f 毫秒\n", dft*1000.0);
  23.  
    }
  24.  
    }

用户层还通知驱动内核启动一个DPC定时器,用于每次来触发应用层的等待事件Event:

  1.  
    DWORD dwMircoSeconds = 1000 * 50; //单位微秒
  2.  
    DeviceIoControl(hDevice, IOCTL_START_TIMER, &dwMircoSeconds, sizeof(DWORD), NULL, 0, &dwOutput, NULL);

在驱动程序中,首先取出来应用层传递进来的事件,并把它转化为内核对象:

  1.  
    case IOCTL_SET_EVENT:
  2.  
    {
  3.  
    //把传递进来的用户层等待事件取出来
  4.  
    HANDLE hUserEvent = *(HANDLE *)pIrp->AssociatedIrp.SystemBuffer;
  5.  
     
  6.  
    //将用户层事件转化为内核等待对象
  7.  
    status = ObReferenceObjectByHandle(hUserEvent, EVENT_MODIFY_STATE,
  8.  
    *ExEventObjectType, KernelMode, (PVOID*)&pDevExt->pEvent, NULL);
  9.  
     
  10.  
    KdPrint(("status = %d\n", status));//status应该为0才对
  11.  
     
  12.  
    ObDereferenceObject(pDevExt->pEvent);
  13.  
    break;
  14.  
    }

在内核的每次定时器到来时,激活等待事件,等于触发激活应用层的WaitFor××函数向下继续执行:

  1.  
    #pragma LOCKEDCODE
  2.  
    VOID PollingTimerDpc( IN PKDPC pDpc,
  3.  
    IN PVOID pContext,
  4.  
    IN PVOID SysArg1,
  5.  
    IN PVOID SysArg2 )
  6.  
    {
  7.  
    PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext;
  8.  
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
  9.  
    KeSetTimer(
  10.  
    &pdx->pollingTimer,
  11.  
    pdx->pollingInterval,
  12.  
    &pdx->pollingDPC );
  13.  
    KdPrint(("PollingTimerDpc\n"));
  14.  
     
  15.  
    //定时器到来,通知用户层
  16.  
    if(pdx->pEvent)
  17.  
    KeSetEvent(pdx->pEvent, IO_NO_INCREMENT, FALSE);
  18.  
     
  19.  
     
  20.  
    /*
  21.  
    //检验是运行在任意线程上下文
  22.  
    PEPROCESS pEProcess = IoGetCurrentProcess();
  23.  
    PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);
  24.  
    KdPrint(("%s\n",ProcessName));
  25.  
    */
  26.  
    }

程序中其他部分见源码解释,这个程序还有两个问题,一是应用层必须正常退出,否则驱动内核层因不能正常关闭DPC定时器,而继续执行已经找不到的等待事件,引起蓝屏崩溃;二是虽然在内核里,DPC定时器的触发精度为1个100ns级别,但当触发周期设置为20ms以下时,在应用层监控WaitFor,都是十几个毫秒的分辨精度,再向下设置已经没有意义。

jpg 改 rar 

向Windows内核驱动传递用户层定义的事件Event,并响应内核层的通知的更多相关文章

  1. go语言学习--内核态和用户态(协程)

    go中的一个特点就是引入了相比于线程更加轻量级的协程(用户态的线程),那么什么是用户态和内核态呢? 一.什么是用户态和内核态 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核 ...

  2. 【windows 操作系统】【CPU】用户模式和内核模式(用户层和内核层)

    所有的现代操作系统中,CPU是在两种不同的模式下运行的: 注意以下内容来自微软: windows用户模式和内核模式 运行 Windows 的计算机中的处理器有两个不同模式:用户模式 和内核模式 . 用 ...

  3. Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platform)

    catalog . 引言 . Windows 2000网络结构和OSI模型 . NDIS驱动 . NDIS微端口驱动编程实例 . NDIS中间层驱动编程实例 . NDIS协议层驱动编程实例 . TDI ...

  4. 理解Windows内核模式与用户模式

     1.基础 执行 Windows 的计算机中的处理器有两个不同模式:"用户模式"和"内核模式". 依据处理器上执行的代码的类型,处理器在两个模式之间切换.应 ...

  5. Windows内核驱动中操作文件

    本页主题:如何在windows内核驱动中对文件操作,实现对文件的拷贝.粘贴.删除.查询信息等,这是很常用也是很简单的方法. 部分内容参考:http://www.cppblog.com/aurain/a ...

  6. 用户空间与内核驱动的交互过程 — ioctl

    在Linux内核模块的开发过程中,经常涉及到运行在用户空间上的应用程序与内核模块进行交互,ioctl系统调用是常用的一种方式.本文并不涉及vlan的具体原理,仅通过vconfig与vlan内核模块进行 ...

  7. Windows系统的四个重要概念——进程、线程、虚拟内存、内核模式和用户模式

    引言 本来在写一篇Windows内存管理的文章,写着写着就发现好多基础的概念都要先讲.更可怕的是,这些基础的概念我却不能完全讲清楚.只好再把这本<深入解析Windows操作系统>翻到第一章 ...

  8. Windows内核驱动开发入门学习资料

    声明:本文所描述的所有资料和源码均搜集自互联网,版权归原始作者所有,所以在引用资料时我尽量注明原始作者和出处:本文所搜集资料也仅供同学们学习之用,由于用作其他用途引起的责任纠纷,本人不负任何责任.(本 ...

  9. Windows内核驱动开发:HelloWorld

    测试信息 Dev Machine: Windows Version: 2004 (19041.264) WDK Version: 10.0.19041.1 SDK Version: 10.0.1904 ...

随机推荐

  1. 适合Eclipse Juno的UML插件

    今天给Eclipse安装UML插件,试了很多都不兼容,我用的Ecllipe版本是4.2 最后终于找到一个叫做AmatersUML的插件还能用,不过还是不够顺手,比如对泛型支持不够,不能从图形直接跳到相 ...

  2. ubuntu下查看windows的 txt 文件乱码

    在终端执行 gsettings set org.gnome.gedit.preferences.encodings auto-detected "['UTF-8','GB18030','GB ...

  3. 开源项目推荐:e-example / Springboot+bootstrap + ……

    前言: 我想要找一个 springboot + bootstrap 的例子介绍,然后搜索到了这个开源项目. 所有能跑起来的项目都有研究价值,看看这个项目的文档.目前正好满足我想要的功能.推荐 正文: ...

  4. 炫酷霸气的HTML5/jQuery应用及源码

    也许在5年前,HTML5还是一种很前卫的技术,大家还只是将它当做实验来看待,更别说产品应用了.但是现在HTML5已经非常流行,无论从PC端还是移动端,HTML5都扮演着非常重要的角色.今天我们要分享的 ...

  5. Python学习(五)——列表操作全透析

    列表是以类的形式实现的. "创建"列表实际上是将一个类实例化. 因此,列表有多种方法能够操作. Python列表操作的函数和方法 列表操作包括下面函数: 1.cmp(list1, ...

  6. C++ 著名程序库 概览

          本文转载自: http://ace.acejoy.com/thread-3777-1-1.html   1.C++各大有名库的介绍--C++标准库 2.C++各大有名库的介绍--准标准库B ...

  7. 156 UIImageView 和 CADisplayLink 实现 Tom 汤姆猫动画效果的区别(扩展知识:分组(黄色文件夹)和文件夹引用(蓝色文件夹)区别)

    (1)UIImageView 的动画操作,来自定义循环播放动画(不建议使用,内存消耗大) (2)CADisplayLink 是一个计时器,但是同 NSTimer 不同的是,CADisplayLink ...

  8. Unable to resolve target 'android-9'

    右键项目文件--->properties--->android  选择对应版本 保存 如还不生效 打开项目文件project.properties ,修改 target=android-1 ...

  9. 【QT】error: Failed to retrieve MSVC Environment from "\VC\vcvarsall.bat":

    安装QT后直接打开,报错. 需要删mysql环境变量. error: Failed to retrieve MSVC Environment from "D:\Englishpath\VS2 ...

  10. mysql中如何修改表的名字?修改表名?

    需求描述: 今天在进行mysql表的历史数据迁移,需要将某张表进行备份,修改表的名字,在此记录下操作过程. 操作过程: mysql> create table ts01 like ti_o_sm ...