本文转自:
https://blog.csdn.net/u010560290/article/details/44647683
在学习内核模块编程的时候遇到了一些由于Makefile书写不正确导致的问题。一个.c源文件的Makefile按照网上的大部分资料介绍那样是没有问题的,多个源文件的内核模块编程时,就出现问题了,自己纠结了半天,最后查资料、请教大神才搞定的。把过程和解决方法贴出来,供大家参考,一起学习。
网上有很多文章讲解内核模块编程的例子,例如下面这个简单的例子:
#hello.c
#ifndef __KERNEL__
#define __KERNEL__
#endif //__KERNEL__
#ifndef MODULE
#define MODULE
#endif //MODULE
#include
#include
#include
static __init int hello_init(void)
{
printk(KERN_INFO"hello linux kernel module ...
");
return 0;
}
static __exit void hello_exit(void)
{
printk(KERN_INFO"goodbye linux kernel module ...
");
return 0;
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
其Makefile文件编写如下:
ifneq ($(KERNELRELEASE),)
obj-m += hello.o
else
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
endif
这是一个.c源文件的情况,还是很方便的。这中书写方式中,obj-m += hello.o这里的hello.o一定要是hello.c源文件的文件名(例如:你的源文件是abc.c,那么你的Makefile中就应该写:obj-m += abc.o),否则当你make的时候会报如下错误:
*** No rule to make target`/home/share/filter/test/mod.c', needed by`/home/share/filter/test/mod.o'. Stop.
这里的mod.o就是我随意命名的模块名,导致报错,因为当前目录下没有mod.c。
可不可以给自己的模块命名呢?当然
同样已hello.c为例,编写随意命名模块名的Makefile,简单的指定模块建立所依赖的目标文件,其Makefile如下:
ifneq ($(KERNELRELEASE),)
obj-m += ABC.o
ABC -objs:=hello.o
else
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
endif
这里增加了一行代码ABC -objs:=hello.o,用以指定建立ABC.o所依赖的目标文件hello.o,这样我们就可以随便给自己的模块命名了。
我推荐第二中Makefile的书写方式,不只是因为这样可以随意命名模块名称,还与多个源文件编译一个内核模块的问题有关。
第一种Makefile的书写方式仅能编译一个源代码文件,因为make时,默认去依赖与obj-m值相同的名称的源代码文件进行编译。但是如果当你的模块要处理的问题相对复杂的时候你可能想把你的源代码放在多个源文件中,并建立.h文件来管理。比如有如下源文件:hello.c hello1.c hello1.h;
如果按照第一种Makefile的书写方式,可能会写成这样:obj-m += hello.o hello1.o。这样书写的Makefile在make阶段是不会报错的,但是当你要insmod ./hello.ko的时候就会如下错误:
insmod: ERROR: could not insert module./hello.ko: Unknown symbol in module
解决的方法便是如第二种Makefile书写方式一样,将模块依赖目标文件用objs一一列举出来,完整的多个源代码文件的Makefile文件编写如下:
ifneq ($(KERNELRELEASE),)
obj-m += ABC.o
ABC -objs:=hello.o hello1.h
else
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
endif