1. 为什么需要系统瘦身?
最近在调试RK3566开发板时遇到一个头疼的问题:1GB内存的设备跑Android 11系统实在太吃力了。开机要等近30秒,操作时经常卡顿,这让我想起五年前用过的千元机体验。通过分析发现,Rockchip原厂提供的Android系统镜像为了兼容各种硬件配置,默认包含了大量我们用不到的驱动和服务,光内核镜像就占了31MB。
这种情况在嵌入式开发中很常见。我经手过的智能家居项目中,80%的设备实际只需要基础功能,但系统却加载了摄像头驱动、传感器支持等冗余模块。以门禁终端为例,根本用不到GPU加速和4K视频解码,但系统里这些功能一个不少。这就好比带着全套露营装备去上班,既占地方又影响行动效率。
2. 内核裁剪实战
2.1 配置检查与精简
先看内核配置,RK3566的默认配置文件rockchip_defconfig里埋着不少"地雷":
cd kernel/arch/arm64/configs make rockchip_defconfig重点检查这几个区域:
- 外设驱动:开发板没有PCIE接口,但配置里开了
CONFIG_PCIE_ROCKCHIP_HOST - 传感器支持:门禁设备不需要陀螺仪,但
CONFIG_GYRO_MPU6500开着 - 多媒体功能:广告机可能用不到
CONFIG_VIDEO_OV5695摄像头驱动
我常用的精简策略是"三不原则":
- 板上没有的硬件对应驱动直接关闭
- 产品用不到的功能模块全部禁用
- 调试用配置(如
CONFIG_DEBUG_FS)在量产时关闭
2.2 实测效果对比
经过一轮裁剪后,效果立竿见影:
| 指标 | 裁剪前 | 裁剪后 | 优化幅度 |
|---|---|---|---|
| 内核镜像大小 | 31MB | 26MB | ↓16% |
| 内核启动时间 | 4.99s | 1.02s | ↓79.5% |
| 完整启动时间 | 25.54s | 19.44s | ↓23.9% |
关键日志时间点变化也很明显:
# 裁剪前 [ 4.990744] init: init first stage started! # 裁剪后 [ 1.017721] init: init first stage started!3. U-Boot优化技巧
3.1 启动流程分析
用printenv查看启动参数时,发现U-Boot加载了压根不存在的SPI Flash驱动:
=> printenv bootargs # 显示包含MTD相关配置通过rk3568_defconfig可以看到这些冗余配置:
- CONFIG_SPL_SPI_FLASH_SUPPORT=y + # CONFIG_SPL_SPI_FLASH_SUPPORT=y - CONFIG_CMD_NAND=y + # CONFIG_CMD_NAND=y3.2 安全与性能平衡
AVB(Android Verified Boot)是个典型的取舍案例:
# 安全需求不高的设备可以关闭 # CONFIG_ANDROID_AVB=y实测关闭后:
- 启动时间减少约200ms
- 系统分区可读写性更强
- 但会失去启动链验证功能
建议根据实际场景选择,比如:
- 支付设备:保留AVB
- 工业控制器:可关闭
4. Android服务层裁剪
4.1 系统服务精简
在base_system.mk中,这些服务常是裁剪目标:
# 可能不需要的服务 PRODUCT_PACKAGES -= \ LiveWallpapers \ PhotoTable \ BasicDreams特别注意handheld_product.mk里的这些包:
# 智能设备通常不需要 PRODUCT_PACKAGES -= \ Calendar \ Email \ QuickSearchBox4.2 Rockchip定制APK处理
在vendor/rockchip/common/apps/apps.mk中,这些APK要特别注意:
# 常见可移除APK RK_APPS := \ RkVideoPlayer \ RkExplorer \ RkUpdateService有个坑我踩过:有些APK被多个mk文件引用,直接删除会导致编译失败。建议先用grep -r "APK名"全局搜索依赖关系。
5. 磁盘加密与文件系统优化
5.1 关闭磁盘加密
在BoardConfig.mk中添加:
# 关闭data分区加密 BOARD_USES_METADATA_PARTITION := true BOARD_WITHOUT_DYNAMIC_PARTITIONS := true优化效果:
- 首次启动时间减少约3秒
- 数据读写速度提升15-20%
- 但会降低数据安全性
5.2 文件系统调整
将fstab中的ext4改为f2fs:
/dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev 0 0实测在1GB设备上:
- 随机写入速度提升2倍
- 存储空间利用率提高约8%
- 但长期使用可能需要维护
6. 内存优化进阶技巧
6.1 32位系统编译
修改BoardConfig.mk的关键配置:
-TARGET_ARCH := arm64 +TARGET_ARCH := arm -TARGET_CPU_ABI := arm64-v8a +TARGET_CPU_ABI := armeabi-v7a效果对比:
| 指标 | 64位系统 | 32位系统 | 差异 |
|---|---|---|---|
| 内存占用 | 580MB | 420MB | ↓27.6% |
| 浮点运算 | 快 | 慢 | ↓约15% |
6.2 Android Go配置
在product.mk中添加:
PRODUCT_USE_GO_OPTIMIZATION := true BUILD_WITH_GO_OPT := true这个配置会让系统:
- 启用更激进的内存回收
- 限制后台进程数量
- 使用轻量级ART优化
7. 调试与验证方法
7.1 启动时间测量
我常用的三板斧:
- U-Boot阶段:看
Total: xxx ms日志 - 内核阶段:通过
printk.time=1参数 - Android阶段:
adb logcat -b events | grep "boot_progress"
7.2 内存占用分析
推荐组合工具:
adb shell dumpsys meminfo adb shell procrank adb shell top -m 10最近发现个好用的Python脚本:
import matplotlib.pyplot as plt # 可以可视化内存变化曲线8. 避坑指南
8.1 过度裁剪问题
有次裁剪后WiFi不能用,原因是:
- 删了
CONFIG_WL_ROCKCHIP - 但保留了
CONFIG_AP6XXX - 驱动依赖关系没理清
解决方案:
make menuconfig # 使用依赖检查功能8.2 兼容性风险
曾遇到OTA升级失败,原因是:
- 裁剪了
CONFIG_EXT4_FS - 但升级包需要解压到ext4分区
现在我的检查清单:
- 保留
/system/bin/recovery相关 - 确保基础文件系统支持完整
- 测试OTA全流程
9. 效果验收标准
建议建立量化指标:
- 启动时间:从按下电源键到launcher就绪
- 内存占用:开机24小时后剩余内存
- 存储占用:
df -h查看分区使用率 - 关键功能:摄像头/网络等必须正常
最近一个门禁项目的数据:
- 启动时间从28s→16s
- 内存占用从720MB→390MB
- 系统镜像从1.2GB→680MB
10. 持续优化思路
系统瘦身是个持续过程,我的经验是:
- 版本迭代:每次SDK更新后重新评估
- 需求变更:新增功能时针对性调整
- 工具链优化:尝试LTO、PGO等编译选项
- 自动化检查:用脚本监控镜像大小变化
有个实用的小技巧:建立裁剪配置的git分支,每次只改一个模块,方便回退和对比。