編譯核心模組

來源:互聯網
上載者:User

編譯核心模組的方法與編譯一般應用程式的方法略有不同. 我們會發現在核心源碼樹的層層目錄中, 都存在有Makefile.
即這些Makefile是分層次組織的. 以往的核心版本中, 編譯模組比較麻煩, 需要我們對這些Makefile做出許多更改.
2.6的核心採用了"kbuild"編譯系統, 簡化了這些問題. 關於kbuild, 可參考核心源碼樹中的 /Documentation/kbuild/modules.txt.

編譯之前, 肯定是需要源檔案的. 這些源檔案可以放在核心源碼樹中, 也可以放在核心源碼樹之外的任何地方. 根據源檔案存在的目錄, 存在兩種編譯方法: 在源碼樹之中和在源碼樹之外.

在源碼樹中編譯模組

官方核心模組的原始碼都是按模組(驅動)類型組織的, 我們到核心源碼樹的drivers目錄可以看到char, usb, block之類的子目錄. 那麼我們在核心源碼樹中添加檔案時, 最好也遵循這些分類. 分類的規則自己靈活把握.

下面以前面的"hello, world"這個簡單的模組為例, 來看看如何在核心源碼樹中編譯模組.

1, 不建立子目錄
(1) 先在核心源碼樹中的drivers目錄編輯一個c來源程式, 名為hello.c.
(2) 修改drivers目錄的Makefile檔案, 添加: obj-m += hello.o
(3) 重新編譯核心(回到源碼樹根目錄, 運行 $ sudo make).

這樣, 在drivers目錄多出了這樣幾個檔案: hello.mod.c, hello.mod.o, hello.o, hello.ko. hello.ko就是編譯出來的模組了.

2, 建立子目錄
如果源檔案比較多, 可以在drivers目錄中建立子目錄. 還是以hello, world為例:
(1) 在核心源碼樹的drivers目錄中建立一個hello子目錄, 並將hello.c放在hello目錄中.
(2) 修改drivers目錄的Makefile檔案, 添加: obj-m += hello/
(3) 在hello目錄中建立一個Makefile檔案, 內容為: obj-m += hello.o
(4) 重新編譯核心(回到源碼樹根目錄, 運行 $ sudo make).

這樣, 新產生的模組檔案就位於hello目錄中.

若在核心源碼樹中編譯模組, 如果不建立子目錄, 那麼只需修改目前的目錄的Makefile, 否則應該在當前建立的子目錄中建立Makefile指定編譯選項, 並修改上層目錄的Makefile以讓kbuild能夠進入建立的子目錄.


在源碼樹之外編譯模組

還是以上面的hello, world為例. 在目前的目錄有個hello.c:

(1)首先在模組代碼所在的目錄建立一個Makefile, 內容為:
obj-m := hello.o
(2)這樣調用make命令:
$ sudo make -C /usr/local/src/kernel/linux-2.6.16.20 SUBDIRS=$PWD modules
這裡/usr/local/src/kernel/linux-2.6.16.20是核心源碼樹所在的目錄.

-C表示要求make先切換到-C指定的目錄. SUBDIRS(也可以用M代替SUBDIRS)使make在編譯模組之前回到目前的目錄.

整個編譯過程實際上是執行-C指定的核心源碼樹的Makefile, 並通過SUBDIR指定你要編譯的核心源檔案的目錄.

簡化命令列輸入
每次調用make的時候輸入這些參數比較比較麻煩, 可以這樣來改寫Makefile以簡化:

obj-m += hello.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

這樣, 只需在目前的目錄調用 $ sudo make 就可以完成上面的工作. 調用 $ sudo make clean 將刪除所有新產生的檔案.

上面的Makefile是這樣確定核心源碼樹所在的目錄的: 我們先到/lib/modules目錄, 會看到一些以核心版本為名的目錄,
目錄中有一個build檔案, 它是一個符號串連, 指向核心源碼樹. 那麼如何確定進入哪個核心版本的目錄呢? 這就可以通過 $ uname -r 來確定, 它指出了當前運行核心的版本.

還可以進一步簡化這個Makefile:
obj-m := hello.o

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

這樣不用在Makefile中一次又一次地指定核心代碼樹的目錄.

上面的例子中只討論了所有的代碼在一個檔案中的情況. 若代碼分布在多個源檔案中,  比如file1.c, file2.c, 產生hello.ko. 應該這樣寫Makefile:
obj-m :=  hello.o
hello-objs := file1.o file2.o
注意, 雖然我們的目的是產生.ko檔案, 但在Makefile中寫為.o!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.