在前一篇博文中,在好奇心的驅使下,探祕了 dotnet run ,發現了神祕的 corehost —— 運行 .NET Core 應用程序的幕後英雄。有時神祕就是一種誘惑,神祕的 corehost 讓人產生了新的好奇心 —— corehost 是如何加載 coreclr 的?因而,「.NET跨平臺之旅」開啓了新的旅程 —— 帶着這個疑問,遊覽 cli/src/corehost/ 。html
corehost 的入口是 corehost.cpp 的 main() ,進來後一條大道通向 corehost.run() 。git
在 corehost.run() 中,首先調用的是 libhost.cpp 中的 detect_operating_mode() ,它根據 coreclr 所在的路徑決定 corehost 的運行模式,有三種運行模式:muxer, standalone, split-fx。若是 corehost 與 coreclr 不在同一個文件夾,運行模式則是 muxer 。若是 corehost 與 coreclr 在同一個文件夾,而且文件夾下存在 .deps.json 文件或者不存在 .runtimeconfig.json 文件,則是 standalone 模式;不然是 split-fx 模式。github
return ((pal::file_exists(own_deps_json) || !pal::file_exists(own_config_filename)) && pal::file_exists(own_dll)) ? host_mode_t::standalone : host_mode_t::split_fx;
dotent cli 默認使用的模式是 split-fx 模式,咱們的示例站點 about.cnblogs.com 用的也是這種模式,經過下面的 tracing 信息能夠看出來(export COREHOST_TRACE=2):json
Checking if CoreCLR path exists=[/usr/share/dotnet-nightly/bin/libcoreclr.so] Detecting mode... CoreCLR present in own dir [/usr/share/dotnet-nightly/bin] and checking if [corehost.deps.json] file present=[0] Host operating in split mode; own dir=[/usr/share/dotnet-nightly/bin]
此次旅程也所以選擇「split-fx 模式」這條遊覽路線。函數
針對 split-fx 模式,corehost.run() 接着會調用 hostpolicy.cpp 的 run() 方法(經過 corehost_init_t ),run() 方法中調用 deps_resolver.cpp 的 resolve_coreclr_dir() 解析 coreclr 所在的路徑,而後調用 coreclr.cpp 的 bind() 與 initialize() 方法加載 coreclr 。學習
在 bind() 方法中,根據以前解析出的 coreclr 路徑,調用 pal.unix.cpp(針對的是Linux運行環境)的 load_library() 打開 coreclr 的庫文件 libcoreclr.so (實際是調用 Linux 的 C 函數 dlopen() ),從而獲得 coreclr 中3個函數(coreclr_initialize, coreclr_shutdown, coreclr_execute_assembly)的句柄。spa
在 initialize() 方法中,根據 bind() 中獲得的句柄調用 coreclr 的 coreclr_initialize() 方法啓動 coreclr , 加載 coreclr 的工做就這樣完成了。unix
找到 coreclr 庫文件所在的位置,打開它,調用它的 coreclr_initialize() 方法,corehost 加載 coreclr 就這麼簡單。若是你有興趣,能夠用 C++ 寫一個本身的 corehost 。code
開源的 .NET 變得更有意思,即便沒有任何文檔,即便沒有正式發佈,你也能夠經過源碼學習它,瞭解它。htm