1

我将内核模块组织为不同的子组件,因此我可以轻松插入/删除现有的子模块以尝试或集成东西。

目录布局如下图所示:

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-1] 替换为 [1-2] 时,我收到如下所示的警告。

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 存储库以了解此问题,以便更轻松地访问这些代码。


主程序

#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是一个子组件,在初始化和清理过程中简单地打印出一些东西:

./include/foo1.h

#ifndef FOO1_H
#define FOO1_H

int InitFoo1(void);
void CleanupFoo1(void);

#endif

./src/foo1.c

#include <linux/module.h>
#include "foo1.h"


int InitFoo1(void)
{
    printk("Init Foo1\n");
    return 0;
}


void CleanupTest(void)
{
    printk("Cleanup Foo1\n");
}

更新_2018/01/15

根据下面的 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
4

1 回答 1

0

构建内核模块时,您Makefile会被处理两次

  1. 当您make从模块的目录中键入时。
  2. 在 Kbuild 进程内部,因为您将M=$(PWD)选项传递给它。

第一次处理 Makefile 时,当前目录等于模块的目录。所以通配符按预期工作,这通过从all收据打印得到确认。

但是第二次使用当前目录处理 Makefile 等于内核的构建目录/lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build在您的情况下)。在那种模式下

$(wildcard src/*.c)

尝试在内核的构建目录中查找文件,这显然失败了。


在第二次处理时,可以使用$(src).

这种方式可以wildcard()用于收集模块的来源。但请注意,内核构建系统期望源文件(更准确地说,目标文件)的路径与模块的构建目录相关。因此,需要剥离$(src)使用wildcard().

于 2018-01-13T09:12:38.523 回答