/kernel(创建内核模式二进制)
创建可在 Windows 内核中执行的二进制文件。 当前项目中的代码通过使用一组简化的 C++ 语言功能进行编译和链接,这些功能特定于在内核模式下运行的代码。
语法
/kernel
备注
通过指定 /kernel
选项,可以告诉编译器和链接器应将裁定哪些语言功能在内核模式中是允许的,并确保您具有足够的表达力来避免内核模式 C++ 独有的运行时不稳定情况。 这是通过禁止使用在内核模式下具有中断功能的 C++ 语言特性来实现的。 编译器为可能具有中断功能但无法禁用的 C++ 语言功能生成警告。
/kernel
选项适用于生成的编译器和链接器阶段,并在项目级别设置。 传递 /kernel
开关可向编译器指示生成的二进制文件在链接后应加载到 Windows 内核中。 编译器会将 C++ 语言功能的范围缩小为与内核兼容的子集。
下表列出了指定 /kernel
时编译器行为的更改。
行为类型 | /kernel 行为 |
---|---|
C++ 异常处理 | 已禁用。 throw 和 try 关键字的所有实例都发出了编译器错误(异常规范 throw() 除外)。 /EH 选项都与 /kernel 不兼容,/EH- 除外。 |
RTTI | 已禁用。 除非以静态方式使用 dynamic_cast ,否则 typeid 和 dynamic_cast 关键字的所有实例都会发出编译器错误。 |
new 和 delete |
必须显式定义 new() 或 delete() 运算符。 编译器和运行时不提供默认定义。 |
在使用 /kernel
选项时,自定义调用约定、/GS
生成选项和所有优化都是允许的。 内联基本上没有受 /kernel
的影响,并具有编译器遵循的相同语义。 如果要确保应用 __forceinline
内联限定符,则必须确保启用警告 C4714 以了解特定 __forceinline
函数何时没有内联。
没有 #pragma
等效项来控制此选项。
向编译器传递 /kernel
开关后,它会预定义名为 _KERNEL_MODE
且具有值 1 的预处理器宏。 你可以使用此宏,根据执行环境是处于用户模式还是内核模式下按条件编译代码。 例如,以下代码指定在针对内核模式执行对类进行编译时,MyNonPagedClass
类应该位于不可分页的内存段中。
#ifdef _KERNEL_MODE
#define NONPAGESECTION __declspec(code_seg("$kerneltext$"))
#else
#define NONPAGESECTION
#endif
class NONPAGESECTION MyNonPagedClass
{
// ...
};
下面的一些目标体系结构与 /arch
选项的组合在与 /kernel
一起使用时产生了错误:
x86 上不支持
/arch:SSE
、/arch:SSE2
、/arch:AVX
、/arch:AVX2
和/arch:AVX512
。 只有/arch:IA32
受 x86 上的/kernel
的支持。x64 上通过
/kernel
来支持/arch:AVX
、/arch:AVX2
和/arch:AVX512
。
使用 /kernel
进行生成会将 /kernel
传递到链接器。 以下是该选项如何影响链接器行为:
禁用了增量链接。 如果将
/incremental
添加到命令行,链接器会发出此错误:致命错误 LNK1295:“/INCREMENTAL”与“/KERNEL”规范不兼容;没有“/INCREMENTAL”的链接
链接器检查每个对象文件(或静态库中的任何包含的存档成员)以了解是否原本可以用
/kernel
选项编译它但没有这样做。 如果任何实例都满足此标准,链接器仍然会成功链接,但可能发出警告,如下表所示。命令 /kernel
obj非 /kernel
对象、MASM 对象或 cvtres 对象/kernel
和非/kernel
对象的混合link /kernel
是 是 是,但出现警告 LNK4257 link
是 是 是 LNK4257 链接对象未使用/KERNEL 编译;映像可能无法运行
/kernel
选项与 /driver
选项彼此独立运行。 它们不会对值产生影响。
在 Visual Studio 中设置 /kernel 编译器选项
打开项目的“属性页”对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性。
选择“配置属性”>“C/C++”>“命令行”属性页。
在“附加选项”编辑框中,输入
/kernel
。 选择“确定”或“应用”以保存更改。