前面提到在SSCLI環境裏運行.NET程序的時候,執行的命令相似java程序的執行過程,即經過clix程序解釋執行.net程序。這個過程看起來跟在windows環境下執行.net程序表面上看起來不同 – Windows環境下的CLR直接執行.net程序文件便可執行,其實內部運做機制是同樣的,在後文我會講解到。java
首先咱們先來解讀下clix的源碼,其源碼位置位於:clr\src\tools\clix\clix.cpp,入口的main函數在clix.cpp:157行。windows
剛開始的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程序運行環境,這一點咱們將在後面看到。app
168 ~ 176的代碼是一個條件編譯代碼,啓用時,clix在運行.net程序以前讓調試器有機會附加到進程上。dom
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命令查看:.net
cd sscli20 cd binaries.x86dbg.rotor dumpbin /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依次執行以下操做:調試
一、從2121行開始,確保虛擬機是在system domain裏運行的;code
二、2133行加載將要執行的.net程序 – 即assembly;blog
三、2134行分析assembly裏的IL格式,確保是一個合法的.net程序;
四、2138 ~ 2143行找到assembly的入口函數點;
五、2148 ~ 2154行爲.net程序建立默認的應用程序域(Application Domain);
六、2155 ~ 2168行爲.net程序準備尋找依賴Assembly的環境;
七、2168行加載.net程序以及其依賴的Assembly進入當前進程;
八、2169 ~ 2184行爲新建立的應用程序域設置一個友好的名字,以便在調試過程當中容易識別;
九、2194行執行.net程序的main函數,進入托管執行環境。