1,下載源碼
xin@xin-desktop:~$ sudo apt-get source linux-image-2.6.32-38-generic
最終安裝在目錄:/usr/src/linux-2.6.32/
2,編寫源碼hello_module.c和Makefile
(1)建立一個目錄mytest
xin@xin-desktop:~/mytest$ vi hello_module.c
#include <linux/init.h> /* printk() */ #include <linux/module.h> /* __init __exit */ static int __init hello_init(void) /*模組載入函數,通過insmod命令載入模組時,被自動執行*/ { printk(KERN_INFO " Hello World enter\n"); return 0; } static void __exit hello_exit(void) /*模組卸載函數,當通過rmmod命令卸載時,會被自動執行*/ { printk(KERN_INFO " Hello World exit\n "); } module_init(hello_init); module_exit(hello_exit); MODULE_AUTHOR("xin"); /*模組作者,可選*/ MODULE_LICENSE("Dual BSD/GPL"); /*模組許可證明,描述核心模組的許可許可權,必須*/ MODULE_DESCRIPTION("A simple Hello World Module"); /*模組說明,可選*/
(2)寫一個Makefile檔案:
內容如下:
#目標檔案obj-m :=hello_module.o#當模組有多個檔案組成時,添加本句#module-objs := file1.o file.o #核心路徑,根據實際情況換成自己的核心路徑,嵌入式的換成嵌入式,PC機的指定PC機路>徑 KDIR :=/usr/src/linux-2.6.32/#模組源檔案路徑 PWD := $(shell pwd)all: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules @rm -rf *.mod.* @rm -rf .*.cmd @rm -rf *.o @rm -rf Module.* clean: rm -rf *.ko
3,編譯
xin@xin-desktop:~/mytest$ make
make: Entering directory `/usr/src/linux-2.6.32'
ERROR: Kernel configuration is invalid.
include/linux/autoconf.h or include/config/auto.conf are missing.
Run 'make oldconfig && make prepare' on kernel src to fix it.
WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
is missing; modules will have no dependencies and modversions.
........................................
........................................
解決方案:
xin@xin-desktop:/usr/src/linux-2.6.32$ sudo make oldconfig
xin@xin-desktop:/usr/src/linux-2.6.32$ sudo make prepare
再次編譯:
xin@xin-desktop:~/mytest$ make
還是有錯:
make: Entering directory `/usr/src/linux-2.6.32'
WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
is missing; modules will have no dependencies and modversions.
CC [M] /home/xin/mytest/hello_module.o
Building modules, stage 2.
MODPOST 1 modules
/bin/sh: scripts/mod/modpost: not found
make[1]: *** [__modpost] 錯誤 127
make: *** [modules] 錯誤 2
make: Leaving directory `/usr/src/linux-2.6.32'
看到提示說沒有scripts/mod/modpost,那我們就編譯它
xin@xin-desktop:/usr/src/linux-2.6.32$ make scripts
HOSTCC scripts/genksyms/genksyms.o
SHIPPED scripts/genksyms/lex.c
SHIPPED scripts/genksyms/parse.h
SHIPPED scripts/genksyms/keywords.c
HOSTCC scripts/genksyms/lex.o
SHIPPED scripts/genksyms/parse.c
HOSTCC scripts/genksyms/parse.o
HOSTLD scripts/genksyms/genksyms
CC scripts/mod/empty.o
HOSTCC scripts/mod/mk_elfconfig
MKELF scripts/mod/elfconfig.h
HOSTCC scripts/mod/file2alias.o
HOSTCC scripts/mod/modpost.o
HOSTCC scripts/mod/sumversion.o
HOSTLD scripts/mod/modpost
HOSTCC scripts/kallsyms
HOSTCC scripts/conmakehash
OK,好了
再來解決這一個warning(前面沒有關注,後面發現這個還是致命的):
WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
is missing; modules will have no dependencies and modversions.
原因:通常頭核心包中是沒有Module.symvers這個檔案的,要想擷取這個檔案只能到下載相同版本核心的標頭檔,是下載不是
apt-get install !!!,只有下載的標頭檔中才有這個Module.symvers。把Module.symvers 複製到核心包中。
然後重新編譯驅動:xin@xin-desktop:~/mytest$ make
將解決這個warning,同時也解決了版本不正確的問題。
(我不知道有多少人會碰上這樣的問題,反正google中我發現沒有人能說明白這個問題)
4,載入模組
xin@xin-desktop:~/mytest$ ls
hello_module.c modules.order hello_module.ko Makefile
xin@xin-desktop:~/mytest$ sudo insmod hello_module.ko
xin@xin-desktop:~/mytest$ lsmod | grep hello_module
hello_module 593 0
ps:
不解決上面的warning,是可以編譯成功的。但是在執行載入後
xin@xin-desktop:~/mytest$ sudo insmod hello_module.ko
報錯:insmod: error inserting 'hellomod.ko': -1 Invalid module format
查了很多資料,普遍的觀點是:
核心無法載入模組的原因是因為記載版本號碼的字串(正規說法:版本印戳)和當前正在啟動並執行核心模組的不一樣,叫vermagic
此時,可用sudo tail /var/log/messages
你在最後一行應該看到類似下面的提示:
Dec 19 13:42:29 localhost kernel: hellomod: version magic '2.6.24.2 SMP mod_unload 686 4KSTACKS ' should be '2.6.27.7-134.fc10.i686 SMP mod_unload 686 4KSTACKS '
而我的只顯示:
Mar 29 16:57:34 xin-desktop kernel: [ 6964.464931] hello_module: no symbol version for module_layout
但是通過modinfo和 uname -r的比較確實不一樣
我按照提供的辦法,修改來源目錄下的Makefie
把Makefile第1-4行的值改為當前核心一樣的值
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 32
EXTRAVERSION = .54+drm33.21
NAME = Man-Eating Seals of Antiquity
確定你當前核心的值,通過
vi /lib/modules/`uname -r`/build/Makefile
但是,我這樣改過之後,還是又上面載入不上的問題,而且版本號碼跟寫進Makefile的不是一樣的,編譯完成的是這樣的:
2.6.32.57+drm33.23 SMP mod_unload modversions 586。
即便我把/usr/src/linux-2.6.32核心源碼中的Makefile改了,也是這樣的,我一直沒有搞清楚,到底核心版本號碼是在哪裡設定的。
最後,消除了這個warning後,雖然核心版本號碼仍不一樣,但是可以載入了。
當前已經載入的核心模組video的資訊:
xin@xin-desktop:~/mytest$ modinfo video
filename: /lib/modules/2.6.32-38-generic/kernel/drivers/acpi/video.ko
license: GPL
description: ACPI Video Driver
author: Bruno Ducrot
srcversion: A52E70043443277D9757C8E
alias: acpi*:LNXVIDEO:*
depends: output
vermagic: 2.6.32-38-generic SMP mod_unload modversions 586
parm: brightness_switch_enabled:bool
hello_module的資訊:
xin@xin-desktop:~/mytest$ modinfo hello_module.ko
filename: hello_module.ko
alias: a simplest module
description: A simple Hello World Module
license: Dual BSD/GPL
author: xin
srcversion: B757E1EEAD29F16BF0B6737
depends:
vermagic: 2.6.32.57+drm33.23 SMP mod_unload modversions 586
注意到 兩者的vermagic是不一樣的,但是可以載入hello_module.ko模組