生活的天平本不平衡,只有通过努力改变其偏向。

Windows驱动编程基础教程 第八部分

2008-05-30

本文作者是楚狂人,有问题请联系QQ16191935,msn walled_river@hotmail.com

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

5.1 获得当前滴答数

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

C++代码
  1. VOID KeQueryTickCount(
  2. OUT PLARGE_INTEGER  TickCount
  3. );

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

C++代码
  1. ULONG KeQueryTimeIncrement();

得知以上的关系之后,下面的代码可以求得实际的毫秒数:

C++代码
  1. void MyGetTickCount (PULONG msec)
  2. {
  3. LARGE_INTEGER tick_count;
  4. ULONG myinc = KeQueryTimeIncrement();
  5. KeQueryTickCount(&tick_count);
  6. tick_count.QuadPart *= myinc;
  7. tick_count.QuadPart /=  10000;
  8. *msec = tick_count.LowPart;
  9. }

这不是一个简单的过程。不过所幸的是,现在有代码可以拷贝了。

5.2 获得当前系统时间

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

C++代码
  1. VOID KeQuerySystemTime(
  2. OUT PLARGE_INTEGER  CurrentTime
  3. );
  4. VOID ExSystemTimeToLocalTime(
  5. IN PLARGE_INTEGER  SystemTime,
  6. OUT PLARGE_INTEGER  LocalTime
  7. );

这两个函数使用的“时间”都是长长整型数据结构。这不是人类可以阅读的。必须通过函数RtlTimeToTimeFields转换为TIME_FIELDS。这个函数原型如下:

C++代码
  1. VOID RtlTimeToTimeFields(
  2. IN PLARGE_INTEGER  Time,
  3. IN PTIME_FIELDS  TimeFields
  4. );

读者需要实际应用一下来加深印象。下面写出一个函数:这个函数返回一个字符串。这个字符串写出当前的年、月、日、时、分、秒,这些数字之间用“-”号隔开。这是一个很有用的函数。而且同时用到上面三个函数,此外,请读者回忆前面关于字符串的打印的相关章节。

C++代码
  1. PWCHAR MyCurTimeStr()
  2. {
  3. LARGE_INTEGER snow,now;
  4. TIME_FIELDS now_fields;
  5. static WCHAR time_str[32] = { 0 };
  6. // 获得标准时间
  7. KeQuerySystemTime(&snow);
  8. // 转换为当地时间
  9. ExSystemTimeToLocalTime(&snow,&now);
  10. // 转换为人类可以理解的时间要素
  11. RtlTimeToTimeFields(&now,&now_fields);
  12. // 打印到字符串中
  13. RtlStringCchPrintfW(
  14. time_str,
  15. 32*2,
  16. L“%4d-%2d-%2d %2d-%2d-%2d”,
  17. now_fields.Year,now_fields.Month,now_fields.Day,
  18. now_fields.Hour,now_fields.Minute,now_fields.Second);
  19. return time_str;
  20. }

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

作者:lonkil | 分类目录:编程开发 | 标签:

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>