要实现hello world也需要做下基本的工作,首先就是内核树的建立.在内核树建立的基础上来进行.
首先建立hello.c和Makefile文件,他们最好在一个文件夹里面.
//hello.c
#include
#include
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.o
KERNELDIR := /lib/modules/2.6.28/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
Makefile文件需要将
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 和$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install退到最左端然后用"TAB"来空格.
# gedit hello.c
# make
make -C /lib/modules/2.6.28/build M=/workdir/LDD3/driver/hello modules
make[1]: Entering directory `/workdir/LDD3/kernel/linux-2.6.28'
CC [M] /workdir/LDD3/driver/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /workdir/LDD3/driver/hello/hello.mod.o
LD [M] /workdir/LDD3/driver/hello/hello.ko
make[1]: Leaving directory `/workdir/LDD3/kernel/linux-2.6.28'
# ls
Makefile Makefile~ Module.symvers hello.c hello.c~ hello.ko hello.mod.c hello.mod.o hello.o modules.order
# insmod hello.ko
insmod: error inserting 'hello.ko': -1 Invalid module format
出现上面的情况口,查看日志文件
# cat /var/log/messages
Apr 2 21:22:18 emboard-desktop syslogd 1.5.0#1ubuntu1: restart.
Apr 2 21:43:56 emboard-desktop -- MARK --
Apr 2 22:03:57 emboard-desktop -- MARK --
Apr 2 22:23:57 emboard-desktop -- MARK --
Apr 2 22:38:20 emboard-desktop kernel: [ 6910.938421] Clocksource tsc unstable (delta = 4693232077 ns)
Apr 2 22:38:22 emboard-desktop kernel: [ 6911.090586] Time: acpi_pm clocksource has been installed.
Apr 2 23:04:04 emboard-desktop -- MARK --
Apr 2 23:24:06 emboard-desktop -- MARK --
Apr 2 23:44:06 emboard-desktop -- MARK --
Apr 2 23:58:22 emboard-desktop kernel: [11713.696567] hello: disagrees about version of symbol struct_module
Apr 2 23:58:50 emboard-desktop kernel: [11741.863228] hello: disagrees about version of symbol struct_module
可能是内核版本的问题.
解决办法一:
修改Makefile
obj-m := hello.o
#KERNELDIR := /lib/modules/2.6.28/build
KERNELDIR := /lib/modules/2.6.24-19-generic/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
将"build"路径换成系统的,当然这个办法不能解决我们所要达到的目的,但是可以试下!
# make
make -C /lib/modules/2.6.24-19-generic/build M=/workdir/LDD3/driver/hello modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.24-19-generic'
CC [M] /workdir/LDD3/driver/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /workdir/LDD3/driver/hello/hello.mod.o
LD [M] /workdir/LDD3/driver/hello/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.24-19-generic'
# insmod hello.ko
#
# insmod hello.ko
insmod: error inserting 'hello.ko': -1 File exists
可见已经成功了,但是没出现"hello word"
# rmmod hello.ko
#
# rmmod hello.ko
ERROR: Module hello does not exist in /proc/modules
# cat /var/log/messages
Apr 2 21:22:18 emboard-desktop syslogd 1.5.0#1ubuntu1: restart.
Apr 2 21:43:56 emboard-desktop -- MARK --
Apr 2 22:03:57 emboard-desktop -- MARK --
Apr 2 22:23:57 emboard-desktop -- MARK --
Apr 2 22:38:20 emboard-desktop kernel: [ 6910.938421] Clocksource tsc unstable (delta = 4693232077 ns)
Apr 2 22:38:22 emboard-desktop kernel: [ 6911.090586] Time: acpi_pm clocksource has been installed.
Apr 2 23:04:04 emboard-desktop -- MARK --
Apr 2 23:24:06 emboard-desktop -- MARK --
Apr 2 23:44:06 emboard-desktop -- MARK --
Apr 2 23:58:22 emboard-desktop kernel: [11713.696567] hello: disagrees about version of symbol struct_module
Apr 2 23:58:50 emboard-desktop kernel: [11741.863228] hello: disagrees about version of symbol struct_module
Apr 3 00:24:07 emboard-desktop -- MARK --
从上面也没看到!可见这个办法是可以实现模块动态加载,但是达不到我们想要的效果.
但是可以在这里看到.
# cat /var/log/syslog
Apr 3 14:55:25 emboard-desktop kernel: [ 3982.870441] Hello, world
Apr 3 14:55:31 emboard-desktop kernel: [ 3989.359755] Goodbye, cruel world
方法二:可以试着去掉内核的模块版本的支持.
进入内核目录:
# make menuconfig
进入上图选中的那个选项,进入:
去掉上图选中的那个选项.
然后编译内核:
# make
# make bzImage
# make modules
# make modules_install
编译成功后,然后进入hello文件夹:
# ls
Makefile Module.symvers hello.c hello.ko hello.mod.c hello.mod.o hello.o modules.order
可以看到上次编译过的文件,现在你可以手动删除:
# rm Module.symvers
# rm hello.ko
# rm hello.mod.c
# rm hello.mod.o
# rm hello.o
# rm modules.order
# ls
Makefile hello.c
然后查看Makefile文件内核树的路径是否是上面编译的路径:
# gedit Makefile
obj-m := hello.o
KERNELDIR := /lib/modules/2.6.28/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
确认后,然后执行make:
# make
make -C /lib/modules/2.6.28/build M=/workdir/LDD3/driver/hello modules
make[1]: Entering directory `/workdir/LDD3/kernel/linux-2.6.28'
CC [M] /workdir/LDD3/driver/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /workdir/LDD3/driver/hello/hello.mod.o
LD [M] /workdir/LDD3/driver/hello/hello.ko
make[1]: Leaving directory `/workdir/LDD3/kernel/linux-2.6.28'
# ls
Makefile Module.symvers hello.c hello.ko hello.mod.c hello.mod.o hello.o modules.order
# insmod hello.ko
# rmmod hello.ko
但是执行后仍然看不到打印信息,但是可以通过下面的方式来判断,hello.ko已经加载了
# insmod hello.ko
# insmod hello.ko
insmod: error inserting 'hello.ko': -1 File exists
# lsmod
Module Size Used by
hello 2304 0
ipv6 267780 8
af_packet 23812 2
可见hello已经加载了.
不能打印出信息,有待调试.
# cat /var/log/messages
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572359] WARNING: at /build/buildd/linux-2.6.24/mm/vmalloc.c:331 __vunmap()
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572368] Pid: 8888, comm: insmod Tainted: GF 2.6.24-19-generic #1
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572391] [sys_init_module+0x151/0x19c0] sys_init_module+0x151/0x19c0
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572440] [_atomic_dec_and_lock+0x47/0x70] _atomic_dec_and_lock+0x47/0x70
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572454] [] printk+0x0/0x20
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572528] [sysenter_past_esp+0x6b/0xa9] sysenter_past_esp+0x6b/0xa9
Apr 3 14:32:41 emboard-desktop kernel: [ 2620.572553] =======================
这个是最后几行,可能问题就出在这里,现在不能确定是什么原因!
最后在google上找到原因:
#dmesg or #cat /var/log/syslog
[358018.485127] Trying to vfree() bad address (f8c150b0)
[358018.485153] WARNING: at /build/buildd/linux-2.6.24/mm/vmalloc.c:331 __vunmap()
[358018.485157] Pid: 14125, comm: insmod Tainted: GF 2.6.24-19-386 #1
[358018.485172] [] sys_init_module +0x155/0x15a0
[358018.485288] [] sysenter_past_esp+0x6b/0xa9
[358018.485330] =======================
1. insmod Tainted: GF 没碰见过,查了一下有篇很好的文章说kernel tainted的。
其中提到了G和F的意思,和/proc/sys/kernel/tainted
G : The opposite of ' P ': the kernel has been tainted (for a reason indicated by a different flag), but all modules loaded into it were licensed under the G PL or a license compatible with the GPL.
F : A module was loaded using the F orce option "-f " of insmod or modprobe , which caused a sanity check of the versioning information from the module (if present) to be skipped.
/proc/sys/kernel/tainted flag:
If the kernel supports the /proc/sys/kernel/tainted flag then insmod will OR the tainted flag with '1' when loading a module without a GPL license. A warning is issued if the kernel supports tainting and a module is loaded without a license. A warning is always issued for modules which have a MODULE_LICENSE() that is not GPL compatible, even on older kernels that do not support tainting. This minimizes warnings when a new modutils is used on older kernels.
insmod -f (force) mode will OR the tainted flag with '2' on kernels that support tainting. It always issues a warning.
2. Trying to vfree() bad address错误:
该错误出于mm/vmalloc.c的vfree()函数。见
可能是在模块初始化失败后,释放分配的内存,发现是错误的地址造成。
3. sys_init_module
4. NUMA:
Non-Uniform Memory Access or Non-Uniform Memory Architecture (NUMA)
#cat /proc/vmallocinfo
Final Result:
module编译用的kernel与host的kernel相差太大,所以失败了,以后再追原因。在内核一致的host上,没有问题。
所以现在还是换成2.6.24的内核吧!浪费怎么多时间,吸取一个教训吧!不过,我觉得走的弯路多了,以后碰到问题也就少了,至少证明有的方法是行不通的了.
好了换成2.6.24的内核试试吧!方法还是一样!只是将内核编译后修改下Makefile的路径就可以了!
所以又重新下载了linux-2.6.24这个版本的内核,因为我的操作系统的内核也是2.6.24.xx.xx的!
按照建立内核树的方法,建立了内核树!
最后修改了Makefile文件如下:
# Makefile2.6
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationship of files and target modules are listed here.
obj-m +=hello.o
else
PWD :=$(shell pwd)
KEVER ?=$(shell uname -r)
KDIR :=/workdir/emboard-workdir/LDD3/kernel/linux-2.6.24
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.order *symvers *~
endif
也同样注意,需要用TAB来对齐的命令.
然后
# ls
Makefile hello.c
# make
make -C /workdir/emboard-workdir/LDD3/kernel/linux-2.6.24 M=/workdir/emboard-workdir/LDD3/driver/hello modules
make[1]: Entering directory `/workdir/emboard-workdir/LDD3/kernel/linux-2.6.24'
CC [M] /workdir/emboard-workdir/LDD3/driver/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /workdir/emboard-workdir/LDD3/driver/hello/hello.mod.o
LD [M] /workdir/emboard-workdir/LDD3/driver/hello/hello.ko
make[1]: Leaving directory `/workdir/emboard-workdir/LDD3/kernel/linux-2.6.24'
# ls
Makefile Module.symvers hello.c hello.ko hello.mod.c hello.mod.o hello.o
# insmod hello.ko
#
但是没有出先信息啊!
# cat /var/log/syslog
最后看到hello,world!说明成功了.
Apr 4 21:39:14 emboard kernel: [ 1742.786969] Hello, world
# rmmod hello.ko
同样最后也出现这样的提示信息.
Apr 4 21:39:12 emboard kernel: [ 1740.039785] Goodbye, cruel world
这样说明成功模块动态加载成功!
***************************************2*******************************************