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

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
