Windows-lib的导出数据的类型声明前的volatile有或没有是什么意思?

Windows-lib的导出数据的类型声明前的volatile有或没有是什么意思?

归属感 发布于 2017-09-09 字数 359 浏览 1187 回复 1

在驱动中获取CPU数目时,看了一下是从lib引出来的一个数,但是声明有些奇怪:

#if (NTDDI_VERSION >= NTDDI_VISTA)
extern NTSYSAPI volatile CCHAR KeNumberProcessors;
#elif (NTDDI_VERSION >= NTDDI_WINXP)
extern NTSYSAPI CCHAR KeNumberProcessors;
#else
extern PCCHAR KeNumberProcessors;
#endif

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

想挽留 2017-10-31 1 楼

首先,变量前面加"volatile"是指程序每次都去该内存保存的地址去获取值,而不是把变量值固定为编译器编译时确定的值。看下面这个例子:

#include <stdio.h>
void main()
{
  int i=10;
  int a = i;
  printf("i= %d",a);
  //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道
  __asm
{
   mov dword ptr [ebp-4], 20h
  }
  int b = i;
  printf("i= %d",b);
}

然后,在调试版本模式运行程序,输出结果如下:
  i = 10
  i = 32
然后,在release版本模式运行程序,输出结果如下:
  i = 10
  i = 10
  输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。下面,我们把 i的声明加上volatile关键字,看看有什么变化:

  #include <stdio.h>
void main()
{
  volatile int i=10;
  int a = i;
  printf("i= %d",a);
  __asm
{
   mov dword ptr [ebp-4], 20h
  }
  int b = i;
  printf("i= %d",b);
}

分别在调试版本和release版本运行程序,输出都是:
  i = 10
  i = 32

关键在“mov dword ptr [ebp-4], 20h”这句,[ebp-4]是堆栈中第一个局部变量的值,这个得程序运行时确定,编译器无法编译时赋值。第一个例子没有加volatile修饰,所以编译器编译时给它赋了10,而后者是每次从i所在的内存地址中获取。

所以extern NTSYSAPI volatile CCHAR KeNumberProcessors;这句的意思是每次都得从KeNumberProcessors所在内存地址取值。而extern 是导出内核变量KeNumberProcessors的意思。
至于为什么VISTA的要加volatile,是为了支持CPU热插拔。你看看下面这段描述就明白了。

The KeNumberProcessors kernel variable is obsolete in Windows Vista SP1, Windows Server 2008, and later versions of Windows. KeNumberProcessors does not appear in WDK headers for WDK releases starting with Windows Vista SP1; however, the variable is still exported from the kernel, so drivers built for earlier platforms will not break.

Windows Server 2008 includes support for Dynamic Hardware Partitioning (DHP) in the Windows Datacenter and Enterprise Edition SKUs. As part of DHP, Windows Server 2008 supports hot adding CPUs at runtime. In a hot-add CPU environment, the number of processors may not remain constant during runtime.

Accordingly, in Windows Server 2008, code that can determine the number of processors must use KeQueryActiveProcessors instead of direct references to the kernel variable, KeNumberProcessors.