• 构建外部模块(Building External Modules)


    参考文档

    构建外部模块(Building External Modules)

    • 本文档描述了如何构建树外内核模块。(This document describes how to build an out-of-tree kernel module.)

    1) 简介(Introduction)

    • “kbuild”是 Linux 内核使用的构建系统。模块必须使用 kbuild 来与构建基础设施的变化保持兼容,并为“gcc”选择正确的标志。提供了在树内和树外构建模块的功能。构建两者的方法类似,所有模块最初都是在树外开发和构建的。(“kbuild” is the build system used by the Linux kernel. Modules must use kbuild to stay compatible with changes in the build infrastructure and to pick up the right flags to “gcc.” Functionality for building modules both in-tree and out-of-tree is provided. The method for building either is similar, and all modules are initially developed and built out-of-tree.)

    2) 如何构建外部模块(How to Build External Modules)

    1. 要构建外部模块,您必须有一个可用的预构建内核,其中包含构建中使用的配置和头文件。此外,内核必须是在启用模块的情况下构建的。如果您使用的是发行版内核,您的发行版将为您运行的内核提供一个包。(To build external modules, you must have a prebuilt kernel available that contains the configuration and header files used in the build. Also, the kernel must have been built with modules enabled. If you are using a distribution kernel, there will be a package for the kernel you are running provided by your distribution.)
    2. 另一种方法是使用“make”目标“modules_prepare”。这将确保内核包含所需的信息。该目标仅作为一种简单的方法而存在,可以为构建外部模块准备内核源代码树。(An alternative is to use the “make” target “modules_prepare.” This will make sure the kernel contains the information required. The target exists solely as a simple way to prepare a kernel source tree for building external modules.)
    3. 注意:即使设置了 CONFIG_MODVERSIONS,“modules_prepare”也不会构建 Module.symvers;因此,需要执行完整的内核构建以使模块版本控制工作。(NOTE: “modules_prepare” will not build Module.symvers even if CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be executed to make module versioning work.)

    2.1 命令语法(Command Syntax)

    构建外部模块的命令是:(The command to build an external module is:)

    $ make -C <path_to_kernel_src> M=$PWD
    
    • 1

    由于命令中给出的“M=<dir>”选项,kbuild 系统知道正在构建外部模块。(The kbuild system knows that an external module is being built due to the “M=<dir>” option given in the command.)

    要针对正在运行的内核进行构建,请使用:(To build against the running kernel use)

    $ make -C /lib/modules/`uname -r`/build M=$PWD
    
    • 1

    2.2选项 (Options)

    $KDIR 是指内核源目录的路径。($KDIR refers to the path of the kernel source directory.)

    make -C $KDIR M=$PWD
    
    • 1

    2.3 目标(Targets)

    在构建外部模块时,只有一部分“make”目标可用。(When building an external module, only a subset of the “make” targets are available.)

    make -C $KDIR M=$PWD [target]
    
    all:
            make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
    clean:
            make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
    
    标准的 make -C 指令是这样的:
       make -C $KDIR M=$PWD [target],下面分别介绍每个字段的含义。
        -C 选项:make -C 表示进入到-C 参数对应的目录中进行编译工作,对应的也是解析目标目录下的
    Makefile,编译完成时返回。
        $KDIR:/lib/modules/$(shell uname -r)/build/,指定内核源码的位置,表示进行内核源码根目录下
    进行编译。
        直接在目标板上编译时,内核头文件默认存放在/lib/modules/$(shell uname -r)/build/中,这个
    build/目录是一个软连接,链接到源码头文件的安装位置。而内核真正的源码库则直接引用正在运行的内核镜
    像。当跨平台编译时,就需要指定相应的内核源码目录,而不是系统中的源码目录,同时交叉编译时,需要指定架构平台和交叉编译工具链;
        M=$(PWD):表示在内核中需要被编译的目录,在示例中也就是当前目录。
        modules,属于[target]部分,事实上,这是个可选选项。默认行为是将源文件编译并生成内核模块,即
    module(s),但是它还支持一下选项:
        modules_install:安装这个外部模块,默认安装地址是/lib/modules/$(uname -r)/extra/,同时可以
    由内建变量 INSTALL_MOD_PATH 指定安装目录
        clean:卸载源文件目录下编译过程生成的文件,在上文的 Makefile 最后一行可以看到。
        help:帮助信息
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.4构建单独的文件(Building Separate Files)

    make -C $KDIR M=$PWD bar.lst
    make -C $KDIR M=$PWD baz.o
    make -C $KDIR M=$PWD foo.ko
    make -C $KDIR M=$PWD ./
    
    • 1
    • 2
    • 3
    • 4

    3) 为外部模块创建 Kbuild 文件(Creating a Kbuild File for an External Module)

    obj-m := <module_name>.o
    
    • 1

    kbuild 系统将从 <module_name>.c 构建 <module_name>.o,并在链接后生成内核模块 <module_name>.ko。上面的行可以放在“Kbuild”文件或“Makefile”中。当模块是从多个源构建的时,需要额外的一行来列出文件:(The kbuild system will build <module_name>.o from <module_name>.c, and, after linking, will result in the kernel module <module_name>.ko. The above line can be put in either a “Kbuild” file or a “Makefile.” When the module is built from multiple sources, an additional line is needed listing the files:)

    <module_name>-y := <src1>.o <src2>.o ......
    
    • 1

    编译多个源文件

    hello_world 总是简单的,但是在实际开发中,就会出现更复杂的情况,这时候就需要了解更多的Makefile选项:

    首先,当一个 .o 目标文件的生成依赖多个源文件时,显然 make 的自动推导规则就力不从心了(它只能根据同名推导,比如编译 filename.o,只会去查找 filename.c ),我们可以这样指定:

    obj-m  += hello.o
    hello-y := a.o b.o hello_world.o
    
    • 1
    • 2

    hello.o 目标文件依赖于 a.o, b.o, hello_world.o,那么这里的 a.o 和 b.o 如果没有指定源文件,根据推导规则就是依赖源文件 a.c, b.c, hello_world.c.

    除了hello-y,同时也可以用hello-objs,实现效果是一样的。

    同时编译多个可加载模块

    kbuild支持同时编译多个可加载模块,也就是生成多个.ko文件,它的格式是这样的:

    obj-m := foo.o bar.o
    foo-y := <foo_srcs>
    bar-y := <bar_srcs>
    
    • 1
    • 2
    • 3

    外部模块头文件的放置

    当编译的目标模块依赖多个头文件时,kbuild对头文件的放置有这样的规定:

    直接放置在 Makefile 同在的目录下,在编译时当前目录会被添加到头文件搜索目录。 放置在系统目录,这个系统目录是源代码目录中的 include/linux/,注意是源代码目录而不是系统目录。 与通用的 Makefile 一样,使用 -I$(DIR) 来指定,不同的是,代表编译选项的变量是固定的,为 ccflag,因为当前 Makefile 相当于是镶嵌到 Kbuild 系统中进行编译,所以必须遵循 Kbuild 中的规定.

    一般的用法是这样的:

    .
    |__ src
    |   |__ complex_main.c
    |   |__ hal
    |       |__ hardwareif.c
    |       |__ include
    |           |__ hardwareif.h
    |__ include
    |__ complex.h
    
    
    --> filename: Kbuild
    obj-m := complex.o
    complex-y := src/complex_main.o
    complex-y += src/hal/hardwareif.o
    
    ccflags-y := -I$(src)/include
    ccflags-y += -I$(src)/src/hal/include
    
    
    ccflags-y := -I$(DIR)/include
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    kbuild就会将$(DIR)/include目录添加到编译时的头文件搜索目录中。

  • 相关阅读:
    java毕业设计少儿编程教育网站系统mybatis+源码+调试部署+系统+数据库+lw
    微服务集成redis并通过redis实现排行榜的功能
    spring复习(第三天上午)(黑马版)
    SpringCloud Gateway 服务网关的快速入门
    Redis hash 命令总结
    NGINX免费配置二级域名及同时开启HTTPS(HTTP强制转HTTPS)nodejs的express后端项目,前端next.js的SSR项目
    CSS逻辑组合伪类
    想要精准营销,从学习搭建一套对的标签体系开始丨DTVision分析洞察篇
    内存条选购注意事项(电脑,笔记本)
    正则表达式
  • 原文地址:https://blog.csdn.net/sinat_42884063/article/details/125509356