關(guān)于Linux內核學(xué)習的誤區以及相關(guān)書(shū)籍介紹
寫(xiě)給Linux內核新手-關(guān)于Linux內核學(xué)習的誤區
先說(shuō)句正經(jīng)的:其實(shí)我沒(méi)資格寫(xiě)這篇文章,因為自己也就一兩個(gè)月以來(lái)才開(kāi)始有所領(lǐng)悟的。因此,這里與其說(shuō)是關(guān)于Linux內核學(xué)習的經(jīng)驗,不如說(shuō)是自己的教訓吧,希望不要扔雞蛋砸我^_^
常常有人問(wèn):我想學(xué)習內核,需要什么基礎嗎?Linus Torvalds本人是這樣回答的:你必須使用過(guò)Linux。 這個(gè)……還是有點(diǎn)太泛了吧,我想下面幾個(gè)基礎可能還是需要的,盡管不一定必需:
1, 關(guān)于操作系統理論的最初級的知識。不需要通讀并理解《操作系統概念》《現代操作系統》等巨著(zhù),但總要知道分時(shí)(time-shared)和實(shí)時(shí)(real-time)的區別是什么,進(jìn)程是個(gè)什么東西,CPU和系統總線(xiàn)、內存的關(guān)系(很粗略即可),等等。
2, 關(guān)于C語(yǔ)言。不需要已經(jīng)很精通C語(yǔ)言,只要能熟練編寫(xiě)C程序,能看懂鏈表、散列表等數據結構的C實(shí)現,用過(guò)gcc編譯器,就可以了。當然,如果已經(jīng)精通C語(yǔ)言顯然是大占便宜的。
3, 關(guān)于CPU的知識。這塊兒可以在學(xué)習內核過(guò)程中補,但這樣的話(huà)你就需要看講解很詳細的書(shū),比方后面將會(huì )提到的《情景分析》。你是否熟悉Intel 80386 CPU?嘗試著(zhù)回答這幾個(gè)問(wèn)題來(lái)判斷一下:1)說(shuō)出80386的中斷門(mén)和陷阱門(mén)的區別;2)說(shuō)出保護模式與實(shí)模式的區別;3)多處理器機器上,普通的讀- 改-寫(xiě)回一塊內存這樣的動(dòng)作,為什么需要特殊的手段來(lái)保護。等等。講解基于其它CPU的Linux內核的書(shū),目前好象只有一本《IA64Linux內核:設計與實(shí)現》──也還是Intel的,其它都是講解基于IA32的。
以上算是知識方面吧,如果還要再補充一條,我想就是:動(dòng)手編譯過(guò)內核。
好了,我們接下來(lái)走。好多人裝上Linux之后,第一件事找到內核源碼所在的路徑,打開(kāi)一個(gè)C程序文件,開(kāi)始嘩嘩嘩翻頁(yè),看看大名鼎鼎的Linux內核代碼到底長(cháng)啥模樣──然后關(guān)閉。這是可理解的,但卻不是學(xué)習的方法。剛開(kāi)始,必須從讀書(shū)入手。至少要對內核有一個(gè)Overview之后,才有可能帶著(zhù)問(wèn)題去試圖閱讀源代碼本身。 下面就講一下我讀過(guò)的幾本書(shū):
1, 《Linux內核設計與實(shí)現》,英文名Linux Kernel Development(所以有人叫它LKD),機械工業(yè)出版社,¥35, 美國Robert Love著(zhù),陳莉君譯者。 評說(shuō):
此書(shū)是當今首屈一指的入門(mén)最佳圖書(shū)。作者是為2.6內核加入了搶占的人,對調度部分非常精通,而調度是整個(gè)系統的核心,因此本書(shū)是很權威的。這本書(shū)講解淺顯易懂,全書(shū)沒(méi)有列舉一條匯編語(yǔ)句,但是給出了整個(gè)Linux操作系統2.6內核的概觀(guān),使你能通過(guò)閱讀迅速獲得一個(gè)overview。而且對內核中較為混亂的部分(如下半部),它的講解是最透徹的。對沒(méi)怎么深入內核的人來(lái)說(shuō),這是強烈推薦的一本書(shū)。
翻譯:翻譯水平、負責任程度都不錯,但是印刷存在一些錯誤。買(mǎi)了此書(shū)的朋友可以參考我在Linux高級應用版的《Linux內核設計與實(shí)現中文版勘誤》:
http://bbs.chinaunix.net/forum/viewtopic.php?t=541234
另外,此書(shū)2005年有了第二版,目前尚無(wú)中譯本面世。我就是對照著(zhù)2nd-en勘誤1st-cn的。
2, 《Linux內核源代碼情景分析》上、下。毛德操、胡希明著(zhù),浙江大學(xué)出版社,上冊¥80,下冊¥70. 評說(shuō):
本書(shū)是基于2.4.0內核的,比較早,也沒(méi)聽(tīng)說(shuō)會(huì )出第二版。上冊講解內存管理、中斷、異常與系統調用、進(jìn)程控制、文件系統與傳統Unix IPC;下冊講解socket、設備驅動(dòng)、SMP和引導。關(guān)于這套書(shū)的評價(jià)褒貶不一,我個(gè)人認為其深度是同類(lèi)著(zhù)作中最優(yōu)秀的。本書(shū)基于Intel IA32體系,由于厚度大,很多體系上的知識都捎帶講解了,所以如果你想深入了解內核的工作機制而又不非常熟悉Intel CPU的體系構造,本書(shū)是最合適的。缺點(diǎn)是:版本較老,沒(méi)有TCP/IP協(xié)議棧部分(它講的socket只是Unix域協(xié)議的),圖表太少,不適合初學(xué)者入門(mén)。還有就是對學(xué)生朋友來(lái)說(shuō),可能書(shū)價(jià)偏高,這樣的話(huà)可以考慮先買(mǎi)上冊,因為上冊是核心部分,下冊一大部分都在講具體PCI/ISA/USB設備的驅動(dòng)。
翻譯:沒(méi)什么翻譯,作者是國人,而且行文流暢。本人書(shū)桌上諸多計算機經(jīng)典圖書(shū)當中,這套是唯一又經(jīng)典又無(wú)閱讀障礙的。
www.linuxforum.net內核版好多朋友已經(jīng)把這書(shū)讀到六七遍了,我很慚愧,上冊差不多讀熟了,下冊就SMP部分還看過(guò)──但這就花費了整整 1年的時(shí)間,還有好多弄不懂的。這里順便說(shuō)明另外一個(gè)研究?jì)群顺R?jiàn)的誤區:目標太龐大。要知道Linux內核(最新的2.6.13)bzip2壓縮之后 37M,解壓縮之后244M,根本不是哪個(gè)人能夠吃透的。即使是內核的核心開(kāi)發(fā)團隊中,恐怕也只Linus Torvalds、Alan Cox、David Miller、Ingo Molnar寥寥數人會(huì )有比較全面的了解,其它人都是做自己專(zhuān)門(mén)的部分。我自己來(lái)說(shuō),目前已經(jīng)決定放棄內存管理的全部(slab層、LRU、rbtree等)、文件系統部分、外設驅動(dòng)部分,暫時(shí)也沒(méi)打算弄IA32以外的其它體系的部分。
3, 《深入理解Linux內核》第二版。中國電力出版社。也是陳莉君譯。此書(shū)是Linux內核黑客在推薦圖書(shū)時(shí)的首選。 評說(shuō):
此書(shū)C版的converse兄送了我一本第一版,因此就沒(méi)買(mǎi)第二版,比較后悔。因此只就第一版說(shuō)一說(shuō),第一版基于2.2,第二版2.4 。我見(jiàn)O'Reilly官方主頁(yè)上說(shuō)第三版的英文版將于2005年11月出版,也不知咱們何時(shí)才能見(jiàn)到。此書(shū)圖表很多,形象地給出了關(guān)鍵數據結構的定義,與《情景分析》相比,本書(shū)內容緊湊,不會(huì )一個(gè)問(wèn)題講解動(dòng)輒上百頁(yè),有提綱挈領(lǐng)的功用,但是深度上要遜于《情景分析》。
4, 其它的幾本書(shū)。市面上能見(jiàn)到的其它的Linux內核的圖書(shū),象《Linux設備驅動(dòng)程序》、《Linux內核源代碼完全注釋》以及新出的《Linux內核分析及編程》等。
《Linux設備驅動(dòng)程序》第二版是基于2.4的,中文翻譯不錯,中國電力出版。這書(shū)強調動(dòng)手實(shí)踐,但它是講解“設備驅動(dòng)”的,不是最核心的東西,而且有些東西沒(méi)硬件的話(huà)無(wú)法實(shí)踐,可能更適合驅動(dòng)開(kāi)發(fā)的程序員吧,不太適合那些For fun and profit的人。此書(shū)有第三版英文版,東南大學(xué)出版社影印,講解2.6的,行文流暢,講解的面也比第二版更廣泛,我讀過(guò)其中關(guān)于同步與互斥、內存分配的部分,感覺(jué)很不錯。
《Linux內核源代碼完全注釋》(機械工業(yè)出版社)是同濟大學(xué)的博士生趙炯的著(zhù)作,講解0.1Linux內核,我沒(méi)買(mǎi)也沒(méi)看,有看過(guò)的朋友說(shuō)一說(shuō)。
《Linux內核分析及編程》(電子工業(yè)出版社)是剛剛出版的,國人寫(xiě)的,講解2.6.11 。很多人說(shuō)好,但有人說(shuō)不夠系統,我沒(méi)買(mǎi),不敢評說(shuō)。
還有一本清華出的《Linux內核編程指南(第三版)》,原書(shū)應該是好書(shū),但是翻譯、排版十分糟爛,脫字跳行,根本沒(méi)法看,我買(mǎi)了一本又扔掉了。
5, 其它資源。 TLDP(The Linux Documentation Project)有大量文檔,其中不少是關(guān)于內核的,有些是在國外出版過(guò)的,象《Linux Kernel Interls》《The Linux Kernel》《Linux Kernel Module Programming Guide》等,作者都是親身參加開(kāi)發(fā)的人,著(zhù)作較為可信。
Http://www.linuxforum.net
中國Linux論壇的內核版。該版是研究?jì)群说闹形腖inux社區中水平最高的,有很多專(zhuān)家級別的牛人,強烈推薦去學(xué)習一下(但建議不要問(wèn)太過(guò)分簡(jiǎn)單的問(wèn)題,人家脾氣再好也會(huì )煩的^_^),它的置頂貼簡(jiǎn)直是一個(gè)包羅萬(wàn)象的FAQ,精華區也有很多資料。只可惜太過(guò)曲高和寡,人氣不是很旺。
6, 一本不是講解Linux的書(shū):《現代體系結構上的Unix系統:內核程序員的SMP和Caching技術(shù)》,人民郵電出版社2003版,定價(jià)¥39. 本書(shū)雖然不是講解Linux,但是對所有Unix內核都是適用的,適合對SMP和CPU的Cache這些組成原理知識不是很熟的朋友,而且是很多國外牛人推薦的書(shū)。中文版翻譯非常負責。
還有個(gè)很重要的問(wèn)題:怎樣瀏覽內核源代碼。有的朋友喜歡在Windows上工作,用Source Insight;有的在Linux,用Source Navigator;還有專(zhuān)門(mén)瀏覽源代碼的軟件,象lxr(Linux Cross Reference);還有用ctags/ectags/cscope等,這些都是很優(yōu)秀的軟件。我個(gè)人用Vim ctags瀏覽(參考了www.linuxforum.net內核版wheelz大俠的文檔,)。
此外,前邊已經(jīng)提到的一個(gè)重要的問(wèn)題是:你研究?jì)群说哪康氖鞘裁矗?開(kāi)發(fā)? 樂(lè )趣?如果是開(kāi)發(fā),而且是國內做開(kāi)發(fā),把kernel API熟悉一下就差不太多了(你也知道國內的水平有多差),比方說(shuō)copy_from_user()、kmalloc()函數等,kernel API在Internet上找得到,編譯內核時(shí)也可以用DocBook生成(具體請參考內核源代碼包下的README文件);如果是研究,那就差別很大了,需要下很大的苦功:會(huì )用kmalloc()絕不說(shuō)明你懂得Linux內核的虛存管理子系統,正如同會(huì )講漢語(yǔ)不說(shuō)明你懂中國文化一樣。
說(shuō)完了,發(fā)現前面講的太羅嗦了,簡(jiǎn)化一下:
1, 動(dòng)手編譯內核
2, 精讀《Linux內核設計與實(shí)現》
3, 上www.linuxforum.net內核版看置頂貼與精華區
此外就憑自己興趣選擇吧。
下面是一篇沒(méi)寫(xiě)完的《Linux內核模塊編程入門(mén)》,不補寫(xiě)了,將就著(zhù)看吧。
albcamus 2005-10-13 02:41
寫(xiě)給Linux內核新手-關(guān)于Linux內核學(xué)習的誤區
Linux內核模塊編程入門(mén)
看到昨天有好幾個(gè)問(wèn)linux內核編程問(wèn)題的帖子,不少是卡在了入門(mén)問(wèn)題上,就整理一下入門(mén)的初步流程。針對2.6內核的Linux系統,需要你的機器上已經(jīng)安裝了kernel-devel這個(gè)包,也就是編譯模塊所必須的東西:內核的頭文件和一些Makefile。
一,Hello World程序:
[code]/*file: hello.c*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
static int hello_init(void)
{
printk(KERN_ALERT "Hello, The fucking crazy worldn");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Bye, The fucking crazy world!n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("albcamus ;");[/code'>albcamus@163.com>;");[/code]
2.6內核的kbuild子系統跟2.4相比有本質(zhì)的改變。我們下面嘗試兩種方式編譯這個(gè)程序:
1, 你可以在本目錄下這樣寫(xiě)一個(gè)Makefile
[code]obj-m := hell.o
clean:
rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions[/code]
然后用這樣的命令行編譯:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
這時(shí)ls一下,就能看到生成了很多文件,其中hello.ko就是我們需要的內核模塊。
2, 專(zhuān)業(yè)點(diǎn)兒,Makefile這樣寫(xiě):
[code]obj-m := hello.o
KERNELBUILD := /lib/modules/`uname -r`/build
default:
make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions[/code]
然后只要make一下就可以了。
插入模塊用insmod命令:
insmod ./hello.ko
這時(shí)候大家可能會(huì )問(wèn):為什么我的屏幕上沒(méi)有見(jiàn)到輸出?這個(gè)是console的日志記錄級別和你printk消息時(shí)指定的級別(本例中指定為 KERN_ALERT,為次高,僅次于KERN_EMERG)決定的。無(wú)論如何,你可以tail 或者cat看看系統日志的最后幾行,系統日志一般為/var/log/messages,或者直接用dmesg命令,肯定能看到輸出了。
二,頭文件問(wèn)題。
C 程序員都知道,要使用某個(gè)外部的函數,應當#include某個(gè)頭文件,這個(gè)頭文件包含了那個(gè)函數的原型(prototype)。內核的頭文件在 include/下,其中include/asm是個(gè)符號鏈接,指向你所用內核的具體的體系結構目錄,比方說(shuō)我的系統是i386的,那么 include/asm就指向include/asm-i386 。
內核編程中我們不能鏈接libc庫,不能使用libc庫中的函數,所以很有些麻煩。一些重要的函數,象strcpy/strcmp/snprintf等,kernel也為我們實(shí)現并導出(export)了,而我們需要 #include相關(guān)的頭文件,在include/linux和include/asm中,你需要自己尋找你所要使用的函數在哪個(gè)頭文件中聲明,并將其 #include進(jìn)來(lái)。
評論