返回

精简Linux内核编译产物:高效模块编译指南

Linux

精简内核编译产物,方便后续模块编译

一个常见的问题是,在编译Linux内核之后,为了后续编译外部模块,通常需要保留庞大的内核源代码目录。这样做会占用大量的磁盘空间。仅仅执行make clean是不够的,它会清除必要的文件,导致模块编译失败。 仔细研究内核的Makefile,并没有提供直接清理不必要文件的目标。

本文旨在探讨如何最小化需要保留的内核编译产物,以满足后续外部模块的编译需求。 核心思路是识别并保留那些用于构建模块所需的头文件、配置文件和链接器脚本。

解决方案一:仅保留必要目录

一个相对简单的方法是手动识别并复制必要的目录和文件。这需要对内核的编译流程有基本的理解。 需要保留的核心目录通常包括以下几项:

  • include/:包含了内核头文件,它们定义了内核的接口,模块编译时会用到。
  • arch/<你的架构>/include/:针对特定架构的头文件。例如,arch/x86/include/
  • scripts/:包含一些辅助编译的脚本和工具。
  • .config:保存着内核配置选项,模块编译需要使用它来了解内核的构建配置。
  • Module.symvers:包含了内核导出的符号表,是编译模块的关键依赖。

操作步骤:

  1. 假设内核源代码路径为/path/to/kernel/source,创建一个新目录用于存放必要的编译产物,例如/path/to/reduced-kernel

  2. 执行复制操作:

    mkdir /path/to/reduced-kernel
    cp -r /path/to/kernel/source/include /path/to/reduced-kernel/
    cp -r /path/to/kernel/source/arch/x86/include  /path/to/reduced-kernel/arch/x86/  # 将x86替换成你使用的架构
    cp -r /path/to/kernel/source/scripts  /path/to/reduced-kernel/
    cp /path/to/kernel/source/.config /path/to/reduced-kernel/
    cp /path/to/kernel/source/Module.symvers /path/to/reduced-kernel/
    
  3. 设置KBUILD_PATH 环境变量:

export KBUILD_PATH=/path/to/reduced-kernel
  1. 现在,可以尝试使用/path/to/reduced-kernel进行外部模块的编译了,例如:
make -C /lib/modules/`uname -r`/build M=/path/to/your/module KBUILD_PATH=$KBUILD_PATH

原理: 这种方法依赖于内核模块编译对头文件和符号表的依赖关系,保留这些必要的元素足以完成编译。 KBUILD_PATH环境变量可以指定需要的内核目录路径。

优势: 手动控制更精细,清楚地了解保留了什么。
缺点: 步骤比较繁琐,可能漏掉某些必要的文件。针对不同的内核配置,可能需要修改步骤,需要开发者对内核有比较深刻的理解。

解决方案二:利用内核Makefile的export目标

内核的Makefile提供了一个不常用的export目标,该目标可以用于创建一个仅包含内核导出头文件的tar包。 该方法可以帮助我们缩小编译产物的体积,但需要一些额外的操作才能直接用于模块的编译。

操作步骤:

  1. 进入内核源码目录:

    cd /path/to/kernel/source
    
  2. 执行make headers_install 生成输出头文件的目录

    make headers_install INSTALL_HDR_PATH=/path/to/kernel_headers
    

3. **使用headers_install目录进行模块的编译。假设/path/to/kernel_headers中是执行headers_install之后产生的头文件输出目录,可以像下面这样做** 
```bash
export KBUILD_HEADERS=/path/to/kernel_headers
  1. 设置环境变量后,再次编译模块时使用:KBUILD_PATH=... make -C .... 可以忽略该变量.
make -C /lib/modules/`uname -r`/build M=/path/to/your/module KBUILD_HEADERS=$KBUILD_HEADERS

原理: headers_install会拷贝内核中用于编译外部模块需要的导出头文件。通过定义 KBUILD_HEADERS 变量可以将该头文件位置提供给编译模块的makefile。

优点: 省去了手动拷贝和识别文件的麻烦。 可以直接编译
缺点: 使用前需要配置好 KBUILD_HEADERS 环境变量。导出的头文件不如手动复制完整。

安全建议

  • 仔细测试: 在实际环境使用之前,务必在新创建的环境中编译几个模块进行测试,确认没有问题后再使用。
  • 备份: 在执行任何删除或者拷贝操作前,请备份你的原始内核源码目录,以防万一。
  • 了解依赖: 在修改精简产物结构时,请清楚理解每个文件/目录在编译过程中的作用。 某些配置下可能会需要一些额外的目录或者文件。
  • 关注内核版本变化: 不同内核版本的include/目录结构可能不同,或者引入了新的依赖关系,需要仔细核实并适配。