当前位置: 首页 > news >正文

【内核驱动基础】内核模块的两种编译方式(in-tree vs out-of-tree)

目录

一、内核模块的编译方式(in-tree vs out-of-tree)

二、内核树外编译(out-of-tree)

特点

典型做法

适用场景

三、内核树内编译(in-tree)

参考资料


一、内核模块的编译方式(in-tree vs out-of-tree)

通常而言,内核模块代码有两种常见的构建形态:

  1. 内核树内编译(in-tree):把模块源码放进(或集成进)内核源码树,由内核顶层构建系统统一编译。
  2. 内核树外编译(out-of-tree,外部模块):模块源码独立放在内核树之外,通过make -C <kernel_dir> M=<module_dir> modules借用内核 Kbuild 来编译。

二、内核树外编译(out-of-tree)

特点

  • 模块源码独立,不需要进入内核源码树。

  • 仍然使用内核的 Kbuild 规则来编译,关键命令是:

    make -C <KERNEL_DIR> M=<MODULE_DIR> modules

典型做法

  • 模块目录里只放一个“外部模块 Makefile”
    • obj-m := hellomodule.o
    • make -C $(KERNEL_DIR) M=$(CURDIR) modules

适用场景

  • 驱动/模块开发调试(迭代快)
  • 第三方闭源或单独交付(不改内核树)
  • 同一内核版本下给多个项目复用

在内核树外编译的方式在我们之前的文章中其实已经实现了,可以参考【内核驱动基础】超详细一文详解Linux驱动模块这一文章,主要实现就是Makefile文件的编写

三、内核树内编译(in-tree)

在内核源码的文件目录下,我们可以看到有很多的驱动程序,我们通过drivers/char中的Makefile文件进一步举例说明,其位置如下:

Makefile文件的内容如下:

# SPDX-License-Identifier: GPL-2.0 # # Makefile for the kernel character device drivers. # obj-y += mem.o random.o obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o obj-$(CONFIG_IBM_BSR) += bsr.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_APM_EMULATION) += apm-emulation.o obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ obj-$(CONFIG_NVRAM) += nvram.o obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_HW_RANDOM) += hw_random/ obj-$(CONFIG_PPDEV) += ppdev.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o obj-$(CONFIG_MWAVE) += mwave/ obj-y += agp/ obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o obj-$(CONFIG_TCG_TPM) += tpm/ obj-$(CONFIG_PS3_FLASH) += ps3flash.o obj-$(CONFIG_XILLYBUS) += xillybus/ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o obj-$(CONFIG_ADI) += adi.o

这个文件的主要作用就是告诉内核的构建系统(Kbuild)在“字符设备驱动”这个目录下,需要编译哪些源文件/子目录,以及它们是编进内核(built-in)还是编成模块(.ko)。

典型写法是这种:

obj-$(CONFIG_FOO) += foo.o

含义:

  • CONFIG_FOO=yfoo.o编进内核镜像(built-in)
  • CONFIG_FOO=mfoo.o会被链接成foo.ko(模块)
  • CONFIG_FOO=n→ 不编译

那么问题来了,这些变量在哪里被设置呢?

—答:在内核根目录.config文件中进行配置,在我们make板卡厂家给的默认配置时,会默认配置.config文件

截取部分.config文件如下:

我们继续提问,这个.config又如何去修改里面的配置参数呢?当然,如果你要手动编写也是无可厚非的,但问题是内核有成千上万个配置选项(CONFIG_*),所以,内核引入了menuconfig。

这个.config文件是由各个驱动目录下的Kconfig文件汇总得到的,只需要修改驱动目录下对应的Kconfig文件,使用make menuconfig可以快速配置.config文件的参数内容。

menuconfig 是 Linux 内核 Kconfig 配置系统提供的一个交互式(终端界面)配置工具。它的核心目的很简单:让你用“菜单”的方式生成/修改内核的 .config,从而决定内核和各类驱动/子系统到底编译进内核(y)、编译成模块(m)还是不编译(n)。其界面如下:

在执行make menuconfig指令的时候一定要确定好自己的编译平台和交叉编译链工具是否正确,否则在部署到板卡上后很有可能会产生错误。例如在rk3588上是如下配置的:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig

menuconfig常用的快捷键如下

  • /:搜索配置项(强烈推荐)
    • 输入关键字或CONFIG_名称,能直接定位选项所在菜单
  • ?:查看当前选项帮助信息(help)
  • y / n / m:直接把当前项设为 y/n/m
  • Space:循环切换状态(n → m → y)
  • Esc:返回/退出

技巧:找不到某个驱动选项时,先按 / 搜它,再根据搜索结果跳转到对应菜单。

下面我们使用一个实例进行强化:

我们当前完成了一个简单驱动程序模块:

#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> static int __init hello_init(void) { printk(KERN_EMERG "[ KERN_EMERG ] Hello Module Init\\n"); printk( "[ default ] Hello Module Init\\n"); return 0; } static void __exit hello_exit(void) { printk("[ default ] Hello Module Exit\\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL2"); MODULE_AUTHOR("cc "); MODULE_DESCRIPTION("hello world module"); MODULE_ALIAS("test_module");

我们将程序放入内核drivers/char目录下

在当前目录下的Makefile文件中,我们配置模块参数

在当前目录的Kconfig文件中,编写模块的Kconfig信息

此处的状态可以设置为bool(y或n)或者tristate(三态,y、n、m,m表示为一个模块)

然后在内核根目录执行make menuconfig,使用/搜索HELLO_MODULE可以看到如下:

在.config文件中搜索HELLO_MODULE可以看到参数已经配置成y

如果想要配置成默认为n,也可以在menuconfig中配置

至此,介绍完了两种编译方式,大家可以自行尝试加深理解。

参考资料

  • Linux下menuconfig与Kconfig基础知识概要
  • 韦东山Linux驱动课程
  • 内核参考文档
http://www.jsqmd.com/news/311290/

相关文章:

  • 硬的技术与可靠品质 比亚迪凭硬核实力出圈
  • 2026年质量好的速冻鱼片/速冻巴沙鱼片主流选择榜
  • 2026年比较好的打孔雕刻工具/石雕雕刻工具人气实力厂商推荐
  • 2026年比较好的护栏网/江苏护栏厂家信誉综合参考
  • HarmonyOS PC 应用的维护成本,从哪来?
  • 哪些 HarmonyOS PC 架构,注定难维护?
  • 基于VLAN标签的网络访问控制实验报告
  • 双非本能搞智驾吗?座舱相关开发怎样?
  • 2026年评价高的抽屉式厨房拉篮/双层厨房拉篮厂家用户好评推荐
  • 2026年评价高的不锈钢厨房水槽/大单槽304不锈钢厨房水槽厂家选择参考建议
  • 2026年知名的反弹器/磁吸反弹器厂家选购参考汇总
  • 第二日笔记
  • 2026年靠谱的阻燃面料/提花面料厂家选择参考建议
  • 2026年热门的二段力缓冲阻尼铰链/合页缓冲阻尼铰链品牌厂家推荐
  • duckDB C++源代码解析
  • 2026年徐州优质电子皮带秤厂家综合评估与精选推荐
  • Yjs 前端实时协作库学习笔记
  • 该如何选择深圳进行算力服务器托管
  • 项目实战: LAMP-电商平台-iwebshop
  • 2026年开年盘点:徐州专业皮带秤销售厂家推荐
  • 2026年精品二手车买卖:五家值得关注的实力公司推荐
  • i386 CPU页式存储管理深度解析
  • 2026年浙江运动鞋垫厂商盘点:技术实力与市场格局解析
  • 2026开年精选:江苏地区罐体防腐保温工程实力团队解析
  • 2026宜昌夷陵区复合肥选购指南:数据驱动的店铺推荐与案例分析
  • 2026天津市政工程路边石厂家综合实力对比与选购指南
  • 2026年长沙地区值得关注的短视频运营服务商盘点
  • 2026年现阶段天津吉林白订购厂家推荐
  • 2026年无局放试验设备选购指南:口碑厂家深度评测与推荐
  • 2026年开年口碑不错的火烧板供应厂家哪家专业