Linux 2.6核心的編譯步驟及模組動態載入

來源:互聯網
上載者:User

本文是基於2.6的核心,也建議各位可以先看一下《Linux核心設計與實現(第二版)》作為一個基礎知識的鋪墊。當然,從實踐角度來看,只要按著以下的步驟去做也應該可以實現成功編譯核心及載入模組。

個人用的Linux版本為:Debian GNU/Linux,核心版本為:2.6.20-1-686.

◆第一步,下載Linux核心的原始碼,即構建LDD3(Linux Device Drivers 3rd)上面所說的核心樹。

如過安裝的Linux系統中已經內建了原始碼的話,應該在/usr/src目錄下。如果該目錄為空白的話,則需要自己手動下載原始碼。下載代碼的方法和連結很多,也可以在CU上通過http://download.chinaunix.net/search/?key=&q=kernel&frmid=53去下載。不過,下載的核心版本最好和所啟動並執行Linux系統的核心版本一致。當然,也可以比Linux系統核心的版本低,但高的話應該不行(個人尚未實踐)。

Debian下可以很方便的通過Debian源下載:

首先尋找一下可下載的核心原始碼:

# apt-cache search linux-source

其中顯示的有:linux-source-2.6.20,沒有和我的核心版本完全符合,不過也沒關係,直接下載就可以了:

# apt-get install linux-source-2.6.20

下載完成後,安裝在/usr/src下,檔案名稱為:linux-source-2.6.20.tar.bz2,是一個壓縮包,解壓縮既可以得到整個核心的原始碼:

# tar jxvf linux-source-2.6.20.tar.bz2

解壓後產生一個新的目錄/usr/src/linux——source-2.6.20,所有的原始碼都在該目錄下。

註:該目錄會因核心版本的不同而不同,各位動手實踐的朋友只需知道自己的原始碼所在的具體位置即可。

◆第二步:配置及編譯核心。

進入/usr/src/linux——source-2.6.20目錄下,可以看到Makefile檔案,它包含了整個核心樹編譯資訊。該檔案最上面四行是關於核心版本的資訊。對於整個Makefile可以不用做修改,採用預設的就可以了。

一般情況下,需要先用命令諸如"make menuconfig", "make xconfig"或者"make oldcofig"對核心進行配置,這幾個都是對核心進行配置的命令,只是它們啟動並執行環境不一樣,執行一下這幾個命令中的任何一個即可對核心進行配置:

make menuconfig是基於介面的核心配置方法,make xconfig應該是基於QT庫的,還有make gcofig也是基於圖形的配置方法,應該是需要GTK的環境,make oldcofig就是對核心樹原有的.config檔案進行配置一下即可。

其實核心的配置部分,主要是保證核心啟動模組可動態載入的配置,預設配置裡面應該已經包含了這樣的內容,因此,我用的是make oldconfig.

在核心源碼的目錄下執行:

# make

# make bzImage

其中,第一個make也可以不執行,直接make bzImage。這個過程可能要持續一個小時左右,因此是對整個核心重新編譯了。執行結束後,可以看到在目前的目錄下產生了一個新的檔案: vmlinux, 其屬性為-rwxr-xr-x。

然後執行:

# make modules

# make modules_install

對核心的所有模組進行編譯和安裝。

執行結束之後,會在/lib/modules下產生新的目錄/lib/modules/2.6.20/。 在隨後的編譯模組檔案時,要用到這個路徑下的build目錄。至此,核心編譯完成。可以重啟一下系統。

◆第三步:編寫模組檔案及Makefile

以LDD3上的hello.c為例:

//hello.c#include <linux/init.h>#include <linux/module.h>MODULE_LICENSE("Dual BSD/GPL");static int hello_init(void){    printk(KERN_ALERT "Hello, world/n");    return 0;}static void hello_exit(void){    printk(KERN_ALERT"Goodbye, cruel world/n");}module_init(hello_init);module_exit(hello_exit);

Makefile檔案的內容為:

obj-m := hello.oKERNELDIR := /lib/modules/2.6.20/buildPWD := $(shell pwd)modules:    $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

其中,hello.c和Makefile檔案應該位於同一個目錄下,可以放在/home下,我的兩個檔案都位於/home/david/.

第四步:編譯和裝載模組

在檔案所處的目錄下,執行:

debian:/home/david # make

然後查看該目錄下有哪些檔案產生:

debian:/home/david # ls -l總計 28drwxr-xr-x 2 david david 4096 2007-02-07 17:49 Desktop-rw-r--r-- 1 david david  462 2007-07-20 13:42 hello.c-rw-r--r-- 1 root  root  2432 2007-07-20 13:55 hello.ko-rw-r--r-- 1 root  root   607 2007-07-20 13:55 hello.mod.c-rw-r--r-- 1 root  root  1968 2007-07-20 13:55 hello.mod.o-rw-r--r-- 1 root  root  1140 2007-07-20 13:55 hello.o-rw-r--r-- 1 david david  267 2007-07-20 13:48 Makefile-rw-r--r-- 1 root  root     0 2007-07-05 14:11 Module.symvers

可見,已經產生模組檔案hello.ko.

然後,就可以載入該模組:

debian:/home/david # insmod hello.ko

查看模組是否載入進核心:

debian:/home/david # lsmod

Module Size Used by

hello 1344 0

nfs 219468 0

nfsd 202224 17

…… ……

其中Module名為hello的即為我們所載入的模組.

卸載模組:

debian:/home/david # rmmod hello

同樣可以通過lsmod來查看該模組是否被卸載.

這裡有兩個問題,其一就是printk()輸出的問題.LDD3上也說,在載入和卸載模組的時候都會有資訊輸出在螢幕上,如果在Windows下通過終端模擬器(我們常用的虛擬機器算是一種),則在螢幕上看不到任何輸出.我同時在虛擬機器和和物理機都運行了該模組,均未看到有"Hello, world"(載入模組時printk的輸出)或"Goodby, cruel world"(卸載模組時printk的輸出). 這個不知道是我作業系統發行版的原因還是系統配置的問題,請瞭解這個問題的朋友指點一下.

其二,書上講到如果螢幕上看不到資訊,可能輸出在某個記錄檔裡面了,並說可能在/var/log/messages檔案中.並且看到網上很多網友也說是輸出到這個檔案裡面.我不知道有沒有發現輸出在其他記錄檔裡的,不過我的這個資訊輸出在/var/log/syslog裡面.在載入和卸載完該模組後, 執行命令:

debian:/home/david # cat /var/log/syslog | grep world

可以看到有兩行內容.當然,也可以不用grep world, 應該會出現在最後兩行.

Jul 20 14:15:29 localhost kernel: Hello, world

Jul 20 14:15:34 localhost kernel: Goodbye, cruel world

這就是printk應該輸出的資訊.

這裡有另外一個方法,可以實現printk的資訊輸出在螢幕上,即更改printk輸出的優先順序.例子中的優先順序為:KERN_ALERT,優先順序為<1>,如果將優先順序改為KERN_EMERG即<0>,則可以看到螢幕的輸出資訊.

修改的方法只是修改一下hello.c中兩句printk()的內容,修改後的hello.c如下:

#include <linux/init.h>#include <linux/module.h>MODULE_LICENSE("Dual BSD/GPL");static int hello_init(void){    printk(KERN_EMERG "Hello, world/n");  /*改動部分*/    return 0;}static void hello_exit(void){    printk(KERN_EMERG"Goodbye, cruel world/n"); /*改動部分*/}module_init(hello_init);module_exit(hello_exit);

同樣的方法編譯產生模組,再次用insmod和rmmod,則在螢幕上看到的輸出資訊為:

debian:/home/david# insmod hello.kodebian:/home/david#Message from syslogd@localhost at Fri Jul 20 14:27:32 2007 ...localhost kernel: Hello, worlddebian:/home/david# rmmod hellodebian:/home/david#Message from syslogd@localhost at Fri Jul 20 14:27:42 2007 ...localhost kernel: Goodbye, cruel worlddebian:/home/david

但是,是否能夠將printk()的優先順序改為KERN_EMERG值得商榷.因為在Linux Kernel Development中,對該優先順序的描述為: An emergency condition; the system is probably dead.

以上就是整個2.6核心編譯步驟以及模組動態載入的方法.理解和解釋有誤的地方,也請各位瀏覽本文的朋友指點,也希望能和對核心和驅動感興趣的朋友交流。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.