新聞中心
前言
.Net8的本地預(yù)編機(jī)器碼AOT,它幾乎進(jìn)行了100%的自舉。微軟為了擺脫C++的鉗制,做了很多努力。也就是代碼幾乎是用C#重寫(xiě),包括了虛擬機(jī),GC,內(nèi)存模型等等。而需要C++做的,也就僅僅是引導(dǎo)程序,本篇通過(guò)代碼來(lái)看下這段至關(guān)重要的引導(dǎo)程序的運(yùn)作模式。

概括
所謂的引導(dǎo)程序,也就是引導(dǎo)被ILC生成的目標(biāo)文件編譯成可執(zhí)行文件,然后在相應(yīng)的平臺(tái)上(MacoS/Linux/Win)進(jìn)行二進(jìn)制執(zhí)行。這里以微軟自家的Windows平臺(tái)為例來(lái)剖析下這段引導(dǎo)程序。
引導(dǎo)程序分為兩個(gè)階段,其一初始化運(yùn)行時(shí),其二運(yùn)行托管的Main入口代碼。分別看下,最后就是代碼展示了。
1.實(shí)例化運(yùn)行時(shí)
這個(gè)很好理解,你如果需要運(yùn)行.Net程序那么必須有一個(gè)運(yùn)行的環(huán)境,第一步就是初始化這個(gè)運(yùn)行環(huán)境。它主要包括以下步驟:
一:環(huán)境變量的初始化
環(huán)境變量的初始化主要是指設(shè)置的環(huán)境變量,對(duì)于GC或者JIT的控制。在這里進(jìn)行一個(gè)初始化和區(qū)分。比如開(kāi)啟了了內(nèi)存映射的環(huán)境變量
DOTNET_EnableWriteXorExecute=1.它就是此時(shí)被AOT識(shí)別并進(jìn)行區(qū)分。
二:注冊(cè)AOT的模塊
AOT程序需要用到哪些模塊,比如
Runtime.WorkstationGC.lib
System.Globalization.Native.Aot.lib
System.IO.Compression.Native.Aot.lib
eventpipe-disabled.lib
Runtime.VxsortDisabled.lib等一些模塊需要用到,那么這里進(jìn)行注冊(cè)下,以便后續(xù)調(diào)用。
三:模塊的初始化
這里的模塊初始化實(shí)際上,R2R的部分預(yù)編譯函數(shù)替代。
2.托管的Main入口
.Net里面托管的Main函數(shù)是一切托管函數(shù)的入口點(diǎn),所以托管Main入口是必須設(shè)置正確,并且能夠運(yùn)行完整托管代碼。本例展示的托管Main如下:
static void Main()
{
Program pm=new Program();
pm = null;
GC.Collect();
Console.WriteLine("This is Ce Shi");
Console.ReadLine();
}
3.代碼展示
上面只是一些概念,具體的行為落實(shí),還得代碼來(lái)。這里看下BootStrap引導(dǎo)程序的代碼。
一:節(jié)操作:
節(jié)存變量
主要是在初始化運(yùn)行時(shí)的模塊初始化階段需要用到
#pragma section(".modules$A", read)
#pragma section(".modules$Z", read)
extern "C" __declspec(allocate(".modules$A")) void* __modules_a[];
extern "C" __declspec(allocate(".modules$Z")) void* __modules_z[];
__declspec(allocate(".modules$A")) void* __modules_a[] = { nullptr };
__declspec(allocate(".modules$Z")) void* __modules_z[] = { nullptr };節(jié)合并
這里主要是然鏈接器進(jìn)行一個(gè)節(jié)的合并
#pragma comment(linker, "/merge:.modules=.rdata")
#pragma comment(linker, "/merge:.unbox=.text")節(jié)聲明函數(shù)
實(shí)例化運(yùn)行時(shí)注冊(cè)AOT模塊的時(shí)候要用到
char _bookend_a;
char _bookend_z;
#pragma code_seg(".managedcode$A")
void* __managedcode_a() { return &_bookend_a; }
#pragma code_seg(".managedcode$Z")
void* __managedcode_z() { return &_bookend_z; }
#pragma code_seg()AOT運(yùn)行環(huán)境的初始化
static int InitializeRuntime()
{
//環(huán)境變量的初始化
if (!RhInitialize())
return -1;
//獲取當(dāng)前模塊的句柄
void* osModule = PalGetModuleHandleFromPointer((void*)&__managed__Main);
//注冊(cè)AOT模塊
if (!RhRegisterOSModule(
osModule,
(void*)&__managedcode_a, (uint32_t)((char*)&__managedcode_z - (char*)&__managedcode_a),
(void*)&__unbox_a, (uint32_t)((char*)&__unbox_z - (char*)&__unbox_a),
(void**)&c_classlibFunctions, _countof(c_classlibFunctions)))
{
return -1;
}
//初始化需要的模塊
InitializeModules(osModule, __modules_a, (int)((__modules_z - __modules_a)), (void**)&c_classlibFunctions, _countof(c_classlibFunctions));
#ifdef NATIVEAOT_DLL
// Run startup method immediately for a native library
__managed__Startup();
#endif // NATIVEAOT_DLL
return 0;
}托管入口
return __managed__Main(argc, argv);以上是.Net8的AOT引導(dǎo)程序的大致運(yùn)作模式。
完整代碼在GitHub:https://github.com/tangyanzhi/jianghupt/releases/download/Aot_bootstrap/AOT-BootStrap.rar
網(wǎng)站標(biāo)題:.Net8的AOT引導(dǎo)程序BootStrap
文章來(lái)源:http://m.fisionsoft.com.cn/article/djspsce.html


咨詢(xún)
建站咨詢(xún)
