原文:
學習核心的好處很多,在學習過程中不僅可以夯實大量理論基礎,還可以學習到很多編碼慣用法,提公升學習能力和分析能力。
一、確立高度,明確目標
在學習核心過程中最容易犯的錯誤,也是非常難掌握的其實是你站在乙個什麼樣的高度上去學習。站什麼樣的高度去學習也與自身的能力相關,所以這個問題其實更多是在新開始學習的學習者感到非常痛苦的一件事。一方面又希望自己能學懂,但是又不知道如何開始入手。
我列舉幾個常見的例子:
(1) 一開始就看原始碼,最開始我也做過這種事,核心有什麼都不知道,結果就想著啃0.11的核心,結果很顯然,2天立馬放棄,完全看不懂。
(2) 翻開書從第一頁開始往下啃,如果這本書比較薄還好,如果比較厚,比如《深入linux核心架構》,那看2天也得放棄。
(3) 不喜歡看目錄,不喜歡快速瀏覽,就想著乙個乙個字眼的往下摳。如果本身有一定基礎,看的時候還不會覺得膩,但是很快就發現,看了半天,什麼都沒有記住。
還有很多類似的問題,這些都是我們平時學習的時候特別容易出現的一些誤區。這些其實都是沒有正確審視自己的能力,胡亂挑選高度導致。
高度越高,也就是越偏向於理解各種抽象概念,傾向於構建對整體結構的乙個認知,忽略一些不必要細節,不關心技術實現手段。高度越低,也就是越偏向於對使用技術的選擇,傾向於**實現的各個細節,但是前提一般會在某個抽象的概念領域內進行各種細節性的討論。
我們的大腦更傾向於理解抽象的內容,但是在行動時,我們卻更傾向於去把握細節性的內容。結果導致的內容就是,我們總是希望通過學習細節來構造對抽象概念的理解,最後被細節性內容中各種雜訊干擾思緒,產生一種「這東西好難」的錯覺。在理解了這點,那高度對我們的行為有和指導意義也就呼之欲出了?
以讀書為例。站的越高,意味著自己看的內容越粗糙,也就是看書的時候不會去逐字逐句的看,而是乙個章節乙個章節的看,極端的情況就是只看目錄,在這個過程中主要集中精力構建整體結構,對核心的概念進行抽象。這時候學的內容都相對表面,但是好處就是對以後的學習有很強的指導意義,缺點很明顯,會讓人底氣不足,而且在達到一定程度後,很容易到達瓶頸,發覺怎麼看都看不懂了。站的越低,意味著自己看的內容很細緻,看書的時候就是乙個個字眼的扣,極端情況就是開始閱讀原始碼,去看開源社群的各種問題。但是就像詩句說的,站的越低,也就常有一種「不識廬山真面目,只緣身在此山中」的感覺。這種情況下特別容易被各種細節干擾,例如為什麼要有這些引數,為什麼這裡需要判斷這個條件等等這些細枝末節的問題。
以前對一篇博文印象很深刻,作者理解的學習曲線劃分成了兩個比較大的過程,上公升的過程就是乙個不斷學習積累的過程,而平緩沒有增長的過程則是對之前積累到飽和的知識進行消化的過程。我將這個學習過程進行進一步的劃分,我覺得在學習積累的前半部分應該以偏向學習抽象概念為主,而後半部分應該偏向學習實現細節。
所以個人的心得是從高到低的學習,在乙個新的學習階段,應該先多花點時間學習一些概念化的內容,這時候切忌去看具體的實現,而是多考慮如何在大腦中構建各種抽象模型
對整體的架構有所概念了,然後開始學習一些細節性的內容,比如開始看些原始碼,摳寫書上的字眼,讀讀一些具體的部落格什麼的。
二、學習小tips
不要從第一頁開始翻 不要一頁一頁的翻
如果開始看**,一定要記住,自己已經站在乙個非常底層的高度度了,能夠有能力閱讀**,就意味著你必須對整體的結構有比較清晰的認識,如果你都不知道這個結構,那看**為時太早。
無論是什麼樣的**,其實思路都很類似,即使linux核心是用c這種面相過程的語言編寫,但是這麼多年發展下來,linux核心已經帶有了大量面對物件程式設計的特點。
在看**的時候也是有兩種不同的高度可以選擇,我先解釋其中最細緻的一種:
乙個函式寫下來經常上百行,但是你需要一行一行的看麼?肯定不能,那清晰認識乙個函式的結構就很重要。
乙個函式就是為了解決乙個問題,函式名基本都能說明其功能,函式引數是輸入,返回值就是輸出,函式體就是整體的執行邏輯。在函式體內部,也基本都是類似的邏輯,先是對各種輸入引數進行檢查,然後書寫功能邏輯,然後構造輸出的結果。所以乙個函式寫下來總是這樣的一種結構。
輸出結果 函式名(輸入)
準備引數
功能邏輯
構造輸出結果
返回輸出結果
}乙個函式其實就是乙個方法,閱讀的難度比書寫的難度要低,書寫**需要考慮的問題非常多,但是在閱讀**的時候問題就簡單很多,很多書寫**過程中需要考慮的問題在閱讀**的過程中就不需要考慮 。
輸入引數:在書寫**的時候,這部分的內容也是很頭疼的內容,不僅需要確定需要哪些輸入,還需要輸入的形式,而且還需要精確定義每個輸入引數的語義;但是在閱讀**的過程中,這部分內容基本可以忽略,我們很少會關係所看到的函式需要哪些引數輸入。
輸出結果:在書寫**的時候,這部分也是很頭疼的一件事,因為精確定義輸出結果也是非常困難和麻煩的一件事;在閱讀**過程中,也需要注意輸出結果,不然乙個函式執行了老半天,結果連輸出結果是什麼都沒概念,也太失敗了點。
引數檢測:在編寫**過著中非常煩的一件事,每個人都希望呼叫函式的人會傳入正確的引數,但是根本做不到,結果每次都要花費一定精力對輸入引數的邊界、非空等進行檢查;在閱讀**過程中,根本不需要閱讀這部分的**,恰恰這部分內容在每個函式體中佔據了相當一部分的位置;
引數準備:編寫**的過程中,因為函式體內部的邏輯需要進行很多準備,所以常常需要有乙個引數準備的過程;而閱讀**的過程基本可以忽略這部分的邏輯,或者快速瀏覽這部分邏輯,這裡恰恰是很多新手花費大量精力糾纏的內容,其實沒必要在這裡糾結,跳過就好。
功能邏輯:這部分是函式體中最為精華的部分,而且**編寫起來也是相當的麻煩,被各種邏輯弄的死去火來,最後還需要重構等等手段;在閱讀**過程中,這部分其實很難把握,因為功能邏輯可能被封裝在另外乙個函式內部,這時候大家會習慣性的繼續深入看,結果弄的自己更加混亂,又比如有的時候幾個功能邏輯點組成了一套邏輯,但是大家卻將這部分邏輯割裂來看,結果總感覺讀的很彆扭。這部分內容需要一些經驗,但是有乙個指導,就是在看這部分**的時候要注意自己所站的高度,選擇採用何種策略。
閱讀**還有很多技巧,例如如何在帶有goto語句的**中快速理解邏輯,如何界定那些注釋是可以忽略的,如何將一些**邏輯看成一塊整體內容,何時應該跳到更深的一層函式閱讀等等。這些都需要平時的經驗積累。
看**有乙個粒度問題,我們不能一行一行的看,也不能乙個乙個函式的看,我之前提到了,linux核心有大量物件導向程式設計的影子,所以在看大量**的時候,必須學會物件導向程式設計的思維模式。這樣對自己在大量**閱讀中提供大量參考意見。
或許有人會告訴你,物件導向程式設計就是弄明白什麼是物件、如何寫乙個class就可以了。確實,學習物件導向程式設計,弄明白物件是基礎,不過我覺得可以再拔高一點,理解一些更抽象的概念,在這些抽象概念的指導下去學習,可以有更多的指導意義。
如果能夠理解上述的這幾個抽象,那在大量**中如何游刃有餘就相對容易了,有乙個簡單的套路:
(1) 在較高的角度,弄明白乙個系統為了解決什麼問題,應該有哪些抽象
(2) 在對整體結構有所了解以後,花心思看看這些抽象對應的領域模型,因為一般情況領域模型很龐大,所以看的時候也需要有步驟的進行拆解學習。
(3) 在對領域模型有所了解後,開始看領域驅動類,想明白為什麼會有這些操作。
(4) 在上述準備好後,就可以花費一些時間去看各個函式的具體實現,並且在看的過程中多思考領域模型為什麼這麼設計。
三、學習資料
學習的資料參考:
linux核心設計與實現(原書第3版) 清晰中文pdf見
linux kernel 的詳細介紹:請點這裡
談談如何學習Linux核心
節選自 上面說的太抽象,接下來就介紹一些我學習時候運用的一些小技巧,當然每個人都有自己的學習習慣,大家可以選擇性參考,我也只列舉了我使用的一些典型技巧。看書絕對不是一件容易的事情,有大量的技巧在其中,其中最讓我感受深刻的就是 不要從第一頁開始翻 不要一頁一頁的翻 我介紹一些我個人看書的技巧 如果開始...
談談如何學習Linux核心
參考 學習核心的好處很多,在學習過程中不僅可以夯實大量理論基礎,還可以學習到很多編碼慣用法,提公升學習能力和分析能力。一 確立高度,明確目標 在學習核心過程中最容易犯的錯誤,也是非常難掌握的其實是你站在乙個什麼樣的高度上去學習。站什麼樣的高度去學習也與自身的能力相關,所以這個問題其實更多是在新開始學...
談談新手如何學習PHP
文章開頭就列舉了那麼多 難免會讓大家感覺有點ad的意味,但是不容質疑的是,默默的確有那麼丁點的表現慾 雖然有時候過於細緻會被人說婆媽,但是幸好這種細緻對於程式設計來說,還是蠻有益的!從默默自己向別人問怎麼學php開始,到後來不少人又來問默默怎麼學php,不管默默是新手,還是老鳥,似乎總是感覺摸不出一...