XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
阅读:2772回复:10

Windows驱动编程基础教程(连载9)

楼主#
更多 发布于:2008-05-30 10:13
本文作者是楚狂人,有问题请联系QQ16191935,msn walled_river@hotmail.com

Windows驱动编程基础教程(5.3)

5.3 使用定时器

    使用过Windows应用程序编程的读者的读者一定对SetTimer()映像尤深。当需要定时执行任务的时候,SetTimer()变得非常重要。这个功能在驱动开发中可以通过一些不同的替代方法来实现。比较经典的对应是KeSetTimer(),这个函数的原型如下:

    BOOLEAN
          KeSetTimer(
                IN PKTIMER  Timer,                // 定时器
                IN LARGE_INTEGER  DueTime,    // 延后执行的时间
                IN PKDPC  Dpc  OPTIONAL        // 要执行的回调函数结构
            );

    其中的定时器Timer和要执行的回调函数结构Dpc都必须先初始化。其中Timer的初始化比较简单。下面的代码可以初始化一个Timer:

    KTIMER my_timer;
    KeInitializeTimer(&my_timer);

    Dpc的初始化比较麻烦。这是因为需要提供一个回调函数。初始化Dpc的函数原型如下:

    VOID
          KeInitializeDpc(
                IN PRKDPC  Dpc,
                IN PKDEFERRED_ROUTINE  DeferredRoutine,
                IN PVOID  DeferredContext
            );

    PKDEFERRED_ROUTINE这个函数指针类型所对应的函数的类型实际上是这样的:

    VOID
    CustomDpc(
            IN struct _KDPC  *Dpc,
            IN PVOID  DeferredContext,
            IN PVOID  SystemArgument1,
            IN PVOID  SystemArgument2
        );

     读者需要关心的只是DeferredContext。这个参数是KeInitializeDpc调用时传入的参数。用来提供给CustomDpc被调用的时候,让用户传入一些参数。
至于后面的SystemArgument1和SystemArgument2则请不要理会。Dpc是回调这个函数的KDPC结构。
请注意这是一个“延时执行”的过程。而不是一个定时执行的过程。因此每次执行了之后,下次就不会再被调用了。如果想要定时反复执行,就必须在每次CustomDpc函数被调用的时候,再次调用KeSetTimer,来保证下次还可以执行。
值得注意的是,CustomDpc将运行在APC中断级。因此并不是所有的事情都可以做(在调用任何内核系统函数的时候,请注意WDK说明文档中标明的中断级要求。)
这些事情非常的烦恼,因此要完全实现定时器的功能,需要自己封装一些东西。下面的结构封装了全部需要的信息:

    // 内部时钟结构
    typedef struct MY_TIMER_
    {
        KDPC dpc;
        KTIMER timer;
        PKDEFERRED_ROUTINE func;
        PVOID private_context;
    } MY_TIMER,*PMY_TIMER;

    // 初始化这个结构:
    void MyTimerInit(PMY_TIMER timer, PKDEFERRED_ROUTINE func)
    {
        // 请注意,我把回调函数的上下文参数设置为timer,为什么要
        // 这样做呢?
        KeInitializeDpc(&timer->dpc,sf_my_dpc_routine,timer);
        timer->func = func;
        KeInitializeTimer(&timer->timer);
        return (wd_timer_h)timer;
    }

    // 让这个结构中的回调函数在n毫秒之后开始运行:
    BOOLEAN MyTimerSet(PMY_TIMER timer,ULONG msec,PVOID context)
    {
        LARGE_INTEGER due;
        // 注意时间单位的转换。这里msec是毫秒。
        due.QuadPart = -10000*msec;
        // 用户私有上下文。
        timer->private_context = context;
        return KeSetTimer(&timer->timer,due,&mytimer->dpc);
    };
    
    // 停止执行
    VOID MyTimerDestroy(PMY_TIMER timer)
    {
        KeCancelTimer(&mytimer->timer);
    };

    使用结构PMY_TIMER已经比结合使用KDPC和KTIMER简便许多。但是还是有一些要注意的地方。真正的OnTimer回调函数中,要获得上下文,必须要从timer->private_context中获得。此外,OnTimer中还有必要再次调用MyTimerSet(),来保证下次依然得到执行。

    VOID
    MyOnTimer (
            IN struct _KDPC  *Dpc,
            IN PVOID  DeferredContext,
            IN PVOID  SystemArgument1,
            IN PVOID  SystemArgument2
        )
    {
        // 这里传入的上下文是timer结构,用来下次再启动延时调用
        PMY_TIMER timer = (PMY_TIMER)DeferredContext;
        // 获得用户上下文
        PVOID my_context = timer->private_context;

        // 在这里做OnTimer中要做的事情
        ……

        // 再次调用。这里假设每1秒执行一次
        MyTimerSet(timer,1000,my_context);
    };

    关于定时器就介绍到这里了。

最新喜欢:

greenpeacegreenp...
mr6698
驱动牛犊
驱动牛犊
  • 注册日期2008-03-26
  • 最后登录2017-09-27
  • 粉丝3
  • 关注0
  • 积分21分
  • 威望200点
  • 贡献值0点
  • 好评度26点
  • 原创分0分
  • 专家分1分
沙发#
发布于:2008-05-30 10:41
超赞!继续关注中。。。
camin920
驱动牛犊
驱动牛犊
  • 注册日期2004-11-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分11分
  • 威望99点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-05-30 11:23
无私奉献呀!
alwaysrun
驱动小牛
驱动小牛
  • 注册日期2006-06-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1059分
  • 威望752点
  • 贡献值1点
  • 好评度98点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-05-30 11:45
赞,继续关注
一颗平常的心!
microbe
驱动小牛
驱动小牛
  • 注册日期2007-12-10
  • 最后登录2011-01-17
  • 粉丝1
  • 关注0
  • 积分914分
  • 威望420点
  • 贡献值1点
  • 好评度88点
  • 原创分0分
  • 专家分1分
地下室#
发布于:2008-05-30 14:17
赞美,顶起!!
pandaforum
驱动小牛
驱动小牛
  • 注册日期2007-02-13
  • 最后登录2011-09-06
  • 粉丝0
  • 关注0
  • 积分728分
  • 威望282点
  • 贡献值1点
  • 好评度66点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-05-30 14:27
多谢 看的很爽!
dt1985324
驱动牛犊
驱动牛犊
  • 注册日期2008-05-06
  • 最后登录2009-02-10
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望106点
  • 贡献值1点
  • 好评度20点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2008-05-30 17:08
   在线刷新等待
strpic
驱动小牛
驱动小牛
  • 注册日期2006-11-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望238点
  • 贡献值0点
  • 好评度156点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2008-05-31 11:31
多谢,正在认真拜读。
demonking
驱动牛犊
驱动牛犊
  • 注册日期2008-04-03
  • 最后登录2012-06-28
  • 粉丝0
  • 关注0
  • 积分11分
  • 威望41点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2008-05-31 16:02
楼主大好人啊
wyhero
驱动牛犊
驱动牛犊
  • 注册日期2008-03-17
  • 最后登录2016-02-02
  • 粉丝0
  • 关注0
  • 积分67分
  • 威望563点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2008-06-03 19:31
谢谢楼主分享,期待继续
zhoujiamurong
驱动小牛
驱动小牛
  • 注册日期2006-03-20
  • 最后登录2009-05-06
  • 粉丝4
  • 关注0
  • 积分1081分
  • 威望360点
  • 贡献值0点
  • 好评度215点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2008-07-21 13:53
爽啊,真爽,谢谢
游客

返回顶部