我将内核模块组织为不同的子组件,因此我可以轻松插入/删除现有的子模块来尝试或集成内容。
目录布局如下所示:
foo --+-- Makefile
|
+-- main.c
|
+-- include --+-- foo1.h
| |
| +-- ... (other headers)
|
|
+-- src ------+-- foo1.c
|
+-- ... (other sources)
这是我的Makefile,
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2]
SRCS := main.c $(wildcard src/*.c)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
当我尝试在上面的Makefile中用[1-2]替换方法[1-1]时,我收到如下警告。
WARNING: "InitFoo1" [.../foo/foo.ko] undefined!
WARNING: "CleanuptFoo1" [.../foo/foo.ko] undefined!
在控制台输出中,我看不到src/foo1.c
已编译,就像我在Makefile中使用方法[1-1]一样。
# [2] echo to check if foo-objs values changes
echo main.o main.o src/foo1.o
main.o main.o src/foo1.o
KCFLAGS="-I/home/cyng93/experiment/issues/so_kbuild_wildcard/include" \
make -C /lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build M=/home/cyng93/experiment/issues/so_kbuild_wildcard modules
make[1]: Entering directory '/linux'
CC [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/main.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "InitFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
WARNING: "CleanupFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
CC /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.mod.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko
make[1]: Leaving directory '/linux'
我尝试回显foo-objs
(在Makefile中检查[2]),发现方法[1-1]和&的值相同。 [1-2]。
SO上的任何人都提出类似的问题可以帮助掩盖一些问题吗?
(我更喜欢[1-2],因为它可以节省我在添加新子组件时更新Makefile的工作量)
下面我还附上了main.c
,foo1.c
&的源代码。 foo1.h
。
您还可以查看github repo for this issue以便更轻松地访问这些代码。
#include <linux/module.h>
#include "foo1.h"
static int myinit(void)
{
printk("Module inserted!\n");
InitFoo1();
return 0;
}
static void myexit(void)
{
CleanupFoo1();
printk("Module removed!\n");
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL v2");
在这里,foo1
是一个子组件,只需在初始化和清理过程中打印出一些内容:
#ifndef FOO1_H
#define FOO1_H
int InitFoo1(void);
void CleanupFoo1(void);
#endif
#include <linux/module.h>
#include "foo1.h"
int InitFoo1(void)
{
printk("Init Foo1\n");
return 0;
}
void CleanupTest(void)
{
printk("Cleanup Foo1\n");
}
根据下面的Tsyvarev回答,可以通过修改Makefile来修改Makefile,如下所示:
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2 (not working)]
# SRCS := main.c $(wildcard src/*.c)
# [approach 1-2 (working)]
MISC := $($(src)/wildcard src/*.c)
SRCS := main.c $(MISC:$(src)%/=%)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
答案 0 :(得分:0)
构建内核模块时,Makefile
处理两次:
make
时。M=$(PWD)
选项传递给它。首次使用当前目录处理Makefile,该目录等于模块的目录。因此,通配符按预期工作,通过从all
收据打印确认。
但第二次处理Makefile时,当前目录等于内核的构建目录(在您的情况下为/lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build
)。在那种模式下
$(wildcard src/*.c)
尝试在内核的构建目录中查找文件,这显然会失败。
在第二次处理时,可以使用$(src)
来引用模块的构建目录。
这样可以使用wildcard()
来收集模块的来源。但请注意,内核构建系统期望源文件(更确切地说, object 文件)的路径相对于模块的构建目录为。因此,需要删除使用$(src)
获得的每个文件的wildcard()
分量。