启动CLR
前面提到在SSCLI環境里運行.NET程序的時候,執行的命令類似java程序的執行過程,即通過clix程序解釋執行.net程序。這個過程看起來跟在windows環境下執行.net程序表面上看起來不一樣 – Windows環境下的CLR直接執行.net程序文件即可執行,其實內部運作機制是一樣的,在后文我會講解到。
首先我們先來解讀下clix的源碼,其源碼位置位于:clr\src\tools\clix\clix.cpp,入口的main函數在clix.cpp:157行。
剛開始的159 ~ 266行都是執行命令行參數解析以及錯誤處理的代碼,主要分三大塊,162 ~ 166行的目的是判斷rotor_palrt和sscoree兩個dll庫文件是否在進程中加載了,rotor_palrt這個庫文件在后面解讀平臺抽象層(PAL)的時候會提到,而sscoree這個庫文件的作用跟CLR里面的mscoree.dll的作用是一致的,即用來加載正確的CLR版本。如將要執行的.net程序是在.net 4.0下面編譯的,則加載.net 4.0的clr,如果運行的是.net 2.0的程序,則加載2.0的clr。sscoree加載CLR的過程是通過幾個導出函數實現的,而clix程序嚴重依賴這幾個函數加載clr和準備.net程序運行環境,這一點我們將在后面看到。
168 ~ 176的代碼是一個條件編譯代碼,啟用時,clix在運行.net程序之前讓調試器有機會附加到進程上。
177 ~ 266的代碼純粹就是命令行參數處理,其目的就是將命令行里運行參數傳遞給將要執行的.net程序。如在命令行執行:clix.exe dotNetApp.exe param1 param2;命令行傳遞給clix的參數列表param1, param2其實是傳給要執行的.net程序dotNetApp.exe的,因此177 ~ 266這段代碼的目的就是做這件事情。
267行這段代碼是整個main函數里最核心的代碼,其執行Launch函數實際加載clr和準備.net運行環境,而Launch函數也是通過在147行調用_CorExeMain2函數完成這項工作的。_CorExeMain2就是sscoree.dll的導出函數,這一點可以用dumpbin命令查看:
cd sscli20cd binaries.x86dbg.rotordumpbin /exports sscoree.dll_CorExeMain2函數的源碼位于:\clr\src\vm\ceemain.cpp:1622。_CorExeMain2函數只做兩件事情,在1646行調用CoInitializeEE確保進程中加載了CLR執行引擎;真正加載.net程序并執行的工作在1659行調用ExecuteEXE完成,而ExecuteEXE最后調用SystemDomain::ExecuteMainMethod完成這項工作。SystemDomain::ExecuteMainMethod的源碼位于 \clr\src\vm\appdomain.cpp:2099行。
跟大部分SSCLI源碼類似,函數的前后兩塊代碼都是一些條件判斷和掃尾操作代碼,從2121行開始,SystemDomain::ExecuteMainMethod依次執行如下操作:
1、從2121行開始,確保虛擬機是在system domain里運行的;
2、2133行加載將要執行的.net程序 – 即assembly;
3、2134行分析assembly里的IL格式,確保是一個合法的.net程序;
4、2138 ~ 2143行找到assembly的入口函數點;
5、2148 ~ 2154行為.net程序創建默認的應用程序域(Application Domain);
6、2155 ~ 2168行為.net程序準備尋找依賴Assembly的環境;
7、2168行加載.net程序以及其依賴的Assembly進入當前進程;
8、2169 ~ 2184行為新創建的應用程序域設置一個友好的名字,以便在調試過程中容易識別;
9、2194行執行.net程序的main函數,進入托管執行環境。
本文轉自 donjuan 博客園博客,原文鏈接:?http://www.cnblogs.com/killmyday/p/4300328.html? ,如需轉載請自行聯系原作者
總結
- 上一篇: 简单干净的C#方法设计案例:SFCUI.
- 下一篇: 课程第七天内容《基础交换七》