Linux內核應該怎麼去學習?
我現在的狀況是對操作系統原理有比較好的理解,讀過一個小型操作系統(10k行左右代碼)。現在想找本linux內核源碼分析的書,只是想了解一下linux設計思想,今後工作中(後台開發)不一定用的到。應該讀什麼書呢?現在知道&
和& ,哪本更適合我,或者還有什麼更好的推薦嗎?
通過閱讀源碼來學習操作系統要注意區分共性與平台特性。
1. 中斷響應是共性,8259 中斷控制器和 IDT 是 x86 的特性。
2. 虛擬內存管理是共性,x86 的 GDT 和 LDT 是特性,而且現在的系統也只是走個過場而已。
3. 任務調度與上下文切換是共性,x86 的 TSS 是特性,而且現在的系統(2.2.0 以後)也不用 TSS 做任務切換了,早期的 Linux 是用了 TSS 的,讀老代碼的時候要注意。
4. IO 是共性,位於 0xB8000 的顯示緩衝區是 x86 的特性。
5. 系統初始化是共性,BIOS 把引導扇區載入到 0x7C00 是 x86 的特性。國內好多書對 PC 的系統引導過程(booting)大書特書,是主次不分、本末倒置,你學的是操作系統,不是 boot loader 。
https://www.zhihu.com/question/20541014/answer/93312920
關於內核學習我建議不要上來就讀內核而是先了解內核的構成和特性,然後通過思考發現疑問這時再去讀內核源碼。即先了解概貌在讀局部細節。而且內核分成好多部分,不要只是按照順序去讀,應該針對某一部分比如內存管理或進程管理橫向讀幾本書,這樣可以理解很全面。
Linux Kernel 四庫全書
1. Linux內核設計與實現 Edition 2
2. Linux設備驅動 Edition 3 3. Linux內核源代碼情景分析 4. 深入理解Linux內核(第三版)1.《Linux內核設計與實現》
本書重在原理。適合入門的最佳圖書。作者是為2.6內核加入了搶佔的人,對調度部分非常精通,而調度是整個系統的核心,因此本書是很權威的。
2.《深入理解Linux內核》
此書比上一本多了些細節。是Linux內核黑客在推薦圖書時的首選。寫的比較簡單易懂,適合剛剛接觸LINUX內核的。
此書圖表很多,形象地給出了關鍵數據結構的定義,與《Linux內核源代碼情景分析》相比,本書內容緊湊,不會一個問題講解動輒上百頁,有提綱挈領的功用,但是深度上要遜於《Linux內核源代碼情景分析》。3.《LINUX設備驅動程序(第3版)》
這書強調動手實踐!但它是講解「設備驅動」的,不是最核心的東西,而且有些東西沒硬體的話無法實踐,可能更適合驅動開發的程序員吧
其中關於同步與互斥、內存分配的部分,感覺很不錯。
4.《Linux內核源代碼情景分析》
書很好,很經典,是浙大教授毛德操寫的,可惜成書於2001年之後一直沒有更新。分上下冊。
很多是基於2.4內核講解的需要注意。如果學習的話也建議學習2.6,2.6跟2.4比發生了很多顯著改善,應該學習的。
全書內容博大精深,不是非常好懂,對細節問題描述比較清晰。但是感覺對內核的整體感覺不夠強。另外缺少網路部分的分析。覺得不是很適合初學者。
上冊講解內存管理、中斷、異常與系統調用、進程式控制制、文件系統與傳統Unix IPC;下冊講解socket、設備驅動、SMP和引導。本書基於Intel IA32體系,由於厚度大,很多體系上的知識都捎帶講解了,所以如果你想深入了解內核的工作機制而又不非常熟悉Intel CPU的體系構造,本書是最合適的。
這本書可以結合陳莉君老師的《深入分析Linux內核源代碼》,這本書也是2.4內核的,網上可以下載
作者: 陳莉君
出版社: 人民郵電出版社出版年: 2002-8頁數: 531ISBN: 9787115105257說明:陳老師是上述《深入理解Linux內核》和《Linux內核設計與實現》的作者,曾通讀過linux的所有代碼。
==================擴充閱讀==================
5.《Linux內核源代碼分析》
作者: (美)Scott Maxwell
譯者: 馮銳/邢飛/等出版社: 機械工業出版社出版年: 2000-06頁數: 633ISBN: 9787111080923點評:面對中高級,這本書很好,對了解操作系統是一本不可多得的好書。
6. 《LINUX KERNEL技術手冊》
參考手冊,很薄,值得一看。
7.《深入Linux內核架構》
這本書針對的是比較新的內核版本2.6.24;內容比較全面,深入淺出。
如果沒有對Linux內核的初步結構的認識,那麼會看得比較吃力。 建議可以一邊去翻在國內已經聞名已經久的四本Linux內核著作(《Linux內核原代碼情景分析》、《Linux內核設計與實現》、《深入理解Linux內核》、《Linux設備驅動程序》),再一邊看這本書,把這本書當作一個補充或者當作一個內核框架圖譜說明書來閱讀,收效會更好。
8.《Linux內核完全注釋》
此書出自同濟一個博士--趙炯。
主要描述和注釋了Linux 0.11內核全部源代碼。對於初學Linux內核操作系統的人來講,該書能夠引領讀者快速入門,並且能全面了解一個簡單操作系統的工作機理。對於進一步學習現在的Linux內核具有非常大的指導作用。對於學習嵌入式應用的技術人員來講,通過《完全注釋》一書的學習也能迅速融入嵌入式應用領域。同樣,該書也能作為閱讀現代Linux內核源代碼的一本參考手冊使用。由於該書是對代碼逐條進行注釋的,因此也能作為深入學習C語言編程的參考書。另外,該書不僅配備有完整的Linux 0.11系統試驗環境,而且本人還在一年前就在網上專門建立了一個針對該書的網站「www.oldlinux.org」,專門開闢了一個討論該書所涉及的Linux內核實現的論壇。目前該網站的內容已經被權威Linux內核發布網站http://www.kernel.org全部作了鏡像(http://mirrors.kernel.org)。
http://oldlinux.org/index_cn.html
網站宗旨:
收集Linux從醞釀到開發初始版本有關的所有資料和信息(1991-1995);
重新建立起最古老的Linux可運行系統,這些系統在其它地方很難再找到了;
為初學者提供一個學習Linux內核基本工作原理的最簡單方法。
本書新版:《Linux內核完全剖析--基於0.12內核》
2009年出的,很厚。
===============自製操作系統系列==================
9.《Orange S:一個操作系統的實現》
作者:於淵
出版社: 電子工業出版社; 第1版 (2009年6月1日)
本書第一版2005年出版,這是第二版。
從只有二十行的引導扇區代碼出發,一步一步地向讀者呈現一個操作系統框架的完成過程。
10.《30天自製操作系統》
作者: (日)川合秀實 [作譯者介紹]
譯者: 周自恆 李黎明 曾祥江 張文旭叢書名: 圖靈程序設計叢書出版社:人民郵電出版社ISBN:9787115287960點評:小日本寫的,不過確實寫的內容很好,講怎麼自己一步步寫操作系統,從彙編到C都有涉及。
_________________________________________________________________________
unix是Linux的基礎,學習linux也要看unix
Unix的絕版好書
UNIX操作系統設計
原書名:The Design of the UNIX Operating System
作者: (美)Maurice J.Bach 譯者: 陳葆鈺 王旭 柳純錄 馮雪山叢書名: 計算機科學叢書出版社:機械工業出版社ISBN:9787111373971點評:當年linux之父參考過,非常經典,無需多言
----------------------------------------------------------
UNIX編程環境
原書名:The UNIX Programming Environment
作者: Brianw.Kernighan
譯者: 陳向群叢書名: 計算機科學叢書出版社:機械工業出版社點評:非常好的入門書.書中絕無生僻的角落,對於入門來說沒有什麼難以理解的。但是字裡行間浸透了作者設計unix的指導思想,這一點是別的入門書無法企及的。
書中提及的點滴都是實用的方法和準則,而這些充斥著在unix上一整天的工作,即使是有經驗的用戶學過此書後工作效率也會提升。UNIX高級教程系統技術內幕
作者: (美)Uresh Vahalia
譯者: 聊鴻斌/等 出版社: 清華大學出版社出版年: 1999-05點評:老書,有電子版。linux/unix的頂級寶貝!補充:
評論區知友 @逸文奧特曼 推薦一本《 操作系統真象還原 》
作者:鄭剛
出版社: 人民郵電出版社
出版年:2016-03
點評: 用詼諧幽默語言講述的深入理解操作系統原理的精品 輕鬆自製操作系統 操作系統並不深奧 本書給予全新解讀
你想更深入了解學習Linux知識體系,你可以看一下我們花費了一個多月整理了上百小時的幾百個知識點體系內容:
【超全整理】《Linux雲計算從入門到精通》系列實戰筆記全放送
如果天賦不是很高,那麼建議先從應用層入手,把應用層玩得比較熟練以後,再開始學習內核。因為內核是為應用服務的,精通應用層以後,再去分析內核源碼,至少知道一些線索了。
那麼內核源碼從哪裡入手呢?
1. 先閱讀經典的內核書籍—— 前面已有不少人提過了,不重複說了;重要的是理解原理。
2. 可以從系統調用的API入手分享;
3. 從自己熟悉的領域入手。以我自己為例,我的領域是網路,所以看內核源碼就是從網路模塊入手,這樣看起來事半功倍。
4. 閱讀內核Document目錄下的自帶文檔——寫的相當好。比如講memory-barrier.txt,把編譯器的優化,CPU的亂序執行,講的相當清楚;
5. 寫一些簡單的內核代碼,可以從獨立的內核模塊開始;
6. 嘗試修改內核源碼,為社區貢獻補丁。我是去年8月開始做這一步的,第一次被內核社區接受補丁時,還是非常興奮的。現在已經被接受幾十個了:D
不要糾結改動有多小,任何小的改善,都會促進內核的發展。
7. 堅持每天都看看內核代碼。
我看了下都從技術角度了,到現在這個技術發展階段,我建議首先考慮一下自己的學習目的是什麼,是不是真的需要學習Linux內核,同樣的時間如果學了別的會不會更好?
不要越過山丘,才發現無人等候。
第一步,如果你不是CS出身的,可以找一本操作系統的書了解一下操作系統的概念。
第二步,找一本Linux內核的書,粗略讀一下,了解概念,不懂沒事,帶著問題到下一步去尋找。前面有人提醒的很好,有些書沉迷啟動,頁表管理之類的概念(尤其是X86的),其實沒毛用,大概明白能和人吹牛聊天就可以了,真到工作的時候用到再看就可以。
第三步,你已經有讀代碼經驗了,建議現在可以找一塊有錢途的,和工作有關,感興趣的(按照個人感覺的重要性排序)內核中的一個子系統,深度的讀一讀。讀不明白可以藉助各種模擬器調試器,也可以搜搜網上的介紹,當然也可以看看書(不過這時候很可能會發現網上的介紹或者書遠沒有代碼更清晰)。
做個類比:比如說寫python, 那麼python的各種庫用的越熟,可以說python就很會了。
對於研究內核啥的也類似,操作系統的核心就是多任務處理,內存管理, 單這些都跟cpu的spec息息相關,所以你看《understand linux kernel》前面講segment和page都是跟硬體相關,後面才是linux是如何利用這些cpu硬體特性實現功能。
所以
1。要是為了求知,那最好從CPU本身開始,從頭寫一個簡單的os, 這裡推薦一個同事自己寫的os : Ted-Chang/matrix, 一個不錯的用來教育和學習操作系統的項目。歡迎star,歡迎交流~
2。要是為了生產力,快速解決問題,服務生產,那就簡單多了,讀完rober love的《Linux Kernel Development 3rd edition》, 知道一下kmalloc和vmalloc有什麼區別, spin_lock什麼的怎麼用,找一個開源的子系統,馬上就可以開工了。 在生產實踐中學習,從修復mail list 裡面的bug開始,帶著問題讀代碼效果最好。 我當時得到的建議是讀ext2的代碼,連journal都沒有,也容易入門。
如果你是學生,只要C基礎不錯,熱愛底層技術,爭取去SuSE北京office實習,雖然我離開已經快4年了,但是還很喜歡裡面的技術氛圍。
比如Cluster support for MD/RAID 1, 就是在SuSE做的。其實在實際項目里學得最快~
其他同學推薦的Robert Love(前SuSE同事): Robert Love - Quora
還有gregkh(也是前SuSE同事, linux的stable版本的maintainer) https://twitter.com/gregkh
首先你要知道大陸有一位諢名茶水的大犇巨擘,然後你設法去結識他,有機會多聆聽他的教誨。並不一定是特別具體的技術,更寶貴的是很多技術人生的道理,然後就是自己的樂趣和努力。進步通常都是百分之九十九的汗水和百分之一的靈感,茶大大是那個可以讓人產生百分之一靈感的存在。
先從小模塊開始,比如,先從驅動開發開始了解。針對一個設備驅動代碼(比如MMC),了解為什麼要在驅動中設置spinlock、BLOCK_IO/UNBLOCK_IO、synchronous IO/asynchronous IO、interrupt 等。並學習如何使用它們。
等熟悉了kernel API, 再去學習背後的原理,自然事半功倍。
只說一點:在弄清一段代碼的具體邏輯之前,要對這段代碼執行的上下文有清醒的認識,中斷,內核線程,還是系統調用。否則看再多細節,腦子裡都是一團漿糊。
花幾個月時間把linux 0.01自己實現一遍,把本科操作系統課程的內容融會貫通,對未來進一步學習理解有極大的幫助。至於現在的linux內核已經是一個極大極為複雜的工程,根本不適合初學者入門。建議從內核剪裁,配置,編譯環境搭建這些簡單並且實用的工作入手,然後根據實際需求學習相應部分的知識。不建議純粹看書,尤其是那種大部頭上來五六百的那種,沒有強烈的興趣驅動,我不相信有人能看的進去。
哥們,別推薦書了,雖然我自己也寫了一本底層的書。但是我認為學習內核的最好方法是去擼代碼,看代碼。有一個知識點大綱,然後一個個的去看lwn,看內核doc,看代碼,對於模塊,文件系統等還得去實際的寫一下。最好有個內核開發的工作。不工程應用,你把市面上的書全看完都沒用。我覺得看書是懂了之後查漏補遺的,不是用來初始學習的。
書的話要反覆看可能看一遍沒有看懂多看幾遍就懂了,推薦 linux kernel development 這本書,和其他大部頭比起來不算厚,但重點講的很好。
實際上 linux 就是你上學學的操作系統的一個實現,等你真正明白了某個子系統的時候你會發現自己上學的時候其實都學過只是太抽象了。裝個虛擬機 搞個 2.6 的內核 好好折騰吧。
推薦「深入linux內核架構」這本書,不會初學者陷入不必要的細節
看內核源碼
既然對操作系統原理有了基礎,那了解 linux kernel 最高效的途徑就是動手改著玩,少看書 ,省腦,kernel 中沒有什麼特別的東西。
可以用虛擬機,從頭編譯起基本系統,熟悉了再實現一些虛擬設備,子系統等。有條件就買個開發板,也能做這些事,還可以看看驅動有什麼不理想的,一般總會有的,試著改好。玩上幾個月,就可以確信自己精通 linux kernel 了。
像 kernel 這種實際使用並頻繁更新的東西,學習應該以手代腦,具體的細節,書上寫的常常過時或重點主次不當,看書得到個大概印象就行了,不要花時間細扣,不划算。感覺其實不是去搞upstream的kernel,你要看的大部分都是驅動。
但是搞驅動首先應該搞明白的是硬體的工作原理,然後再用kernel的API等東西去實現時序和邊角。
當然也有可能這是我看書看多產生的學而不思則殆的錯覺。
做Linux後台開發,現在國內大部分公司有這樣的職位,其實其要求是Linux後台伺服器開發,需要掌握的是系統編程,參考書籍是Linux程序設計,UNIX環境高級編程,UNIX網路編程等。我在華為做了4年Linux內核開發,又稱之為嵌入式開發,目前國內搞Linux內核開發的大公司很少,因為華為做CPU,那就必須做內核開發,這樣才能發揮CPU的性能,搞內核開發的小公司,都是嵌入式公司,而且大部分重點在驅動開發。阿里也有搞Linux內核,但是騰訊的操作系統層全部交給Suse去管理了。不要隨意去學一個東西,個人認為最難自學的有內核,設計模式,複雜演算法,編譯原理。搞清楚自己的目的再學習,不要把人生浪費在無意義的學習上,好多內核的書都寫的不咋地,那本深入理解Linux內核,個人認為翻譯的一般。先弄清楚你的目的真正需要什麼技能,再去學習!
- 我覺得第一本書最好是 &
by Robert Love
個人覺得這是最容易入門的一本,沒有太多的細節,不像直接分析0.11版本所有源碼的那種書事無巨細全給你說,它只是告訴你這個子系統大概是什麼實現思路,有哪些數據結構,對應的操作是什麼。至於具體的實現,你如果有興趣自己再鑽研吧。
我覺得這是比較正確的一種思路,一開始就陷到很多底層細節里,很容易失去興趣,也不容易整體有宏觀的把握。
- 另外推薦下一個網站: http://eudyptula-challenge.org/ 如果你有興趣的話,大概是一系列的關於kernel development的challenges,一共20個題 (好像偏driver?)
另外就是一些子系統的設計的更詳細的東西,可以找相關的文檔,或者有對應的書,比如
- 驅動有 &
by Corbet, Rubini, Greg-KH - VM &
by Mel Gorman - etc..
BTW, 我只是kernel newbie,所以實力眼界有限,如果想了解更多可以去 stack exchange 上搜相關問題。
學習內核的好處很多,在學習過程中不僅可以夯實大量理論基礎,還可以學習到很多編碼慣用法,提升學習能力和分析能力。
但是如果問其如何學習Linux內核,不同的人會給出不同的答案,有的人會告訴你先去看看0.11的內核源碼,有的人則是推薦先看《Linux內核設計與實現》這樣的書,有的人則會說先把內存定址學懂,然後再開始考慮網路協議棧和文件系統之類的內容。Linux內核設計與實現 第二版下載地址:http://www.linuxidc.com/Linux/2011-05/35530.htmLinux內核設計與實現(原書第3版) 清晰中文PDF 見 http://www.linuxidc.com/Linux/2014-02/96174.htm如果是以前,我一般都是上面的幾個答案,不過今天的內容並不從這幾個角度去介紹,而是介紹一些我學習過程中的一些小技巧。高度決定視角,視角決定行動在學習內核過程中最容易犯的錯誤,也是非常難掌握的其實是你站在一個什麼樣的高度上去學習。站什麼樣的高度去學習也與自身的能力相關,所以這個問題其實更多是在新開始學習的學習者感到非常痛苦的一件事。一方面又希望自己能學懂,但是又不知道如何開始入手。我列舉幾個常見的例子:(1) 一開始就看源碼,最開始我也做過這種事,內核有什麼都不知道,結果就想著啃0.11的內核,結果很顯然,2天立馬放棄,完全看不懂。(2) 翻開書從第一頁開始往下啃,如果這本書比較薄還好,如果比較厚,比如《深入Linux內核架構》,那看2天也得放棄。(3) 不喜歡看目錄,不喜歡快速瀏覽,就想著一個一個字眼的往下摳。如果本身有一定基礎,看的時候還不會覺得膩,但是很快就發現,看了半天,什麼都沒有記住。還有很多類似的問題,這些都是我們平時學習的時候特別容易出現的一些誤區。這些其實都是沒有正確審視自己的能力,胡亂挑選高度導致。高度是什麼?說了半天,這個高度到底是什麼?我這裡給一個我自己的界定:高度:指切入問題時採取的抽象程度。語文不好,說的亂七八糟,說的直白一些,也就是說:高度越高,也就是越偏向於理解各種抽象概念,傾向於構建對整體結構的一個認知,忽略一些不必要細節,不關心技術實現手段。高度越低,也就是越偏向於對使用技術的選擇,傾向於代碼實現的各個細節,但是前提一般會在某個抽象的概念領域內進行各種細節性的討論。我們的大腦更傾向於理解抽象的內容,但是在行動時,我們卻更傾向於去把握細節性的內容。結果導致的內容就是,我們總是希望通過學習細節來構造對抽象概念的理解,最後被細節性內容中各種雜訊干擾思緒,產生一種「這東西好難」的錯覺。在理解了這點,那高度對我們的行為有和指導意義也就呼之欲出了?以讀書為例站的越高,意味著自己看的內容越粗糙,也就是看書的時候不會去逐字逐句的看,而是一個章節一個章節的看,極端的情況就是只看目錄,在這個過程中主要集中精力構建整體結構,對核心的概念進行抽象。這時候學的內容都相對錶面,但是好處就是對以後的學習有很強的指導意義,缺點很明顯,會讓人底氣不足,而且在達到一定程度後,很容易到達瓶頸,發覺怎麼看都看不懂了。站的越低,意味著自己看的內容很細緻,看書的時候就是一個個字眼的扣,極端情況就是開始閱讀源碼,去看開源社區的各種問題。但是就像詩句說的,站的越低,也就常有一種「不識廬山真面目,只緣身在此山中」的感覺。這種情況下特別容易被各種細節干擾,例如為什麼要有這些參數,為什麼這裡需要判斷這個條件等等這些細枝末節的問題。如何運用高度以前對一篇博文印象很深刻,作者理解的學習曲線劃分成了兩個比較大的過程,上升的過程就是一個不斷學習積累的過程,而平緩沒有增長的過程則是對之前積累到飽和的知識進行消化的過程。我將這個學習過程進行進一步的劃分,我覺得在學習積累的前半部分應該以偏向學習抽象概念為主,而後半部分應該偏向學習實現細節。所以個人的心得是從高到低的學習,在一個新的學習階段,應該先多花點時間學習一些概念化的內容,這時候切忌去看具體的實現,而是多考慮如何在大腦中構建各種抽象模型,對整體的架構有所概念了,然後開始學習一些細節性的內容,比如開始看些源碼,摳寫書上的字眼,讀讀一些具體的博客什麼的。註:在圖中還有一個消化過程,這個過程的主要任務就是將不同的知識點進行串聯,形成一個有粗有細的知識拓撲網路。Linux Kernel 的詳細介紹:請點這裡Linux Kernel 的下載地址:請點這裡相關閱讀:Linux內核將用nftables替代iptableshttp://www.linuxidc.com/Linux/2013-10/91727.htmLinux 3.12代號Suicidal Squirrelhttp://www.linuxidc.com/Linux/2013-09/90023.htm怎樣在 Ubuntu 上安裝 Linux 3.11 內核http://www.linuxidc.com/Linux/2013-09/89674.htmUbuntu 13.10 (Saucy Salamander) 內核已升級至 Linux Kernel 3.10 RC5http://www.linuxidc.com/Linux/2013-06/86110.htmLinux Kernel 3.4.62 LTS 現已經提供下載http://www.linuxidc.com/Linux/2013-09/90368.htm如何在Ubuntu 13.10上安裝Linux內核 3.12http://www.linuxidc.com/Linux/2013-11/92930.htm學習小Tips
上面說的太抽象,接下來就介紹一些我學習時候運用的一些小技巧,當然每個人都有自己的學習習慣,大家可以選擇性參考,我也只列舉了我使用的一些典型技巧。 如何看書看書絕對不是一件容易的事情,有大量的技巧在其中,其中最讓我感受深刻的就是:不要從第一頁開始翻不要一頁一頁的翻我介紹一些我個人看書的技巧 花些時間看看前言,在很多書的前言部分,作者會告訴你,整本書的結構應該是什麼樣,應該要以什麼樣的順序去閱讀,在閱讀的時候應該站在什麼樣的角度去閱讀,這是作者的建議,有什麼比作者的建議更值得我們聽取呢!?不要寄希望與一次看懂一本書,越是好的書越是要反覆的看,但是很多人對這個反覆理解有問題,認為反覆的看就是一頁頁翻,重複看幾遍。其實不是這樣,每次反覆應該讓自己換一個高度,第一次翻的時候可以站在很高的高度,看一本書甚至只需要1天的時間,重複幾次後,站的高度應該越低,很可能看一個章節需要1天時間,甚至有時候看一頁就需要1天的時間。一本書的目錄就像你在沙漠中的指南針,不要忽略目錄的作用。每次翻開書,在決定自己看什麼之前,花點時間瀏覽下目錄,讓自己回憶(了解)要看的章節的架構,帶著這個結構去學習事半功倍。帶著問題去看書,這點很難,因為提什麼樣的問題和你選擇的高度密切相關,站的高度越高,那就越不要給自己提一些細節性的問題,反之則反之。還有很多更細緻的技巧,例如如何辨別哪些是需要關注的關鍵詞,如何將書本中不同章節的知識點串聯等等,有很多我自己也做不好,所以也就不在這獻醜了。 如何看代碼如果開始看代碼,一定要記住,自己已經站在一個非常底層的高度度了,能夠有能力閱讀代碼,就意味著你必須對整體的結構有比較清晰的認識,如果你都不知道這個結構,那看代碼為時太早。無論是什麼樣的代碼,其實思路都很類似,即使Linux內核是用C這種面相過程的語言編寫,但是這麼多年發展下來,Linux內核已經帶有了大量面對對象編程的特點。 在看代碼的時候也是有兩種不同的高度可以選擇,我先解釋其中最細緻的一種:如何閱讀函數一個函數寫下來經常上百行,但是你需要一行一行的看么?肯定不能,那清晰認識一個函數的結構就很重要。一個函數就是為了解決一個問題,函數名基本都能說明其功能,函數參數是輸入,返回值就是輸出,函數體就是整體的執行邏輯。在函數體內部,也基本都是類似的邏輯,先是對各種輸入參數進行檢查,然後書寫功能邏輯,然後構造輸出的結果。所以一個函數寫下來總是這樣的一種結構。輸出結果 函數名(輸入){ if (輸入的參數有問題) { 異常處理,跳出 } 準備參數 功能邏輯 構造輸出結果 返回輸出結果}一個函數其實就是一個方法,閱讀的難度比書寫的難度要低,書寫代碼需要考慮的問題非常多,但是在閱讀代碼的時候問題就簡單很多,很多書寫代碼過程中需要考慮的問題在閱讀代碼的過程中就不需要考慮 函數名:在書寫代碼過程中需要考慮一個函數的函數名需要能夠精確表達出這個函數所具備的功能,所以經常存在各種名目規範。而閱讀代碼過程則可以通過閱讀函數名大致了解這個函數的功能。注釋:在編寫代碼的時候,都會建議添加對應的函數注釋,解釋函數體的功能和一些注意事項;在閱讀過程中可以選擇性的閱讀這些注釋(注意:是選擇性閱讀,千萬不要每個注釋都讀)輸入參數:在書寫代碼的時候,這部分的內容也是很頭疼的內容,不僅需要確定需要哪些輸入,還需要輸入的形式,而且還需要精確定義每個輸入參數的語義;但是在閱讀代碼的過程中,這部分內容基本可以忽略,我們很少會關係所看到的函數需要哪些參數輸入。輸出結果:在書寫代碼的時候,這部分也是很頭疼的一件事,因為精確定義輸出結果也是非常困難和麻煩的一件事;在閱讀代碼過程中,也需要注意輸出結果,不然一個函數執行了老半天,結果連輸出結果是什麼都沒概念,也太失敗了點。參數檢測:在編寫代碼過著中非常煩的一件事,每個人都希望調用函數的人會傳入正確的參數,但是根本做不到,結果每次都要花費一定精力對輸入參數的邊界、非空等進行檢查;在閱讀代碼過程中,根本不需要閱讀這部分的代碼,恰恰這部分內容在每個函數體中佔據了相當一部分的位置;參數準備:編寫代碼的過程中,因為函數體內部的邏輯需要進行很多準備,所以常常需要有一個參數準備的過程;而閱讀代碼的過程基本可以忽略這部分的邏輯,或者快速瀏覽這部分邏輯,這裡恰恰是很多新手花費大量精力糾纏的內容,其實沒必要在這裡糾結,跳過就好。功能邏輯:這部分是函數體中最為精華的部分,而且代碼編寫起來也是相當的麻煩,被各種邏輯弄的死去火來,最後還需要重構等等手段;在閱讀代碼過程中,這部分其實很難把握,因為功能邏輯可能被封裝在另外一個函數內部,這時候大家會習慣性的繼續深入看,結果弄的自己更加混亂,又比如有的時候幾個功能邏輯點組成了一套邏輯,但是大家卻將這部分邏輯割裂來看,結果總感覺讀的很彆扭。這部分內容需要一些經驗,但是有一個指導,就是在看這部分代碼的時候要注意自己所站的高度,選擇採用何種策略。構造輸出結果:函數體內部還會花費大量的代碼進行對最後返回結果的構造工作,就像搭積木一樣;不過在閱讀代碼的時候,我們並不需要花費太多精力在這些邏輯上,多注意注意一些返回結果的語義。 閱讀代碼還有很多技巧,例如如何在帶有goto語句的代碼中快速理解邏輯,如何界定那些注釋是可以忽略的,如何將一些代碼邏輯看成一塊整體內容,何時應該跳到更深的一層函數閱讀等等。這些都需要平時的經驗積累。如何在大量的代碼中遊刃有餘看代碼有一個粒度問題,我們不能一行一行的看,也不能一個一個函數的看,我之前提到了,Linux內核有大量面向對象編程的影子,所以在看大量代碼的時候,必須學會面向對象編程的思維模式。這樣對自己在大量代碼閱讀中提供大量參考意見。或許有人會告訴你,面向對象編程就是弄明白什麼是對象、如何寫一個class就可以了。確實,學習面向對象編程,弄明白對象是基礎,不過我覺得可以再拔高一點,理解一些更抽象的概念,在這些抽象概念的指導下去學習,可以有更多的指導意義。層:層並不是面向對象編程特有,但是理解層是很重要的,我們遇到的典型的層就是網路協議棧,為什麼我們網路協議會有那麼多層,就因為需要處理的事情太多,我們不得不將內容一塊塊的分割,分割的時候,發現用層進行組織,可以讓結構更加清晰,所以你以後會發現,大量的系統都會帶有層的味道。linux內核中帶有大量的層設計,如網路協議棧有層,內存管理與定址有層,文件I/O也有層。領域模型:領域模型就是一個系統中最為核心的幾個抽象實體,一個系統,基本就是圍繞著領域模型展開,在學習內核不同的子系統的時候,一定要花大量的精力在領域模型上,切記!!!在Linux內核上也有大量的領域模型,例如在虛擬文件系統部分存在4大抽象inode,dentry,file等。在進程調度系統的最核心抽象是task_struct。在進程地址空間則有mm_struct,address_space等這些核心的領域模型。我感覺可以花費80%的時間在理解這些領域模型上。領域驅動類:領域模型內部其實是大量的屬性組成,但是如果只有屬性,沒有一個執行的方法,那這個領域模型也不能發揮作用,面向對象編程的做法就是將這些方法編程領域驅動類,說的直白一些就是介面。在Linux中就是那些函數指針和對應的回調函數。平時看代碼,大家會花費大量的時間去看各個回調函數,這個其實是吃力不討好的辦法,與其花大量的心思去看各個回調函數的實現,不如多思考下,為什麼會有這些操作方法,它們是如何抽象出來的。如果能夠理解上述的這幾個抽象,那在大量代碼中如何遊刃有餘就相對容易了,有一個簡單的套路:(1) 在較高的角度,弄明白一個系統為了解決什麼問題,應該有哪些抽象(2) 在對整體結構有所了解以後,花心思看看這些抽象對應的領域模型,因為一般情況領域模型很龐大,所以看的時候也需要有步驟的進行拆解學習。(3) 在對領域模型有所了解後,開始看領域驅動類,想明白為什麼會有這些操作。(4) 在上述準備好後,就可以花費一些時間去看各個函數的具體實現,並且在看的過程中多思考領域模型為什麼這麼設計。 總結文中的內容就是我個人的一些學習Linux內核的心得,這個心得其實不僅僅可以用於學習Linux內核,在大量場景下也適用。還有很多內容可以談,限於能力有限,很多東西沒辦法用文字表達出來,等什麼時候能力足夠了,再繼續把後續內容補上。以這個基礎,隨便哪本書配上源碼應該都可以。不過如果工作不是立即用得上,看了估計收穫也有限,不如 Unix 環境高級編程,Linux 設備驅動程序,Linkers and Loaders 依次練過來。
帶著問題學內核,學用結合,活學活用,急用先學,立竿見影,在「用」字上狠下功夫。
推薦閱讀:
※問一個函數指針問題?
※自學c語言,有什麼好的建議或方法嗎?
※C++標準庫中有哪些危險函數?
※如何學好編程語言以及進行軟體開發?
※美劇《矽谷》第三季第一集神秘代碼寫的是什麼?