當前位置: 妍妍網 > 碼農

.NET9托管如何到非托管的?

2024-04-27碼農

點選上方 藍字 江湖評談 設為關註/星標




前言

.NET程式碼全部都是托管的,托管在了CLR這個執行時上面。但是實際上真正的執行得靠非托管,電腦它不辨識MSIL的二進制(參考: )。有沒有想過如何從托管到非托管呢?本篇看下

詳情

簡單的例子:

staticMain(string[] args) { GC.Collect(); }

托管 意即C#程式碼,非托管意即C / C++/AS M 碼。 這裏以GC垃圾回收GC.Collect()為例,Collect函式毫無疑問是托管的。當你對Collect跟蹤到時候,JIT會把整個MSIL載入到記憶體裏面去,然後透過DebugInfo偵錯資訊表定位當前斷點的位置以及當前光標所在的位置。準確的讓偵錯程式停下來或者繼續執行。

既然載入到記憶體,其實就很好理解了。Debug模式下透過DebugInfo來確定當前執行的堆疊軌跡,Release模式下其實也有偵錯資訊,只不過刪繁就簡了。同樣的透過DebugInfo來確定堆疊的執行軌跡。

程式碼:

extern"C"void QCALLTYPE GCInterface_Collect(INT32 generation, INT32 mode){ QCALL_CONTRACT; BEGIN_QCALL; _ASSERTE(generation >= -1); GCX_COOP(); GCHeapUtilities::GetGCHeap()->GarbageCollect(generation, false, mode); END_QCALL;}

GC.Collect透過QCall的模式進入到非托管之後,會呼叫C++程式碼,進行全代(如果Collect不指定某個代,就會對所有代進行GC)垃圾回收。一段受控代碼/函式對應一個非托管的呼叫約定,雙方約定俗成了如何進行通訊/呼叫的。

整體

整體性來說,Collect托管函式會被CLR載入,然後呼叫JIT進行Compile。最終Compile的結果裏麵包含了對於GCInterface_Collect非托管函式FCall的約定呼叫。如此基本上構成了托管-】非托管的運作過程。

往期精彩回顧