最新的WDK将与支持C++11的Visual Studio 15一起使用。
然而,我还没有看到关于有多少功能是可用的文档。
显然,我不会使用std::thread
和std::mutex
,但不太清楚的是,神奇的静态。
Class * function()
{
static Class myInstance;
return &myInstance;
}
现在,在用户模式下,这是线程安全的,但尚不清楚这种构造是否可以在内核中工作。
更令人担忧的是,C++11之前的代码在内核中是可以接受的(假设析构函数是琐碎的)。
我发现了一些关于开关/kernel msdn:/kernel(创建内核模式二进制文件)的文档,它描述了一个开关,告诉编译器.obj将用于内核模式。
这描述了异常和RTTI的不同行为,但没有提到神奇的静态。
从一个简单的可见反编译
Class * GetInstance()
{
static Class instance;
return &instance;
}
以及一些用户模式测试,编译器
- 不发出任何线程本地代码
- 不提供用户模式下的线程安全行为
编辑
为了清楚起见。当未指定/kernel
时,magic statics有效,静态初始化是线程安全的。该机制(使用fs:)不适用于内核。
使用/kernel
时,代码不是线程安全的,但与内核兼容。(未提及fs:)
除非您计划完全重写内核并部署导出名称的全新标准化(这意味着丢弃所有现有的可执行文件),否则我认为这基本上是不可能的。事实上,许多C++特性都是编译器必须翻译成存在的东西的元函数。
像std::thread
这样的东西可以实现为内核资源的包装器(很可能是"指向数据结构的指针:这就是HANDLE的实际含义"),让这些结构驻留在另一个进程中,并且对客户端程序完全不透明。
像函数调用这样的东西需要一个所有语言都可以依赖的标准ABI(App.Binary接口),同时生成必须链接的对象代码。
现在,由于缺少重载,C ABI是微不足道的(只需将_
与函数名垂直:这是windows内核库采用的惯例,每个编译器开发人员在制作windows版本时都必须依赖它),但C++名称篡改是。。。专有的(没有定义必须如何在系统级完成,所以每个编译器都有自己的)。
因此,唯一可靠的内核将是只导出extern "C"
的内核。它可以在内部用C++编写,但在任何情况下,它的接口都必须是纯C(这只是class* function();
,与HANDLE CreateClass()
在语义上没有什么不同
请注意,即使在C++规范级别定义一个标准ABI也没有多大帮助:所有C++编译器都会链接相同的编译器,但不需要遵循其他语言。
系统级ABI必须足够简单,不需要客户端语言功能(如函数重载),而不是所有语言都必须支持这些功能。
更为复杂的是,C++还有一些模板,它们在编译过程中实例化代码,并且无法跨越进程边界或内核屏障可靠地实现:想象一下内核内部有vector<int>
和vector<double>
:我可以依赖于必须使用这些函数的系统,但vecotr<foo>
呢?
在我的机器上编译我的软件时,我如何要求所有用户的系统内核使vector<foo>
存在?在安装过程中可以这样做,但同样,需要对通信接口进行更多的标准化。
内核是存在于汇编程序级别的物理资源的管理器。用C表示它们几乎是微不足道的。如果您使用C++低级别特性(这些特性与C基本相同),那么在C++中表示它们仍然是微不足道的,但是,一旦您进入抽象,您就会立即遇到标准化的缺失和关于在哪里以及如何实现的复杂而非琐碎的选择,这些选择将转化为对那些在内核级别的使用可能没有那么明确定义的东西的未来限制。
当然,原则上没有任何东西禁止在内核实现中内部使用C++,但这会在跨资源使用的边界管理中产生问题。
实际的协议是"允许我访问资源"one_answers"保留您的资源"。
客户端程序可以将这两个调用封装在RAII类中,并在其上应用所有C++11特性,但将其移动到边界的另一边呢?内核可以返回win::unique<something>
吗?好不是这样,因为你不能破坏你自己不在进程中的东西:"samrt句柄"将有一个析构函数,从而导致对内核函数的另一次调用。o在任何情况下,内核都将具有单独的创建/获取和删除/释放功能。
就智能句柄而言,我当然可以为C++程序开发一个API,但程序到内核的通信仍然是通过简单的函数实现的(因此,无论如何,智能句柄都是由客户端管理的)
类似地,如果调用都是同步的,但创建/删除本身不是同步的(它们不是一个在另一个内部调用的),则堆栈展开可以工作。它们通过RAII模式,通过驻留在您堆栈中的LOCAL对象进行"同步"。但是*HPEN
(注意去引用)结构不在您的堆栈中:在另一个进程(GDI驱动程序)中,因此smart<HPEN>
必须在构造时调用CreatePen
,在销毁时调用DeletePen
,因为内核本身无法知道您的"展开"(这是您的,而不是内核)何时会到达正确的点。
内核//中的C++//可以存在于完全由内核本身在同一内核调用中同步构建和销毁的对象中,因此不会超出内核,以某种方式被客户端使用。这当然是可能的,但由于内核的目的是导出功能,并且导出需要平面API,因此很快就会出现C++内核导出客户端C++包装器使用的纯C接口的情况。
我怀疑这种努力是否合理。