4

提供最新的 WDK 以与支持 C++11 的 Visual Studio 15 一起使用。

但是,我还没有看到关于有多少功能可用的文档。

显然,我不会使用std::threadand std::mutex,但不太清楚的是魔术静力学。

Class * function()
{
     static Class myInstance;

     return &myInstance;
}

这现在在用户模式下是线程安全的,但尚不清楚这种构造是否可以在内核中工作。

更令人担忧的是,内核中是否可以接受 C++11 之前的代码(假设析构函数是微不足道的)。

4

2 回答 2

3

我找到了一些关于开关 /kernel msdn 的文档:/kernel (Create Kernel Mode Binary),它描述了一个开关,告诉编译器 .obj 是用于内核模式的。

这描述了异常和 RTTI 的不同行为,但没有提到魔法静态。

从一个简单的可见反编译

Class * GetInstance()
{
   static Class instance;
   return &instance;
}

和一些用户模式测试,编译器

  1. 不发出任何线程本地代码。
  2. 不提供来自用户模式的线程安全行为。

编辑

为了清楚起见。当/kernel未指定时,魔术静态工作并且静态初始化是线程安全的。该机制(使用 fs:)不适用于内核。

/kernel代码不是线程安全的,但与内核兼容。(没有提到fs:)

于 2016-03-09T18:43:36.617 回答
0

除非您计划完全重写内核并部署一个全新的导出名称标准化(这意味着丢弃所有现有的可执行文件),否则我认为这几乎是不可能的。许多 C++ 特性实际上是元函数,编译器必须将其转换为存在的东西。

std::thread通过让这些结构驻留在另一个进程中并且对客户端程序。

保持这种不透明度的函数调用之类的事情需要所有语言都可以依赖的标准 ABI(应用程序二进制接口),同时生成必须链接的目标代码。

现在,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++,但这会在跨资源使用的边界管理中产生问题。

实际的协议是“让我访问资源”和“保留您的资源”。

客户端程序可以将这两个调用包装在 RAII 类中并在其上应用所有 C++11 功能,但是将其移动到边界的另一侧呢?内核可以返回一个win::unique<something>吗?嗯......不是真的,因为你不能摧毁你自己不在你的进程中的东西:那个“samrt句柄”将有一个析构函数,导致另一个内核函数调用。o 在任何情况下,内核都会有单独的创建/获取和删除/释放功能。

我当然可以根据智能句柄为您的 C++ 程序开发一个 API,但与内核通信的程序仍将通过普通函数(因此智能句柄都管理到客户端,无论如何)

类似地,如果调用都是同步的,则堆栈展开有效,但创建/删除本身不是同步的(它们不是在另一个内部调用)。它们通过 RAII 模式通过驻留在您的堆栈中的本地对象“同步”。但是*HPEN(请注意取消引用)结构不在您的堆栈中:在另一个进程(GDI 驱动程序)中,因此smart<HPEN>必须调用CreatePen构造和DeletePen销毁,因为内核本身无法知道您的“展开”(即你的,而不是内核)将来到正确的点。

C++ //in kernel// 可以存在于完全由内核本身在同一个内核调用中同步构造和销毁的对象,然后 - 结果 - 不会离开内核,以某种方式被客户端使用。这当然是可能的,但是由于内核的目的是导出功能并且导出需要平面 API,因此您很快将使用 C++ 内核导出客户端 C++ 包装器使用的普通 C 接口。

我怀疑这种努力是否合理。

于 2016-03-01T07:54:24.100 回答