Linux 內核源碼外編譯 linux模塊--編譯驅動模塊的基本方法


1、先編寫一個簡單的hello模塊,hello.c 源碼如下:

#ifndef __KERNEL__
#  define __KERNEL__
#endif
#ifndef MODULE
#  define MODULE
#endif

// 下面的是主要的內容
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");

static int year=2012;

int hello_init()
{
    printk(KERN_WARNING "Hello kernel, it's %d!\n",year);
    return 0;
}


void hello_exit()
{
    printk("Bye, kernel!\n");
}

// 下面兩個為關鍵的模塊函數
module_init(hello_init);
module_exit(hello_exit);

如果上面的代碼看起來不太熟悉,那么需要查看以下相關的書籍,比如《Linux設備驅動程序,第三版》,也就是大名鼎鼎的LDD;

2、老式驅動模塊編譯方法:

直接寫出make規則到makefile文件中,引用內核體系的頭文件路徑,舉例如下:

# The path of kernel source code
INCLUDEDIR = /media/GoldenResources/linux/linux-2.6.30/include

# Compiler
CC = gcc

# Options
CFLAGS = -D__KERNEL__ -DMODULE -O -Wall -I$(INCLUDEDIR)

# Target
OBJS = hello.o

all: $(OBJS)

$(OBJS): hello.c
    $(CC) $(CFLAGS) -c $<

install:
    insmod $(OBJS)

uninstall:
    rmmod hello

.PHONY: clean
clean:
    rm -f *.o

這里有我是用的一個linux內核源代碼路徑:/media/GoldenResources/linux/linux-2.6.30/include ,注意設置到正確的源碼路徑。

嘗試這編譯:$make

gcc -D__KERNEL__ -DMODULE -O -Wall -I/media/GoldenResources/linux/linux-2.6.30/include -c hello.c In file included from /media/GoldenResources/linux/linux-2.6.30/include/linux/kernel.h:11:0, from hello.c:8: /media/GoldenResources/linux/linux-2.6.30/include/linux/linkage.h:5:25: fatal error: asm/linkage.h: No such file or directory compilation tterminate
make:
*** [hello.o] Error 1

出現錯誤: include/linux/linkage.h:5:25: fatal error: asm/linkage.h: No such file or directory , 網上查閱相關資料后,找到不錯的說明:

請查看:http://stackoverflow.com/questions/9492559/module-compiling-asm-linkage-h-file-not-found 

主要意思是這種編譯方法不能很好的解決相關的依賴體系,主要是源於歷史原因,linux內核升級很快,越來越復雜,所以建議使用kbuild體系來自動完成;故下面采用了可行的kbuild體系來完成。

3、使用kbuild進行模塊編譯:

基本方法可以參考: http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt

核心思想是,通過-C指明系統上的內核體系路徑,通過M=指明模塊源文件路徑,然后自己構造一個makefile文件,從而實現編譯過程。

3.1 構建適用於kbuild方法的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

開始make:

$make
make -C /lib/modules/3.5.0-17-generic/build M=/media/GoldenResources/arm/ARM/HelloWorld/hello modules
make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic'
scripts/Makefile.build:44: /media/GoldenResources/arm/ARM/HelloWorld/hello/Makefile: No such file or directory
make[2]: *** No rule to make target `/media/GoldenResources/arm/ARM/HelloWorld/hello/Makefile'.  Stop.
make[1]: *** [_module_/media/GoldenResources/arm/ARM/HelloWorld/hello] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic'
make: *** [all] Error 2

自動使用了當前運行中的內核,構建對應的模塊,但是提示找不到Makefile,而該目錄下的文件為makefile,所以嘗試修改名字:

$mv makefile  Makefile

特別注意,要使用Makefile才行!不能時makefile;

修改后,編譯成功:

$make
make -C /lib/modules/3.5.0-17-generic/build M=/media/GoldenResources/arm/ARM/HelloWorld/hello modules
make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic'
  Building modules, stage 2.
  MODPOST 1 modules  # 說明成功編譯了一個模塊
make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic'

3.2 加載和刪除內核模塊:

$sudo insmod ./hello.ko #加載
$sudo rmmod hello       #刪除

並沒有看到源代碼中的輸出信息,查看系統相應日志即可:

$tail /var/log/kern.log   # 注意ubuntu下的日志路徑
Oct 23 22:22:22 qunengrong-Studio-1450 kernel: [43021.773888] Hello kernel, it's 2012!
Oct 23 22:22:37 qunengrong-Studio-1450 kernel: [43037.092339] Bye, kernel!

至此,我們已經可以成功編譯和加載內核模塊了;

 

4、額外成就,要注意模塊與內核版本的匹配:

假設我直接使用另一個內核體系進行構建,比如3.5.0-15-generic,但是當前系統運行的為3.5.0-17-generic的內核,則加載時報錯,如下:

$make -C /lib/modules/3.5.0-15-generic/build M=`pwd` modules
make: Entering directory `/usr/src/linux-headers-3.5.0-15-generic'
  CC [M]  /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.o
/media/GoldenResources/arm/ARM/HelloWorld/hello/hello.c:16:5: warning: function declaration isn’t a prototype
/media/GoldenResources/arm/ARM/HelloWorld/hello/hello.c:23:6: warning: function declaration isn’t a prototype
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.mod.o
  LD [M]  /media/GoldenResources/arm/AR/HelloWorld/heARo/hello.ko
make: Leaving directory `/usr/src/linux-headers-3.5.0-15-generic'

$sudo insmod ./hello.ko  # 版本不一致報錯
insmod: error inserting './hello.ko': -1 Invalid module format

由此可見,使用自動構建帶來的方便,將該通用Makefile分享如下:

obj-m := name.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

轉:http://www.cnblogs.com/QuLory/ 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM