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

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

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

Windows驱动编程基础教程(5.1-5.2)


5.1 获得当前滴答数

    在编程中,获得当前的系统日期和时间,或者是获得一个从启动开始的毫秒数,是很常见的需求。获得系统日期和时间往往是为了写日志。获得启动毫秒数很适合用来做一个随机数的种子。有时也使用时间相关的函数来寻找程序的性能瓶颈。
    熟悉Win32应用程序开发的读者会知道有一个函数GetTickCount(),这个函数返回系统自启动之后经历的毫秒数。在驱动开发中有一个对应的函数KeQueryTickCount(),这个函数的原型如下:

    VOID
        KeQueryTickCount(
            OUT PLARGE_INTEGER  TickCount
        );

    遗憾的是,被返回到TickCount中的并不是一个简单的毫秒数。这是一个“滴答”数。但是一个“滴答”到底为多长的时间,在不同的硬件环境下可能有所不同。为此,必须结合另一个函数使用。下面这个函数获得一个“滴答”的具体的100纳秒数。

    ULONG
          KeQueryTimeIncrement(
              );

    得知以上的关系之后,下面的代码可以求得实际的毫秒数:
    
    void MyGetTickCount (PULONG msec)
    {
        LARGE_INTEGER tick_count;
        ULONG myinc = KeQueryTimeIncrement();
        KeQueryTickCount(&tick_count);
        tick_count.QuadPart *= myinc;
        tick_count.QuadPart /=  10000;
        *msec = tick_count.LowPart;
    }
    
    这不是一个简单的过程。不过所幸的是,现在有代码可以拷贝了。

5.2 获得当前系统时间

    接下来的一个需求是得到当前的可以供人类理解的时间。包括年、月、日、时、分、秒这些要素。在驱动中不能使用诸如CTime之类的MFC类。不过与之对应的有TIME_FIELDS,这个结构中含有对应的时间要素。
    KeQuerySystemTime()得到当前时间。但是得到的并不是当地时间,而是一个格林威治时间。之后请使用ExSystemTimeToLocalTime()转换可以当地时间。这两个函数的原型如下:

    VOID
      KeQuerySystemTime(
            OUT PLARGE_INTEGER  CurrentTime
        );
    VOID
      ExSystemTimeToLocalTime(
            IN PLARGE_INTEGER  SystemTime,
            OUT PLARGE_INTEGER  LocalTime
        );

    这两个函数使用的“时间”都是长长整型数据结构。这不是人类可以阅读的。必须通过函数RtlTimeToTimeFields转换为TIME_FIELDS。这个函数原型如下:
    
    VOID
      RtlTimeToTimeFields(
           IN PLARGE_INTEGER  Time,
            IN PTIME_FIELDS  TimeFields
        );
    
    读者需要实际应用一下来加深印象。下面写出一个函数:这个函数返回一个字符串。这个字符串写出当前的年、月、日、时、分、秒,这些数字之间用“-”号隔开。这是一个很有用的函数。而且同时用到上面三个函数,此外,请读者回忆前面关于字符串的打印的相关章节。

    PWCHAR MyCurTimeStr()
    {
        LARGE_INTEGER snow,now;
        TIME_FIELDS now_fields;
        static WCHAR time_str[32] = { 0 };
        // 获得标准时间
        KeQuerySystemTime(&snow);
        // 转换为当地时间
        ExSystemTimeToLocalTime(&snow,&now);
        // 转换为人类可以理解的时间要素
        RtlTimeToTimeFields(&now,&now_fields);
        // 打印到字符串中
        RtlStringCchPrintfW(
            time_str,
            32*2,
            L"%4d-%2d-%2d %2d-%2d-%2d",
            now_fields.Year,now_fields.Month,now_fields.Day,
            now_fields.Hour,now_fields.Minute,now_fields.Second);
        return time_str;
    }

    请注意time_str是静态变量。这使得这个函数不具备多线程安全性。请读者考虑一下,如何保证多个线程同时调用这个函数的时候,不出现冲突?

最新喜欢:

greenpeacegreenp...
kabunhi
驱动牛犊
驱动牛犊
  • 注册日期2007-06-27
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分461分
  • 威望57点
  • 贡献值0点
  • 好评度46点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-05-30 10:33
thank you
lonkil
驱动牛犊
驱动牛犊
  • 注册日期2008-04-24
  • 最后登录2010-07-08
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望13点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-05-30 10:52
一直在关注楼主的连载,辛苦了。
谢谢
http://www.vcfans.com
microbe
驱动小牛
驱动小牛
  • 注册日期2007-12-10
  • 最后登录2011-01-17
  • 粉丝1
  • 关注0
  • 积分914分
  • 威望420点
  • 贡献值1点
  • 好评度88点
  • 原创分0分
  • 专家分1分
地板#
发布于:2008-05-30 14:16
顶,一定要顶!!
dt1985324
驱动牛犊
驱动牛犊
  • 注册日期2008-05-06
  • 最后登录2009-02-10
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望106点
  • 贡献值1点
  • 好评度20点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-05-30 17:05

"...这两个函数使用的“时间”都是长长整型数据结构。这不是人类可以阅读的。"

呵呵 ,
zhoujiamurong
驱动小牛
驱动小牛
  • 注册日期2006-03-20
  • 最后登录2009-05-06
  • 粉丝4
  • 关注0
  • 积分1081分
  • 威望360点
  • 贡献值0点
  • 好评度215点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-06-19 13:20
太感谢了
游客

返回顶部