点击上方蓝字 江湖评谈设为关注
前言
.NET8是多指令集,多平台的深层次技术框架。Linux和MacOS是其使用的重点,本篇来看下Linux下面的Main(托管和非托管)入口点详情。
详述
在Linux上面一般的用户态都是以libc.so库文件里面的函数为用户态入口,举个例子,比如说著名的Linux发行版界面系统Ubuntu22.04.它的一个情况具体如下。
经过一系列系统初始化,首先内核态会调用用户态的模块libc.so,加载它。此后会调用这个模块里面的函数__libc_start_main_impl,这个函数加载非托管用户态的入口函数。它调用了__libc_start_call_main函数,同样在libc.so模块里面。通过__libc_start_call_main这个函数名称,即可看出它直接调用的就是非托管Main(通用的C++里面的Main入口)。这里说个题外话的问题,Windows上面,非托管Main调用是哪个函数,哪个模块呢?
答案很简单:Windows上面,也就是微软自家平台上,调用非托管Main的是BaseThreadInitThunk函数,它所在的模块是用户态的kernel32.dll。
这里Linux和Windows可以一一对应下:
用户态入口调用模块以及函数:
Linux:libc.so -> __libc_start_main_impl
Windows:ntdll.dll -> RtlUserThreadStart
非托管Main调用模块以及函数:
Linux:libc.so -> __libc_start_call_main
windows:kernel32.dll -> BaseThreadInitThunk
除了上面的不同点,还有不同点在于:
linux调用了__libc_start_call_main函数之后,就会直接调CLR的main(corerun.cpp)
但是Windows会调用MSCV的一些库函数比如:
exewmain.cpp:wmainCRTStartup
execommoninl:__scrt_common_main
execommoninl:invoke_main
最后才是CLR Main
以上为非常简单的技术介绍,基本为入门的前置级。
往期精彩回顾