元模块
元模块是 KernelSU 的一项革新性功能,它将关键的模块系统能力从核心转移到可插拔模块中。这种架构转变在保持 KernelSU 稳定性和安全性的同时,为模块生态系统释放了更大的创新潜力。
什么是元模块?
元模块是一种特殊类型的 KernelSU 模块,为模块系统提供核心基础设施功能。与常规模块不同,元模块控制常规模块的安装和挂载方式。
元模块是一种基于插件的扩展机制,允许完全自定义 KernelSU 的模块管理基础设施。通过将挂载和安装逻辑委托给元模块,KernelSU 避免成为脆弱的检测点,同时支持多样化的实现策略。
主要特征:
- 基础设施角色: 元模块提供常规模块依赖的服务
- 单实例: 只允许一个元模块处于运行状态
- 优先执行: 元模块脚本在常规模块脚本之前运行
- 特殊钩子: 提供三个用于安装、挂载和清理的钩子脚本
为什么需要元模块?
传统的 Root 解决方案将挂载逻辑内置在核心中,这使得它们更容易被检测且难以演进。KernelSU 的元模块架构通过关注点分离解决了这些问题。
战略优势:
- 减少检测面: KernelSU 本身不执行挂载,减少了检测向量
- 稳定性: 核心保持稳定,而挂载实现可以不断演进
- 创新性: 社区可以开发替代挂载策略
- 选择性: 用户可以选择最适合其需求的实现
挂载灵活性:
- 无挂载: 对于仅使用无挂载模块的用户,完全避免挂载开销
- OverlayFS 挂载: 传统方法,支持读写层(通过
meta-overlayfs) - Magic Mount: Magisk 兼容挂载,以获得更好的应用兼容性
- 自定义实现: 基于 FUSE 的 overlayfs、自定义 VFS 挂载或全新方法
超越挂载:
- 可扩展性: 添加内核模块支持等功能,无需修改核心 KernelSU
- 模块化: 独立于 KernelSU 版本更新实现
- 定制化: 为特定设备或用例创建专门的解决方案
重要
如果没有安装元模块,依赖挂载的模块,其挂载功能将不会生效。新安装的 KernelSU 需要安装元模块(如 meta-overlayfs)才能使模块正常工作。
对于用户
安装元模块
像安装常规模块一样安装元模块:
- 下载元模块 ZIP 文件(例如
meta-overlayfs.zip) - 打开 KernelSU Manager 应用
- 点击浮动操作按钮(➕)
- 选择元模块 ZIP 文件
- 重启设备
meta-overlayfs 元模块是官方参考实现,提供传统的基于 overlayfs 的模块挂载,支持读写系统分区。
检查活动的元模块
您可以在 KernelSU Manager 应用的模块页面中查看当前活动的元模块。活动的元模块将显示在模块列表中,并带有特殊标识。
卸载元模块
警告
卸载元模块会影响所有模块。移除后,模块将不再被挂载,直到您安装另一个元模块。
卸载步骤:
- 打开 KernelSU Manager
- 在模块列表中找到元模块
- 点击卸载(您会看到特殊警告)
- 确认操作
- 重启设备
卸载后,如果您需要元模块的功能,应该安装另一个元模块。
单元模块约束
只允许一个元模块处于运行状态。如果您尝试安装第二个元模块,KernelSU 将阻止安装以避免冲突。
切换元模块的步骤:
- 卸载所有常规模块
- 卸载当前元模块
- 重启
- 安装新元模块
- 重新安装常规模块
- 再次重启
对于模块开发者
如果您正在开发常规 KernelSU 模块,您不需要太担心元模块。只要用户安装了兼容的元模块(如 meta-overlayfs),您的模块就能正常工作。
您需要知道的:
- 挂载需要元模块: 模块中的
system目录只有在用户安装了提供挂载功能的元模块时才会被挂载 - 无需更改代码: 现有模块无需修改即可继续工作
TIP
如果您熟悉 Magisk 模块开发,您的模块在安装元模块后将在 KernelSU 中以相同方式工作,因为它提供了 Magisk 兼容的挂载。
对于元模块开发者
创建元模块允许您自定义 KernelSU 处理模块安装、挂载和卸载的方式。
基本要求
元模块通过 module.prop 中的特殊属性来识别:
id=meta-example
name=My Custom Metamodule
version=1.0
versionCode=1
author=Your Name
description=Custom module mounting implementation
metamodule=1metamodule=1(或 metamodule=true)属性将此模块标记为元模块。没有此属性,模块将被视为常规模块。
文件结构
元模块结构:
meta-example/
├── module.prop (必须包含 metamodule=1)
│
│ *** 元模块特定钩子 ***
├── metamount.sh (可选: 自定义挂载处理程序)
├── metainstall.sh (可选: 常规模块的安装钩子)
├── metauninstall.sh (可选: 常规模块的清理钩子)
│
│ *** 标准模块文件(全部可选) ***
├── customize.sh (安装自定义)
├── post-fs-data.sh (post-fs-data 阶段脚本)
├── service.sh (late_start service 脚本)
├── boot-completed.sh (启动完成脚本)
├── uninstall.sh (元模块自己的卸载脚本)
└── [任何其他文件]除了特殊的元模块钩子外,元模块可以使用所有标准模块功能(生命周期脚本等)。
钩子脚本
元模块可以提供最多三个特殊钩子脚本:
1. metamount.sh - 挂载处理程序
目的: 控制启动期间模块的挂载方式。
执行时机: 参考 执行顺序
环境变量:
MODDIR: 元模块的目录路径(例如/data/adb/modules/meta-example)- 所有标准 KernelSU 环境变量
职责:
- 以无系统方式挂载所有已启用的模块
- 检查
skip_mount标志 - 处理特定模块的挂载要求
关键要求
执行挂载操作时,必须将源/设备名称设置为 "KSU"。这将挂载标识为属于 KernelSU。
示例(正确):
mount -t overlay -o lowerdir=/lower,upperdir=/upper,workdir=/work KSU /target对于现代挂载 API,设置源字符串:
fsconfig_set_string(fs, "source", "KSU")?;这对于 KernelSU 正确识别和管理其挂载至关重要。
示例脚本:
#!/system/bin/sh
MODDIR="${0%/*}"
# 示例: 简单的绑定挂载实现
for module in /data/adb/modules/*; do
if [ -f "$module/disable" ] || [ -f "$module/skip_mount" ]; then
continue
fi
if [ -d "$module/system" ]; then
# 使用 source=KSU 挂载(必需!)
mount -o bind,dev=KSU "$module/system" /system
fi
done2. metainstall.sh - 安装钩子
目的: 自定义常规模块的安装方式。
执行时机: 在模块安装期间,文件提取后但安装完成前。此脚本被内置安装程序source(而非执行),类似于 customize.sh 的工作方式。
环境变量和函数:
此脚本继承内置 install.sh 的所有变量和函数:
- 变量:
MODPATH、TMPDIR、ZIPFILE、ARCH、API、IS64BIT、KSU、KSU_VER、KSU_VER_CODE、BOOTMODE等 - 函数:
ui_print <msg>- 向控制台打印消息abort <msg>- 打印错误并终止安装set_perm <target> <owner> <group> <permission> [context]- 设置文件权限set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]- 递归设置权限install_module- 调用内置模块安装过程
用例:
- 在内置安装之前或之后处理模块文件(准备好后调用
install_module) - 移动模块文件
- 验证模块兼容性
- 设置特殊目录结构
- 初始化模块特定资源
注意: 安装元模块本身时不会调用此脚本。
3. metauninstall.sh - 清理钩子
目的: 卸载常规模块时清理资源。
执行时机: 在模块卸载期间,在删除模块目录之前。
环境变量:
MODULE_ID: 正在卸载的模块的 ID
用例:
- 处理文件
- 清理符号链接
- 释放分配的资源
- 更新内部跟踪
示例脚本:
#!/system/bin/sh
# 卸载常规模块时调用
MODULE_ID="$1"
IMG_MNT="/data/adb/metamodule/mnt"
# 从镜像中删除模块文件
if [ -d "$IMG_MNT/$MODULE_ID" ]; then
rm -rf "$IMG_MNT/$MODULE_ID"
fi执行顺序
了解启动执行顺序对于元模块开发至关重要:
post-fs-data 阶段:
1. 执行通用 post-fs-data.d 脚本
2. restorecon,加载 sepolicy.rule
3. 执行元模块的 post-fs-data.sh(如果存在)
4. 执行常规模块的 post-fs-data.sh
5. 加载 system.prop
6. 执行元模块的 metamount.sh
└─> 以无系统方式挂载所有模块
7. post-mount.d 阶段运行
- 通用 post-mount.d 脚本
- 元模块的 post-mount.sh(如果存在)
- 常规模块的 post-mount.sh
service 阶段:
1. 执行通用 service.d 脚本
2. 执行元模块的 service.sh(如果存在)
3. 执行常规模块的 service.sh
boot-completed 阶段:
1. 执行通用 boot-completed.d 脚本
2. 执行元模块的 boot-completed.sh(如果存在)
3. 执行常规模块的 boot-completed.sh要点:
metamount.sh在所有 post-fs-data 脚本(元模块和常规模块)之后运行- 元模块生命周期脚本(
post-fs-data.sh、service.sh、boot-completed.sh)始终在常规模块脚本之前运行 .d目录中的通用脚本在元模块脚本之前运行post-mount阶段在挂载完成后运行
符号链接机制
当安装元模块时,KernelSU 会创建一个符号链接:
/data/adb/metamodule -> /data/adb/modules/<metamodule_id>这为访问活动元模块提供了稳定的路径,无论其 ID 如何。
好处:
- 一致的访问路径
- 轻松检测活动元模块
- 简化配置
真实示例: meta-overlayfs
meta-overlayfs 元模块是官方参考实现。它展示了元模块开发的最佳实践。
架构
meta-overlayfs 使用双目录架构:
元数据目录:
/data/adb/modules/- 包含
module.prop、disable、skip_mount标记 - 启动期间快速扫描
- 存储占用小
- 包含
内容目录:
/data/adb/metamodule/mnt/- 包含实际模块文件(system、vendor、product 等)
- 存储在 ext4 镜像(
modules.img)中 - 使用 ext4 功能优化空间
metamount.sh 实现
以下是 meta-overlayfs 如何实现挂载处理程序:
#!/system/bin/sh
MODDIR="${0%/*}"
IMG_FILE="$MODDIR/modules.img"
MNT_DIR="$MODDIR/mnt"
# 如果尚未挂载,则挂载 ext4 镜像
if ! mountpoint -q "$MNT_DIR"; then
mkdir -p "$MNT_DIR"
mount -t ext4 -o loop,rw,noatime "$IMG_FILE" "$MNT_DIR"
fi
# 为双目录支持设置环境变量
export MODULE_METADATA_DIR="/data/adb/modules"
export MODULE_CONTENT_DIR="$MNT_DIR"
# 执行挂载二进制文件
# (实际挂载逻辑在 Rust 二进制文件中)
"$MODDIR/meta-overlayfs"主要特性
Overlayfs 挂载:
- 使用内核 overlayfs 进行真正的无系统修改
- 支持多个分区(system、vendor、product、system_ext、odm、oem)
- 通过
/data/adb/modules/.rw/支持读写层
源标识:
// 来自 meta-overlayfs/src/mount.rs
fsconfig_set_string(fs, "source", "KSU")?; // 必需!这为所有 overlay 挂载设置 dev=KSU,实现正确识别。
最佳实践
开发元模块时:
- **始终将源设置为"KSU"**以进行挂载操作 - 内核卸载和 zygisksu 卸载需要此设置才能正确卸载
- 优雅地处理错误 - 启动过程对时间敏感
- 尊重标准标志 - 支持
skip_mount和disable - 记录操作 - 使用
echo或日志记录进行调试 - 彻底测试 - 挂载错误可能导致启动循环
- 记录行为 - 清楚地解释您的元模块做什么
- 提供迁移路径 - 帮助用户从其他解决方案切换
测试您的元模块
发布前:
- 在干净的 KernelSU 设置上测试安装
- 验证挂载各种模块类型
- 检查兼容性与常见模块
- 测试卸载和清理
- 验证启动性能(metamount.sh 是阻塞的!)
- 确保正确的错误处理以避免启动循环
常见问题
我需要元模块吗?
对于用户: 仅当您想使用需要挂载的模块时。如果您只使用运行脚本而不修改系统文件的模块,则不需要元模块。
对于模块开发者: 不需要,您正常开发模块。仅当您的模块需要挂载时,用户才需要元模块。
对于高级用户: 仅当您想自定义挂载行为或创建替代挂载实现时。
我可以有多个元模块吗?
不可以。一次只能安装一个元模块。这可以防止冲突并确保可预测的行为。
如果我卸载了唯一的元模块会怎样?
模块将不再被挂载。您的设备将正常启动,但模块修改将不会应用,直到您安装另一个元模块。
meta-overlayfs 是必需的吗?
不是。它提供与大多数模块兼容的标准 overlayfs 挂载。如果您需要不同的行为,可以创建自己的元模块。
另请参阅
- 模块指南 - 通用模块开发
- 与 Magisk 的区别 - 比较 KernelSU 和 Magisk
- 如何构建 - 从源代码构建 KernelSU