[書籍導讀]
Linux 驅動程式 第二版
導讀
這本書是針對 Linux 2.4 版核心而寫的。2.4.0 測試版剛推出時,兩位作者開始寫這本書,原文書出版時,2.4.11
已經推出了。我看完這本書並開始翻譯時,已經是 2.4.18 版的時代了,等到完成翻譯與校對工作,2.4.24 與 2.6.1 版都出現了。對於想要從本書獲得
2.6 版知識的讀者,現在就可以告訴你,死心吧。如果真的有什麼理由讓你非得研究 2.6 版不可,那麼,捐點小錢給作者,或許可以如願以償:https://lwn.net/Articles
/driver-porting/。
如果你是第一版的讀者,或是已經有 Linux 驅動程式(或任何核心程式)的寫作經驗,請跳過這篇導讀,因為你己經知道我要交代的東西。如果你從沒在
Linux 系統上寫過任何程式,請將本書放回書架,因為這本書帶給你的挫折感,將遠高於你能得到的成就感。如果你懂 C 語言,而且也有一點程式設計經驗,但是從沒寫過
Linux 驅動程式,那麼,這一篇導讀或許對你能有所幫助。
基本知識
很顯然地,本書的主題 - 驅動程式 - 並不適合初學程式設計的新手。然而,本書第一版的經驗告訴我,有許多學校使用這本書當「系統程式」課程的教材,而學習這門課的學生卻不一定有豐富的程式設計經驗,所以,我想列出一些閱讀本書之前應該學習的知識,幫助莘莘學子做好課前準備。
首先,你要懂 C 語言,尤其是最難懂的指標(pointer)與結構(structure)。C
語言本身沒提供物件導向機制,但是 Linux 核心的研發團隊使用「結構」來模擬「類別」,使用「函式指標」(function pointer)與「註冊表」(函式指標陣列)來提供
subclassing 機制。因此,你會見到大量的結構與函式指標。關於 C 語言,請參閱 K & R 所著的那本聖經。
其次,你必須熟悉資料結構的操作,尤其是串列(list)。Linux 核心內部有許多稱為「佇列」(queue)或「表」(table)的資料結構,它們其實都是某種形式的串列。知道如何安插、刪除串列中的節點,可讓你在寫驅動程式時更加得心應手。關於
Linux 核心提供的通用串列支援,請參閱本書第十章的《10.5 鏈結串列》。
最後,也是最重要的,就是你必須了解 Unix 的「系統呼叫」(system call)機制。寫 Linux
驅動程式,基本上可說是在“實作”(implementing)應用程式可能用到的各種系統呼叫。例如,如果掃瞄機的應用程式會使用 open()、read()、close()
這三種系統呼叫來存取 /dev/scanner,那麼,/dev/scanner 的驅動程式就必須實作出 open、read
與 close 這三種作業方法。對於系統呼叫沒有概念的讀者,建議你閱讀《Understanding the Linux Kernel,2/e》的第九章。
本書的範例程式
本書的所有範例程式都可從 O'Reilly 的網站取得:
http://examples.oreilly.com/linuxdrive2/
(美國總站)
Linux 驅動程式 第二版
(台灣分站)
從美國總站取得的版本比較舊(ldd2-samples-1.0.1.tar.gz),這版本有部份檔案需要稍微修改,才可在
2.4.10 版之後的環境下順利編譯。我修改好的版本(ldd2-samples-1.0.2.tar.gz)放在台灣歐萊禮的網站上。讀者可用下列方式取得:
# wget http://www.oreilly.com.tw/bookcode/ldd2-samples-1.0.2.tar.gz
解開:
# tar xzvf
ldd2-samples-1.0.2.tar.gz
# ls -F ldd2
allocator/ Makefile.arm misc-modules/
sbull/ simple/
Changes Makefile.ia64 misc-progs/
scull/ skull/
foo Makefile.m68k oops/
scullc/ snull/
LICENSE Makefile.mips pci/
scullp/ spull/
local-scratch Makefile.ppc pci-compat.h
scullv/ sysdep.h
Makefile Makefile.sparc README
short/ usb/
Makefile.alpha Makefile.sparc64 Rules.make
shortprint/
作者提供的範例程式是依據 Linus 本人發佈的正式版核心而寫的(來自 http://www.kernel.org/
的版本),如果你使用 Red Hat 或 SuSE 隨附的版本,在編譯上可能會遇到一些困難。因此,我們建議你從 kernel.org 下載最新的
2.4.x 版核心原始程式:
[root@linux
~]# cd /usr/src/
[root@linux /usr/src]# wget http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.24.tar.bz2
[root@linux /usr/src]# tar xvjfp linux-2.4.24.tar.bz2
[root@linux /usr/src]# chown -R root.root linux-2.4.24/
[root@linux /usr/src]# ln -s linux-2.4.24/ linux
使用 RedHat 或 SuSE 的讀者,請一併修正 /usr/include/linux/ 與 /usr/include/asm/,讓它們分別指向正確版本的目錄:
[root@linux
/usr/src]# cd /usr/include/
[root@linux /usr/include]# mv linux linux.redhat
[root@linux /usr/include]# mv asm asm.redhat
[root@linux /usr/include]# ln -s /usr/src/linux/include/linux/ linux
[root@linux /usr/include]# ln -s /usr/src/linux/include/asm/ asm
編譯新版核心:
[root@linux
/usr/include]# cd /usr/src/linux
[root@linux /usr/src/linux]# make clean
[root@linux /usr/src/linux]# make menuconfig
...(略)...
[root@linux /usr/src/linux]# vi Makefile (非必要)
[root@linux /usr/src/linux]# make dep
[root@linux /usr/src/linux]# make bzImage ( x86
)
或
[root@linux
/usr/src/linux]# make vmlinux ( sparc64
或其它平台)
...(下午茶時間)...
[root@linux /usr/src/linux]#
make modules
[root@linux /usr/src/linux]# make modules_install
安裝新版核心:
[root@linux
/usr/src/linux]# cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.24
( x86 )
或
[root@linux
/usr/src/linux]# cp vmlinux /boot/vmlinux-2.4.24
[root@linux /usr/src/linux]# cp .config /boot/config-2.4.24
[root@linux /usr/src/linux]# cp System.map /boot/System.map.2.4.24
[root@linux /usr/src/linux]# vi /etc/lilo.conf
或 silo.conf、milo.conf、grub.conf,看你所用的 bootloader 而定。
參考設定內容:
# (lilo.conf、silo.conf、milo.conf):
image=/boot/vmlinuz-2.4.24 #
如果你的 /boot 是位於自己的分割區,
label=mylinux # 請改成 image=/vmlinuz-2.4.24
read-only
root=/dev/hda3
# grub.conf:
title gpLinux (2.4.24 custom kernel)
root (hd0,0)
kernel /vmlinuz-2.4.24 ro root=/dev/hda3
[root@linux /usr/src/linux]#
lilo ( x86 only
)
[root@linux /usr/src/linux]#
reboot ( 阿彌陀佛 ... )
重新開機後,用 dmesg 檢視開機訊息,看看是否所有必要裝備都啟動了。有興趣看本書的讀者,至少都應該是玩家級的高手,所以我就不再解釋上述步驟的意義。
如果能順利啟動新核心,就可以試著編譯看看範例程式了。
[root@sparc
~/ldd2]# cd misc-modules/
[root@sparc ~/ldd2/misc-modules]# make clean
[root@sparc ~/ldd2/misc-modules]# make
跑跑看:
[root@sparc
~/ldd2/misc-modules]# insmod ./hello.o
Warning: loading ./hello.o will taint the kernel: no license
[root@sparc ~/ldd2/misc-modules]# tail -n 1 /var/log/messages
Jan 19 20:59:49 sparc kernel: Hello, world
出現「no license」警告訊息是正常的,如果你不想看到這段訊息,請修改原始程式,在 #include
<linux/module.h> 之後加入下列敘述:
MODULE_LICENSE("GPL");
然後重新編譯一次,再試試看。
批評指教
雖然我自認在這本書的翻譯與校稿上投入了大量的心力,但是無論編譯過程如何嚴謹,我仍不敢保證本書沒有瑕疵。如果讀者認為本書譯文有任何模稜兩可或交代不清之處,或是有任何錯誤(漏字、錯字、贅字、技術描述
...),或是您有任何能使本書更好的建議,我非常歡迎讀者提供批評指教。
台灣歐萊禮公司特地設置 bookq@oreilly.com.tw
信箱,如果讀者對於本公司出版品內容有任何意見(包括技術問題),請寫信到此信箱,或是直接寫給我也可以。我很珍惜每一位讀者的指教。對於錯誤糾正,在經過查證之後,我會公佈在本書中文網頁的勘誤表,並於下一刷改正。如果您對本書的內容有疑問,在您回報錯誤之前,請先查閱網頁上的勘誤表,看看是不是已經有人發現了。
林長毅 謹識
lin@oreilly.com.tw
中華民國 93 年一月 台北 |