.Net8的AOT引导程序BootStrap

所谓的引导程序,也就是引导被ILC生成的目标文件编译成可执行文件,然后在相应的平台上(MacoS/Linux/Win)进行二进制执行。这里以微软自家的Windows平台为例来剖析下这段引导程序。
首页 新闻资讯 行业资讯 .Net8的AOT引导程序BootStrap

前言

.Net8的本地预编机器码AOT,它几乎进行了100%的自举。微软为了摆脱C++的钳制,做了很多努力。也就是代码几乎是用C#重写,包括了虚拟机,GC,内存模型等等。而需要C++做的,也就仅仅是引导程序,本篇通过代码来看下这段至关重要的引导程序的运作模式。

概括

所谓的引导程序,也就是引导被ILC生成的目标文件编译成可执行文件,然后在相应的平台上(MacoS/Linux/Win)进行二进制执行。这里以微软自家的Windows平台为例来剖析下这段引导程序。

引导程序分为两个阶段,其一初始化运行时,其二运行托管的Main入口代码。分别看下,最后就是代码展示了。

1.实例化运行时

这个很好理解,你如果需要运行.Net程序那么必须有一个运行的环境,第一步就是初始化这个运行环境。它主要包括以下步骤:

一:环境变量的初始化

环境变量的初始化主要是指设置的环境变量,对于GC或者JIT的控制。在这里进行一个初始化和区分。比如开启了了内存映射的环境变量
DOTNET_EnableWriteXorExecute=1.它就是此时被AOT识别并进行区分。

二:注册AOT的模块

AOT程序需要用到哪些模块,比如

Runtime.WorkstationGC.lib
System.Globalization.Native.Aot.lib
System.IO.Compression.Native.Aot.lib
eventpipe-disabled.lib
Runtime.VxsortDisabled.lib

等一些模块需要用到,那么这里进行注册下,以便后续调用。

三:模块的初始化

这里的模块初始化实际上,R2R的部分预编译函数替代。

2.托管的Main入口

.Net里面托管的Main函数是一切托管函数的入口点,所以托管Main入口是必须设置正确,并且能够运行完整托管代码。本例展示的托管Main如下:

static void Main(){
   Program pm=new Program();pm=null;GC.Collect();Console.WriteLine("This is Ce Shi");Console.ReadLine();}

3.代码展示

上面只是一些概念,具体的行为落实,还得代码来。这里看下BootStrap引导程序的代码。

一:节操作:

节存变量

主要是在初始化运行时的模块初始化阶段需要用到

#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 };

节合并

这里主要是然链接器进行一个节的合并

#pragma comment(linker, "/merge:.modules=.rdata")#pragma comment(linker, "/merge:.unbox=.text")

节声明函数

实例化运行时注册AOT模块的时候要用到

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运行环境的初始化

staticintInitializeRuntime(){//环境变量的初始化if(!RhInitialize())return-1;//获取当前模块的句柄void*osModule=PalGetModuleHandleFromPointer((void*)&__managed__Main);//注册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_DLLreturn0;}

托管入口

return__managed__Main(argc,argv);

以上是.Net8的AOT引导程序的大致运作模式。

完整代码在GitHub:https://github.com/tangyanzhi/jianghupt/releases/download/Aot_bootstrap/AOT-BootStrap.rar


11    2023-07-11 00:17:58    .Net8 AOT C