簡體   English   中英

在Windows內核中可以使用多少C ++ 11

[英]How much of C++11 is usable in Windows Kernel

最新的WDK將與Visual Studio 15一起使用,后者支持C ++ 11。

但是,我還沒有看到有關有多少功能可用的文檔。

顯然,我不會使用std::threadstd::mutex ,但不太清楚,是神奇的靜態。

Class * function()
{
     static Class myInstance;

     return &myInstance;
}

這在用戶模式下現在是線程安全的,但目前還不清楚這種結構是否可以在內核中運行。

更值得關注的是,預編譯C ++ 11代碼在內核中是可以接受的(假設析構函數是微不足道的)。

我找到了一些關於switch / kernel msdn:/ kernel(創建內核模式二進制文件)的文檔,它描述了一個開關,告訴編譯器.obj的目的地是內核模式。

這描述了異常和RTTI的不同行為,但未提及魔法靜態。

從一個簡單的可見反編譯

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

和一些用戶模式測試,編譯器

  1. 不發出任何線程本地代碼。
  2. 不提供usermode的線程安全行為。

編輯

為清楚起見。 當未指定/kernel時,魔術靜態工作正常,靜態初始化是線程安全的。 機制(使用fs :)不適用於內核。

使用/kernel代碼不是線程安全的,但是內核兼容。 (沒有參考fs :)

除非你打算完全重寫內核e部署一個全新的導出名稱標准化 (這意味着丟棄所有現有的可執行文件),我認為這幾乎是不可能的。 許多C ++特性都是-in事實元函數 ,編譯器必須將其轉換為存在的東西。

std::thread這樣的東西可以實現為內核資源的包裝(很可能是“指向數據結構指針的指針:這就是HANDLE實際上是什么)”,讓這些結構駐留在另一個進程中對客戶端程序完全不透明。

函數調用這樣保留這種不透明度的東西需要所有語言都可以依賴的標准ABI (App。二進制接口),同時產生必須鏈接的目標代碼。

現在,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在任何情況下,內核都會有一個單獨的Create / Get和Delete / Relese函數。

我當然可以根據智能句柄為您的C ++程序開發一個API,但是內核通信的程序仍然是通過普通函數(因此智能句柄都可以管理到客戶端,無論如何)

類似地,如果調用都是同步的,則堆棧展開有效,但創建/刪除本身不是同步的(它們不在另一個內部調用)。 它們通過RAII模式“同步”,通過駐留在您的堆棧中的LOCAL對象。 但是*HPEN (請注意取消引用)結構不在您的堆棧中:在另一個進程(GDI驅動程序)內部,因此smart<HPEN>必須在構造時調用CreatePen並在銷毀時調用DeletePen ,因為內核 - 本身 - 不能知道什么時候你的“解開”(那是你的,而不是內核)會來到正確的位置。

內核中的C ++ //可以存在於內核本身在同一內核調用中完全構造和銷毀的對象,然后由於客戶端以某種方式使用而不會超出內核。 這當然是可能的,但由於內核的目的是導出功能並且導出需要平面API,因此您很快將使用C ++內核導出客戶端C ++包裝器使用的普通C接口。

我懷疑這種努力是否合理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM