4、配置内核:通过 make linux-menuconfig 定制 Linux 内核,添加或删除驱动模块

好,到了这一步,咱们的 Buildroot 已经能把一个基础的内核编译出来了。但说实话,那个默认配置通常很「干净」——干净到可能连你板子上的网卡、声卡、触摸屏驱动都没有。

所以这一节,我们就来亲手折腾一下内核。说白了,就是通过 make linux-menuconfig 这个命令,打开一个图形化的配置界面,把咱们需要的驱动勾上,不需要的统统关掉。

4.1 为什么非要手动配内核?

你可能想问:Buildroot 不是有默认配置吗?为什么还要自己进去改?

嗯,我刚开始用 Buildroot 时也这么想。结果第一次把镜像烧到板子上,发现网卡不工作,串口只能输出不能输入…… 折腾了半天,才发现是内核里对应的驱动模块没编译进去。

说白了,Buildroot 的默认内核配置只是一个「最小可用集」。它保证你能启动,但外设驱动基本靠猜。你的板子用的是哪颗芯片、哪个型号的网卡、哪个接口的显示屏——这些都得你自己去告诉内核。

核心原则:内核配置的原则是「够用就好」。不要一股脑把所有驱动都选上,那样编译出来的内核又大又慢,还容易出冲突。

4.2 进入内核配置界面

在 Buildroot 的顶层目录下,执行:

make linux-menuconfig

等一下,这里有个小坑。我第一次执行这个命令时,等了半天没反应。后来发现是因为 Buildroot 还没下载和解压内核源码。它会先自动完成下载、解压、打补丁这些步骤,然后才弹出配置界面。所以如果看到终端在刷屏,别急,那是正常流程。

等一会儿,你会看到一个蓝底白字的界面,类似下面这样:

Linux/arm 5.10.24 Kernel Configuration
─────────────────────────────────────────────
    General setup  --->
    Enable loadable module support  --->
    Enable the block layer  --->
    System Type  --->
    Bus support  --->
    Kernel Features  --->
    Boot options  --->
    CPU Power Management  --->
    Floating point emulation  --->
    Userspace binary formats  --->
    Device Drivers  --->
    File systems  --->
    Security options  --->
    Cryptographic API  --->
    Library routines  --->
    Kernel hacking  --->
─────────────────────────────────────────────
    <Select>    <Exit>    <Help>

这个界面和 make menuconfig 一模一样,操作方式也一样:方向键移动,回车进入,空格或 Y 键选中,N 键取消。

4.3 添加驱动模块的实战流程

我以最常见的场景为例——给一块 ARM 板子添加 USB 网卡驱动和 I2C 驱动。你跟着走一遍,就能举一反三了。

4.3.1 添加 USB 网卡驱动

假设你的板子用的是 RTL8152 或 RTL8153 这种 USB 转以太网芯片。进入:

Device Drivers  --->
    Network device support  --->
        USB Network Adapters  --->
            <*> Realtek RTL8152/RTL8153 Based USB Ethernet Adapters

注意,这里要用 <*> 而不是 <M>。为什么?<*> 表示编译进内核,<M> 表示编译成模块。对于根文件系统里必须有的驱动(比如网卡、存储),我建议直接编译进内核。否则启动时还得先加载模块,但模块又放在文件系统里——这就成了「先有鸡还是先有蛋」的问题。

我的习惯:所有跟启动、网络、存储相关的驱动,一律编译进内核。其他外设(比如摄像头、声卡)可以编译成模块,按需加载。

4.3.2 添加 I2C 驱动

很多传感器、显示屏都挂在 I2C 总线上。进入:

Device Drivers  --->
    I2C support  --->
        I2C Hardware Bus support  --->
            <*> Synopsys DesignWare I2C adapter

这里要根据你的 SoC 型号来选择。比如全志的芯片通常用 DesignWare 的 I2C 控制器,而 STM32MP1 系列用的是 ST 自家的驱动。拿不准的话,去查芯片手册或者看内核源码里的 arch/arm/boot/dts/ 目录,设备树文件里会写明 compatible 属性。

4.4 删除不需要的驱动模块

添加驱动只是第一步。更重要的,其实是「做减法」。我见过不少新手,把内核配置里所有驱动都选上,结果编译出来的 zImage 有 20 多 MB,启动慢得像蜗牛。

举个例子,如果你的板子没有 WiFi 模块,那就把:

Device Drivers  --->
    Network device support  --->
        Wireless LAN  --->

这一整项都取消掉。同理,没有蓝牙就关掉蓝牙驱动,没有 PCIe 就关掉 PCIe 支持。

注意:删除驱动时要小心。有些驱动是系统依赖的,比如 CONFIG_OF(设备树支持)就不能关,关了内核连设备树都解析不了。如果不确定某个选项的作用,按 ? 键查看帮助信息。

4.5 保存配置并退出

配置完成后,按 Tab 键选中 <Save>,回车。它会问你保存路径,默认是 .config,直接回车就行。然后选 <Exit> 退出。

这时候,Buildroot 会把你的配置保存到 output/build/linux-xxx/.config 里。下次再执行 make 时,它会直接用这个配置来编译内核。

4.6 一个小技巧:保存配置到 Buildroot 外部

我个人习惯把内核配置单独保存一份,方便以后复用。比如:

cp output/build/linux-5.10.24/.config board/mycompany/myboard/linux.config

然后在 Buildroot 的配置里指定:

BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/mycompany/myboard/linux.config"

这样,就算你把 output 目录删了重来,内核配置也不会丢。我在项目里吃过这个亏——有一次不小心 make clean 把整个 output 清掉了,辛辛苦苦配了一下午的内核配置全没了。从那以后,我就养成了这个习惯。

4.7 本章知识体系

下面这张图,帮你理清内核配置的核心逻辑:

内核配置核心流程 make linux-menuconfig 添加驱动模块 删除无用驱动 调整内核特性 常见添加项 • USB网卡驱动 (RTL8152等) • I2C/Spi总线驱动 • 触摸屏/显示驱动 • 音频编解码器驱动 常见删除项 • 未使用的无线网卡驱动 • 未使用的蓝牙协议栈 • 未使用的文件系统 • 调试/测试选项 常用调整 • 内核抢占模型 • 内存管理参数 • 定时器频率 • 内核压缩方式 保存 .config 并退出

4.8 避坑指南

最后,分享几个我踩过的坑:

  • 配置没保存就退出——这个最冤。界面里选了半天,结果退出时选了 <Exit> 没选 <Save>,白忙活。记住:先 Save,再 Exit。
  • 依赖选项没选——比如你选了某个 USB 网卡驱动,但它依赖 USB 支持。如果你没开 USB 子系统,这个驱动虽然选上了,编译时也会报错。遇到这种情况,按 ? 查看依赖关系,把依赖项也勾上。
  • 设备树和驱动不匹配——有时候驱动选对了,但设备树里对应的节点 status 是 "disabled"。这属于硬件描述层面的问题,跟内核配置无关。如果驱动加载不上,记得去检查设备树。

嗯,内核配置这部分就讲到这里。你跟着操作一遍,把板子需要的驱动都配好,然后就可以继续往下走了。


公众号:蓝海资料掘金营,微信deep3321