🔗 运行环境:Linux
🚩 撰写作者:左手の明天
🥇 精选专栏:《python》
🔥 推荐专栏:《算法研究》
#### 防伪水印------ 左手の明天 ####💗 大家好🤗🤗🤗,我是**左手の明天**!好久不见💗
💗今天更新系列【C/C++ 】------ Linux内核裁剪💗
📆 最近更新:2026 年 03 月 08 日 ,左手の明天的第359篇原创博客
📚 更新于专栏: C/C++入门与进阶
#### 防伪水印------ 左手の明天 ####
在嵌入式Linux开发中,"内核裁剪"是绕不开的核心技能------我们日常接触的路由器、智能摄像头、NVR、车载设备等嵌入式产品,其内核都不是Linux官方的"完整版",而是经过针对性裁剪、适配硬件的"定制版"。很多新手会觉得内核裁剪"高深莫测",怕裁错导致系统崩溃,其实只要掌握"核心逻辑+实操步骤",就能轻松上手,甚至能根据需求精准控制内核体积,兼顾性能与资源占用。
本文将从"为什么要裁剪""裁剪的核心原理""手把手实操""避坑指南"四个维度,深入浅出讲解Linux内核裁剪,全程贴合嵌入式开发实际场景(以ARM架构、Linux 5.10 LTS版本为例),新手也能跟着一步步操作,最终实现一个"最小可用、适配硬件"的轻量化内核。
一、先搞懂:为什么要进行内核裁剪?
Linux官方内核(比如从kernel.org下载的源码)是一个"大而全"的集合,包含了支持各种架构(x86、ARM、RISC-V)、各种硬件(网卡、摄像头、硬盘)、各种功能(虚拟化、调试、网络协议)的代码,编译后体积通常在几十MB甚至上百MB。
但嵌入式设备的资源往往非常有限:比如入门级ARM开发板,内存可能只有64MB/128MB,存储可能只有几百MB(Flash/EMMC),CPU性能也远不如PC。如果直接使用完整版内核,会出现两个致命问题:
-
资源浪费:内核中大量无用的驱动(比如x86架构的驱动、PC端的显卡驱动)、功能模块(比如KVM虚拟化、IPv6协议)会占用大量内存和存储,导致设备运行卡顿,甚至无法正常启动;
-
稳定性下降:无用的模块会增加内核的复杂性,可能引入不必要的BUG,同时也会增加系统启动时间,影响嵌入式设备的实时性。
而内核裁剪的核心目的,就是"保留必需,删除无用"------只保留目标硬件必需的驱动、核心功能,删除所有不相关的模块,最终实现:
-
减小内核体积(通常可从几十MB压缩到几MB);
-
降低内存占用,释放更多资源给上层应用(如NVR的录像、预览功能);
-
缩短系统启动时间(从几十秒优化到几秒);
-
减少BUG,提升系统稳定性和实时性。
举个实际例子:海康威视NVR的嵌入式内核,就是基于Linux 4.19版本裁剪而来,只保留了ARM架构、HI35xx芯片相关驱动、ext4文件系统、RTSP/ONVIF相关网络协议,删除了x86、RISC-V架构支持、虚拟化、多余的文件系统(如ntfs)等,最终内核体积控制在5MB以内,确保NVR能稳定运行在资源有限的硬件上。
二、核心原理:内核裁剪的"底层逻辑"
很多新手觉得裁剪难,其实是没搞懂内核的"组织方式"。Linux内核的源码是按"模块"组织的,每个模块对应一个功能或一个驱动,比如:
-
架构相关模块:对应不同的CPU架构(ARM、x86等);
-
驱动模块:对应各种硬件(网卡、串口、GPIO、存储等);
-
功能模块:对应网络协议(TCP/IP、IPv6)、文件系统(ext4、yaffs2)、调试功能(KGDB)等;
-
通用模块:对应内核的基础功能(进程管理、内存管理)。
内核裁剪,本质上就是"选择哪些模块编译进内核、哪些模块不编译、哪些模块编译为可加载模块",对应三种配置选项:
| 配置选项 | 含义 | 适用场景 |
|---|---|---|
| y(yes) | 将模块直接编译进内核(内核启动时自动加载) | 必需的模块(如CPU架构支持、核心驱动) |
| m(module) | 将模块编译为可加载模块(需要时手动加载) | 可选的模块(如不常用的外设驱动) |
| n(no) | 不编译该模块(彻底删除) | 无用的模块(如其他架构驱动、多余功能) |
核心原则:只将"硬件必需、应用必需"的模块设为y,可选模块设为m,无用模块设为n。比如嵌入式板卡没有IPv6需求,就将IPv6协议设为n;没有USB设备,就将USB驱动设为n。
另外,内核裁剪有一个"黄金法则":不盲目裁剪,以厂商默认配置为基础。大多数嵌入式芯片厂商(如华为海思、瑞芯微)都会提供针对自家芯片的"默认配置文件(defconfig)",这个文件已经适配了芯片的核心硬件,我们在此基础上裁剪,能大幅降低出错概率,避免从零配置导致的硬件不兼容。
三、手把手实操:Linux内核裁剪全流程(ARM架构为例)
本节以"ARM架构、Linux 5.10 LTS内核、Ubuntu 20.04交叉编译环境"为例,一步步完成内核裁剪、编译、验证,全程可复现,新手跟着做就能成功。
前置准备
-
内核源码:从kernel.org下载Linux 5.10 LTS源码(https://www.kernel.org/),解压到Ubuntu目录(如/home/user/linux-5.10.y);
-
交叉编译工具链:安装ARM架构交叉编译器(如arm-linux-gnueabihf-gcc),用于编译适配ARM板卡的内核;
-
厂商defconfig:获取目标板卡的defconfig文件(如imx6ull的defconfig),拷贝到内核源码的arch/arm/configs/目录下(若没有,可使用内核自带的arm_defconfig作为基础);
-
依赖工具:安装编译内核所需的依赖(Ubuntu下执行):
cppsudo apt install make libncurses5-dev flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf
步骤1:加载默认配置(核心一步)
进入内核源码目录,加载厂商提供的defconfig,这是裁剪的基础,避免从零配置:
bash
# 进入内核源码目录
cd /home/user/linux-5.10.y
# 加载defconfig(以imx6ull为例,替换为自己的板卡defconfig)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx6ull_14x14_evk_defconfig
说明:ARCH=arm指定目标架构为ARM,CROSS_COMPILE指定交叉编译器前缀,imx6ull_14x14_evk_defconfig是厂商提供的默认配置,加载后会生成.config文件(内核配置文件),后续的裁剪都是修改这个文件。
步骤2:图形化裁剪(最常用、最直观)
内核提供了多种裁剪方式(menuconfig、xconfig、gconfig),其中menuconfig是字符界面,无需图形化环境,最适合嵌入式开发,执行以下命令启动图形化裁剪界面:
bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
启动后,会进入如下界面(字符界面,可通过方向键操作):
(此处省略界面截图,核心操作:方向键上下选择选项,Enter进入子菜单,空格切换配置选项y/m/n,Esc退出)
下面重点讲解"新手必剪"的模块,按以下分类裁剪,避免裁错核心功能:
分类1:架构相关(必剪,避免无用架构占用体积)
进入 "Architecture support" 子菜单,只保留目标架构(ARM),删除其他架构:
-
保留:ARM architecture(设为y)、目标CPU型号(如ARMv7);
-
删除:x86、RISC-V、MIPS等所有非ARM架构(设为n)。
分类2:驱动模块(核心裁剪,只保留硬件必需驱动)
进入 "Device Drivers" 子菜单,这是裁剪的重点,按目标板卡的硬件配置逐一筛选:
-
保留:板卡实际存在的硬件驱动(如UART串口、SPI、I2C、网卡、EMMC/SD卡、GPIO),设为y;
-
删除:
-
USB相关:若板卡无USB设备,删除USB驱动(USB support设为n);
-
显卡驱动:嵌入式板卡通常无独立显卡,删除显卡驱动(Graphics support下的无用驱动);
-
其他外设:如蓝牙、WiFi(无相关硬件则删除)、并口、串口(多余的串口)。
-
注意:驱动裁剪是最容易出错的地方,若不确定某类驱动是否需要,可先设为m(编译为模块),避免设为n导致硬件无法使用。
分类3:文件系统(按需裁剪,只保留根文件系统类型)
进入 "File systems" 子菜单,嵌入式根文件系统通常用ext4、yaffs2、jffs2,其他文件系统可删除:
-
保留:ext4(最常用)、yaffs2(适配Flash),设为y;
-
删除:ntfs(Windows文件系统)、btrfs(PC端文件系统)、xfs等无用文件系统(设为n)。
分类4:功能模块(删除无用功能,大幅减小体积)
进入 "General setup""Networking support" 等子菜单,删除嵌入式设备用不到的功能:
-
调试功能:删除KGDB(内核调试)、printk调试信息(设为n),可大幅减小体积;
-
网络协议:若无需IPv6,删除IPv6协议(Networking support → IPv6设为n);
-
虚拟化:删除KVM、QEMU相关功能(设为n);
-
其他:删除Power management(若无需电源管理)、System V IPC(无用则删除)。
分类5:模块编译优化(可选,进一步减小体积)
进入 "Enable loadable module support" 子菜单,若不需要动态加载模块,可关闭"Enable loadable module support"(设为n),这样所有模块都会编译进内核,同时删除模块相关的功能,进一步减小体积(适合对稳定性要求高、无需动态加载驱动的场景)。
步骤3:保存配置并退出
裁剪完成后,按Esc键退出子菜单,回到主界面,选择 "Save" 保存配置,默认保存到.config文件(无需修改文件名),然后选择 "Exit" 退出menuconfig。
步骤4:编译内核
配置完成后,执行编译命令,生成适配ARM板卡的内核镜像和设备树(DTB):
bash
# 编译内核镜像(zImage,ARM架构常用)和设备树(dtb)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage dtbs -j$(nproc)
# 若需要编译模块(之前设为m的模块),执行以下命令
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules INSTALL_MOD_PATH=./modules_out install
说明:-j$(nproc) 表示使用当前CPU所有核心编译,加快编译速度;编译完成后,内核镜像(zImage)路径为 arch/arm/boot/zImage,设备树路径为 arch/arm/boot/dts/(对应板卡的.dtb文件)。
步骤5:验证裁剪结果
编译完成后,我们可以通过两个方式验证裁剪效果:
-
查看内核体积:对比裁剪前后的zImage文件大小,通常裁剪后体积可从20MB+压缩到5MB以内;
-
烧写验证:将zImage和dtb烧写到目标板卡,启动系统,查看是否能正常启动,核心硬件(串口、网卡、存储)是否正常工作。
若系统能正常启动,且核心功能正常,说明裁剪成功;若启动失败(如串口无输出、无法挂载根文件系统),大概率是某类核心驱动被误裁,可重新进入menuconfig,将对应的驱动设为y,重新编译烧写。
四、避坑指南:新手最容易踩的5个坑
很多新手裁剪内核时,容易出现"裁错导致系统崩溃"的问题,总结以下5个高频坑,帮你避开不必要的麻烦:
坑1:从零配置,不使用厂商defconfig
新手容易直接执行make menuconfig,从零开始配置,导致核心硬件驱动缺失,系统无法启动。正确做法:优先使用厂商提供的defconfig,在此基础上裁剪,厂商defconfig已经适配了芯片的核心硬件,能大幅降低出错概率。
坑2:误裁核心驱动/架构模块
比如将ARM架构支持、串口驱动、根文件系统驱动设为n,导致系统无法启动。解决方法:裁剪时牢记"不确定就不裁",若不确定某模块是否必需,可先设为m,后续验证后再决定是否删除;核心驱动(如串口、存储)必须设为y。
坑3:关闭所有调试功能,导致无法定位问题
新手为了减小体积,会删除所有调试功能(如printk、KGDB),但裁剪后若系统启动失败,无法通过日志定位问题。正确做法:调试阶段保留基础调试功能,待系统稳定后,再删除调试功能,减小体积。
坑4:裁剪后不验证,直接量产
裁剪完成后,只查看内核体积,不烧写验证,导致量产时出现硬件不兼容、功能异常等问题。正确做法:裁剪后必须烧写目标板卡,验证核心功能(启动、驱动、文件系统、网络)是否正常,确保无问题后再进行后续操作。
坑5:过度裁剪,追求"最小体积"而牺牲稳定性
有些新手一味追求最小体积,删除一些看似无用但实际必需的模块(如内存管理相关模块),导致系统运行不稳定、频繁崩溃。核心原则:裁剪的前提是"稳定可用",体积不是越小越好,而是"够用即可"。
五、总结:内核裁剪的核心逻辑与进阶方向
通过本文的讲解,相信你已经明白:Linux内核裁剪并不是"玄学",而是"按需取舍"的过程,核心逻辑是"以厂商defconfig为基础,保留必需模块,删除无用模块,兼顾体积与稳定性"。
对于新手来说,先掌握"基础裁剪流程",能完成嵌入式板卡的内核裁剪、编译、验证,就已经达标;对于进阶需求,可进一步学习:
-
内核配置文件(.config)的手动修改,精准控制每一个模块;
-
内核模块的动态加载与卸载,灵活适配不同硬件;
-
内核裁剪的极致优化,比如删除内核冗余代码、优化编译选项,进一步减小体积、提升性能。
最后提醒:内核裁剪是一个"反复调试、逐步优化"的过程,新手不必担心裁错,多尝试、多验证,就能慢慢掌握其中的技巧。比如海康威视NVR的内核裁剪,也是经过多次调试、验证,才最终确定最优的配置,既保证了系统稳定,又控制了内核体积,支撑上层APP(录像、预览、告警)的稳定运行。
如果你在实操过程中遇到问题(如编译失败、系统启动异常),可以在评论区留言,我会逐一解答,帮你顺利完成内核裁剪!