標籤:

如何開始學習CoreCLR源代碼?

C#開發者希望學習下CLR的源碼,但是不知道如何入門...

希望知乎大神指導幾個問題:

1. CoreCLR是什麼IDE編寫的,代碼好像大部分是C++的。

2. 學習此類開源代碼要如何入手比較合適


先解決些大問題再回到題主的具體問題。

首先,請確定自己是不是真的想深入到VM(CLR)層面的代碼。是不是其實有些好奇的地方在.NET Core的庫層面就已經夠用?是的話請看dotnet/corefx,而不是CoreCLR。

然後,如果是已經對C#有所了解但想進一步了解CLR的話,《CLR via C#》值得一讀。通過它先了解CLR都提供了一些怎樣的服務,各種服務之間是如何聯繫起來的,有個大體概念。

另外還有兩本書可以伴隨《CLR via C#》一起讀。一本是《Pro .NET Performance》,另一本是《Writing High-Performance .NET Code》。兩本的切入點都是編寫高性能.NET代碼,都涉及一些關於CLR的知識,可以讓讀者了解到CLR的某些功能(或者說優化)會如何反映到應用的性能上。

再次,在深入CLR之前,先打好MSIL(Microsoft Intermediate Language,也叫做CIL(Common Intermediate Language))的基礎是件值得做的事。熟悉MSIL所提供的功能之後,帶著「CLR要如何逐一實現MSIL的功能」的問題去整理知識脈絡鑽進CoreCLR去看,比沒頭緒亂看一通要有效的多。

這個可以閱讀CLI(Common Language Infrastructure)規範ECMA-335,也可以讀一些現成的書,例如《Inside Microsoft .Net Il Assembler》、《Expert .NET 2.0 IL Assembler》等。

接下來,確定想了解CoreCLR源碼但沒有任何基礎的話,請先仔細閱讀《Shared Source CLI 2.0 Internals》。這是一本免費發布的書,講的是Shared Source Common Language Infrastructure 2.0 Release(SSCLI 2.0)的實現,其中很多內容對應到CoreCLR里仍然適用(或大致思路仍然一致);SSCLI 2.0與CLRv2的主要區別是JIT編譯器和GC的具體實現不同,runtime涉及PAL的部分也可能不同,而runtime的其它部分幾乎一樣。通讀一遍此書能讓初學者至少有個概念,CLR的源碼會涉及什麼方面的知識,有啥看不懂的可以先有針對性的補充背景知識。

相比《CLR via C#》,這本書更多的涉及到代碼,但仍站在比較抽象的角度去描述CLR各部分的功能和聯繫,適合當作閱讀代碼的線索。

微軟在CLRv2之後還給CLR添加了許多新功能,這些新東西自然在SSCLI 2.0沒有反映,在看CoreCLR代碼時得另找資料去學習。

例如說security model的差異。SSCLI 2.0反映CLRv2的情況,其security model主要還是「Code Access Security」(CAS),需要在安全檢查是做棧遍歷(stack walk);CoreCLR實現的是transparency model(Mono里直接把這個叫做CoreCLR security model),不需要做棧遍歷。

再接下來,讀完SSCLI 2.0書之後,請在鑽進CoreCLR源碼前先閱讀CoreCLR源碼中自帶的Book of the Runtime(BotR)。這是CoreCLR自帶的文檔,寫得非常好而且專門為CoreCLR更新了內容,與時俱進。微軟還在慢慢更新BotR的,逐漸放出更多內容出來,值得持續關注。

說BotR好主要是因為CoreCLR里有很多代碼細節不太直觀,如果沒有文檔描述大體概念和思路的話,直接鑽進代碼里很容易被大量奇怪的細節淹沒——除非您對managed runtime已經非常熟悉了。但就像 @代碼豆 大大的回答所說,BotR跟實際代碼之間還有一定距離,光靠它還不足以深入到CoreCLR的枝末細節;一邊調試一邊學習是最靠譜的。

CoreCLR的代碼有著濃厚的微軟色彩——存在大量僅為維持向後兼容性的代碼。最初入門閱讀代碼時要自己知道如何自動忽略掉它們才行。

最後,如果要深入到JIT編譯器和GC的話,請另外閱讀專門書籍。

SSCLI 2.0里的JIT編譯器是一個非常簡單的FJIT,基本上就是把MSIL一條條對應到各自的彙編模版生成出來,不涉及多少編譯原理;CoreCLR里的JIT編譯器是RyuJIT,裡面需要用的知識大多是傳統編譯原理書上會講到的,可以挑幾本自己喜歡的編譯原理書讀讀來打基礎。

GC方面的話,《The Garbage Collection Handbook》是學習的不二之選。

還有可以多騷擾 @代碼豆 大大讓他多寫點介紹文,哈哈~~

===========================================================

然後回到題主的問題:

1、CoreCLR是用什麼IDE編寫的:根本不重要。

CoreCLR的build系統可以在第一次build之後生成出Visual Studio的solution,所以可以很方便的在Visual Studio里開發和調試。這些solution包括C++和C#的project,CLR自身的代碼主要用C++實現,而mscorlib(.NET標準庫的核心部分)則主要用C#實現。

實際上CLR開發們里emacs黨比較多吧。以前看Channel 9的訪談幾乎沒看到他們有用Visual Studio來開發CLR的。所以說用啥IDE根本不是重點。

&<- 更新:CLR組裡工作的 @代碼豆 大大提醒說現在內部還是用VS的多,用emacs的少。請參考他的回答。

2、學習此類開源代碼要如何入手比較合適:「此類」就是「託管運行時」(managed runtime)咯?或者叫「虛擬執行環境」(virtual execution environment)或「虛擬機」(virtual machine)。先從我前面說的那些資料入手至少對學習CoreCLR來說是條好路線。

如果是說別的類似的東西,例如JVM,我以前發過一個書單,可以參考:從表到里學習JVM實現


不請自來,不是大牛,只是在CLR混了1年說說體會吧。首先你要明白你到底了解那塊,一上來就想把CoreCLR全部搞定,這個說實話不現實。有個大體概念,比如CLR有那幾塊組成,然後每塊的分工是什麼,然後挑一個自己覺得有興趣的點入手。材料 @RednaxelaFX都說的很詳細了,就不多說了。還有個人感覺,對於大多數人來說一上來就想通過看源碼直接了解CLR,這個不現實,而且這個是我們組的認同,實話講CLR的內部資料寫的其實不是很好,Book of runtime雖然不錯,但也只是告訴你大體的概念,非常具體東西還是沒有涉及到。所以很多嘗試直接看源碼的人開始還行,後來就開始被轉暈了。組裡大部分人學習的辦法還是靠mentor輔導和修bug,然後通過修bug擴大知識面,比如你修了一個簡單EH bug,然後你可以嘗試看一下CLR是怎麼處理EH的怎麼做stackwalking的,慢慢就有感覺了。如果是作為external的dev,你在github直接聯繫我們就行了,coreclr還是有很多bug我們想要修但沒時間管的,所以如果你要是想幫忙大家還是很高興的。對了還是要說一點,我上面說的只是針對普通人,我知道也有人是特殊的存在。比如我知道一個大牛,他之前在windows組有8-9年的經驗,來了CLR後從來都不看什麼資料或者問別人,對於他來講有什麼不懂得直接看代碼就行了。還有一個我不得不說,他和組裡其他大牛的區別就是掃地僧和少林歷任主持的區別,大多數是都是對自己在組的知識極為精通,同時對CLR其他部分有大體了解,他基本上是對所有的部分都極為精通。。。而且他的辦法感覺就是記代碼。。。沒錯就是記代碼!那哥們傳說強大到你問他CLR的任何問題,他都可以直接告訴你去哪個函數修改,然後還基本都能成。。。如果你是這兩種人,大哥請受小弟一拜!

然後回答一下第一個問題,雖然我們IDE用VS,但不是真正意義上的用,只是當text editor和代碼閱讀,所以有部分人也會用emacs代替。而VS的build和debug功能,因為我們會搭建自己的private runtime用VS debug的話有時候會不管用,所以大家debug普遍喜歡用windbg,而VS的build基本就不用,我們都是用自己內部寫的腳本調用msbuild。github的版本是為了方便非CLR的人使用專門修改過的,所以你要是build的話還是以github上方式為主。


推薦閱讀:

Stack-based 的虛擬機有什麼常用的優化策略?
RyuJIT為什麼比JIT64編譯速度快?
程序集什麼玩意?我知道其表現形式為dll和exe,但是exe不是直接執行的文件嗎?而dll只是類庫,供exe調用代碼?

TAG:源代碼 | CLR |