完全指南:架构原理、三个 Hook 脚本开发与 meta-overlayfs 参考实现)
KernelSU Metamodule元模块完全指南架构原理、三个 Hook 脚本开发与 meta-overlayfs 参考实现【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSUMetamodule元模块是 KernelSU 引入的一种插件化扩展机制它将传统 root 方案内置在守护进程核心中的模块安装/挂载逻辑抽离为可独立安装、可替换的特殊模块。本文以官方文档为主线结合ksud守护进程源码系统讲解 metamodule 的设计动机、用户操作流程、hook 脚本开发规范、启动执行顺序以及官方参考实现meta-overlayfs的架构细节帮助普通用户正确使用、模块开发者理解兼容性边界、进阶开发者写出可上线的自定义 metamodule。什么是 MetamoduleMetamodule 是一种特殊的 KernelSU 模块它为整个模块系统提供核心基础设施功能。普通模块的作用是修改系统文件通过system/目录实现 systemless 修改而 metamodule 控制的则是普通模块如何被安装、如何被挂载。从源码角度可以更精确地理解这一概念。metamodule.rs 中通过is_metamodule()函数判定一个模块是否为 metamodule它读取模块的module.prop属性表检查metamodule键的值是否为1或true大小写不敏感。其余所有模块都被当作普通模块处理。关键特性基础设施角色普通模块的运行依赖 metamodule 提供的挂载等服务单实例约束同一时间只能安装一个 metamodule源码在 module.rs 的安装流程中对此做了强制校验优先执行metamodule 的脚本总是先于普通模块脚本执行详见下文启动执行顺序专属 Hook提供安装metainstall.sh、挂载metamount.sh、清理metauninstall.sh三个特殊脚本。为什么需要 Metamodule传统 root 方案把挂载逻辑内置在核心中这使得核心更容易被检测、也更难演进。KernelSU 的 metamodule 架构通过关注点分离separation of concerns解决这个问题。战略优势缩小检测面KernelSU 自身不执行挂载操作减少了被检测的向量稳定性守护进程核心保持稳定挂载实现可以独立演进、独立修复创新空间社区可以在不 fork KernelSU 的前提下发展替代挂载策略选择自由用户可以选择最适合自己需求的实现。挂载方式的灵活性不挂载对于只使用无需挂载型模块仅执行脚本的用户完全省去挂载开销OverlayFS 挂载传统方案支持读写层通过meta-overlayfsMagic mount兼容 Magisk 的挂载方式应用兼容性更好自定义实现基于 FUSE 的 overlay、自定义 VFS 挂载或全新的方案。超越挂载本身的价值可扩展无需修改 KernelSU 核心即可添加内核模块支持等新特性模块化挂载实现可以独立于 KernelSU 版本单独更新定制化可为特定设备或特定场景打造专用解决方案。重要提示如果没有安装 metamodule普通模块将不会被挂载。全新安装的 KernelSU 必须安装一个 metamodule如meta-overlayfs才能使模块生效。用户指南安装 Metamodule安装 metamodule 的方式与安装普通模块完全相同下载 metamodule 的 ZIP 文件例如meta-overlayfs.zip打开 KernelSU Manager 应用点击悬浮操作按钮➕选择 metamodule 的 ZIP 文件重启设备。meta-overlayfs是官方参考实现提供基于传统 overlayfs、支持 ext4 image 的模块挂载能力。查看当前激活的 Metamodule在 KernelSU Manager 应用的模块页面可以查看当前激活的 metamodule。激活的 metamodule 会以特殊标识显示在模块列表中。源码层面ksud通过 metamodule.rs 中的get_metamodule_path()定位激活的 metamodule优先解析/data/adb/metamodule符号链接指向的目录若符号链接缺失或失效则回退扫描/data/adb/modules/下所有模块的module.prop查找metamodule1的模块。卸载 Metamodule警告卸载 metamodule 将影响所有模块。卸载后所有普通模块将不再被挂载直到安装另一个 metamodule。卸载步骤打开 KernelSU Manager在模块列表中找到 metamodule点击卸载此时会看到特殊警告提示确认操作重启设备。卸载后如果希望模块继续工作必须安装另一个 metamodule。卸载流程对应源码 module.rs 中的处理若卸载的是 metamodule则调用metamodule::remove_symlink()移除/data/adb/metamodule符号链接若卸载的是普通模块则先执行 metamodule 提供的metauninstall.sh清理钩子。单实例限制与切换流程同一时间只能安装一个 metamodule。如果尝试安装第二个KernelSU 会阻止该安装以避免冲突。安装流程中会调用 metamodule.rs 的check_install_safety()并在检测到已有 metamodule 时直接终止安装提示用户先卸载当前 metamodule。切换 metamodule 的推荐流程卸载所有普通模块卸载当前的 metamodule重启安装新的 metamodule重新安装普通模块再次重启。模块开发者视角如果你开发的是普通 KernelSU 模块无需为 metamodule 操心。只要用户安装了兼容的 metamodule如meta-overlayfs你的模块就能正常工作。需要了解的两点挂载依赖 metamodule模块中的system目录只有在用户安装了提供挂载功能的 metamodule 时才会被挂载无需修改代码已有模块无需任何改动即可继续工作。提示如果你熟悉 Magisk 模块开发那么安装了 metamodule 的 KernelSU 中你的模块将以完全相同的方式工作——因为 metamodule 提供了兼容 Magisk 的挂载。Metamodule 开发者指南创建 metamodule 可以完全自定义 KernelSU 处理模块安装、挂载和卸载的方式。基本要求module.propmetamodule 通过在module.prop中加入特殊属性来标识idmeta-example nameMy Custom Metamodule version1.0 versionCode1 authorYour Name descriptionCustom module mounting implementation metamodule1关键要求metamodule1或metamoduletrue属性将该模块标记为 metamodule。缺少此属性时模块按普通模块处理——这正是 metamodule.rs 中is_metamodule()的判定逻辑命名约定强烈建议 metamodule 的 ID 以meta-开头如meta-overlayfs、meta-magicmount、meta-custom便于用户识别也避免与普通模块产生命名冲突。文件结构一个 metamodule 的典型目录结构meta-example/ ├── module.prop (必须包含 metamodule1) │ │ *** Metamodule 专属 Hook *** ├── 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 (metamodule 自身的卸载脚本) └── [其他任意附加文件]metamodule 除了使用专属 hook 外还可以使用所有标准模块特性生命周期脚本等。三个 Hook 脚本详解metamodule 最多可以提供三个特殊 hook 脚本。对应脚本文件名在 defs.rs 中定义为常量metamount.sh、metainstall.sh、metauninstall.sh。1. metamount.sh —— 挂载处理器作用控制模块在启动过程中的挂载方式。执行时机post-fs-data阶段在所有模块脚本运行之前准确顺序见下文启动执行顺序。源码 init_event.rs 在加载完system.prop后调用metamodule::exec_mount_script()late_load.rs 中同样会在加载流程中执行 metamodule 挂载脚本随后进入post-mount阶段。环境变量MODDIRmetamodule 的目录路径如/data/adb/modules/meta-example所有标准 KernelSU 环境变量。从源码看exec_mount_script()还会额外注入MODULE_DIR环境变量指向被挂载模块的根目录并通过 busyboxsh执行脚本。职责systemless 挂载所有已启用的模块检查skip_mount标志处理模块特殊的挂载需求。关键要求执行挂载操作时必须将 source/device 名称设置为KSU以此标识该挂载属于 KernelSU。正确示例overlay 挂载mount -t overlay -o lowerdir/lower,upperdir/upper,workdir/work KSU /target现代 mount API 下设置 source 字符串fsconfig_set_string(fs, source, KSU)?;这一点至关重要——KernelSU 内核的 umount 逻辑与 zygisksu 的 umount 逻辑都依赖该标识才能正确卸载挂载。示例脚本简单 bind mount 实现#!/system/bin/sh MODDIR${0%/*} # 示例简单 bind mount 实现 for module in /data/adb/modules/*; do if [ -f $module/disable ] || [ -f $module/skip_mount ]; then continue fi if [ -d $module/system ]; then # 使用 sourceKSU 挂载必需 mount -o bind,devKSU $module/system /system fi done2. metainstall.sh —— 安装钩子作用定制普通模块的安装过程。执行时机模块安装期间文件解压之后、安装完成之前。该脚本由内置安装器source而非直接执行与customize.sh的工作方式类似。源码层面metamodule.rs 的get_install_script()展示了其拼接逻辑安装普通模块时若检测到已激活的 metamodule 且存在metainstall.sh则将其内容拼接到内置安装器脚本之后、exit 0之前组合执行若 metamodule 被禁用存在disable标记或没有metainstall.sh则回退使用默认安装器。继承的环境变量与函数来自内置install.sh变量MODPATH、TMPDIR、ZIPFILE、ARCH、API、IS64BIT、KSU、KSU_VER、KSU_VER_CODE、KSU_UAPI_VER、KSU_RUNTIME_MODE、KSU_LATE_LOAD、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移动模块文件校验模块兼容性准备特殊的目录结构初始化模块专属资源。注意安装 metamodule 自身时不会调用此脚本——get_install_script()对is_metamodule为真的情况直接返回默认安装器。3. metauninstall.sh —— 清理钩子作用卸载普通模块时清理相关资源。执行时机模块卸载期间模块目录被删除之前。源码 module.rs 的卸载流程会先调用metamodule::exec_metauninstall_script(module_id)失败仅告警不阻断卸载。环境变量MODULE_ID正在被卸载的模块 ID由 metamodule.rs 的exec_metauninstall_script()注入。使用场景处理文件清理符号链接释放已分配的资源更新内部跟踪记录。示例脚本#!/system/bin/sh # 卸载普通模块时被调用 MODULE_ID$1 IMG_MNT/data/adb/metamodule/mnt # 从 image 中删除模块文件 if [ -d $IMG_MNT/$MODULE_ID ]; then rm -rf $IMG_MNT/$MODULE_ID fi启动执行顺序理解启动执行顺序对 metamodule 开发至关重要。下面顺序与源码 init_event.rs 及run_stage()init_event.rs的实现相互印证post-fs-data 阶段: 1. 执行通用 post-fs-data.d 脚本 2. Prune 模块、restorecon、加载 sepolicy.rule 3. 执行 metamodule 的 post-fs-data.sh若存在 4. 执行普通模块的 post-fs-data.sh 5. 加载 system.prop 6. 执行 metamodule 的 metamount.sh └─ systemless 挂载所有模块 7. post-mount.d 阶段运行 - 通用 post-mount.d 脚本 - metamodule 的 post-mount.sh若存在 - 普通模块的 post-mount.sh service 阶段: 1. 执行通用 service.d 脚本 2. 执行 metamodule 的 service.sh若存在 3. 执行普通模块的 service.sh boot-completed 阶段: 1. 执行通用 boot-completed.d 脚本 2. 执行 metamodule 的 boot-completed.sh若存在 3. 执行普通模块的 boot-completed.sh要点metamount.sh在所有post-fs-data 脚本包括 metamodule 和普通模块的之后运行metamodule 的生命周期脚本post-fs-data.sh、service.sh、boot-completed.sh始终先于普通模块脚本执行.d目录中的通用脚本先于 metamodule 脚本执行post-mount阶段在挂载完成后运行。符号链接机制安装 metamodule 后KernelSU 会创建符号链接/data/adb/metamodule - /data/adb/modules/metamodule_id这为访问激活的 metamodule 提供了与 ID 无关的稳定路径。源码 metamodule.rs 的ensure_symlink()在安装时创建该链接先清理旧的符号链接或目录再重建卸载时由remove_symlink()移除。该路径对应 defs.rs 中的METAMODULE_DIR常量/data/adb/metamodule/。收益一致的访问路径易于检测激活的 metamodule简化配置。真实世界示例meta-overlayfsmeta-overlayfs是官方参考实现展示了 metamodule 开发的最佳实践。双目录架构meta-overlayfs采用双目录架构元数据目录/data/adb/modules/存放module.prop、disable、skip_mount标记启动时扫描快速存储占用小。内容目录/data/adb/metamodule/mnt/存放模块的实际文件system、vendor、product 等存储在 ext4 imagemodules.img中利用 ext4 特性优化空间。对应到源码普通模块的system目录只有在存在且未标记skip_mount时才需要挂载见 module.rs 中need_mount的判定path.join(system).exists() !path.join(skip_mount).exists()而 metamodule 通过metamount.sh读取这些元数据并完成实际挂载。metamount.sh 实现以下是meta-overlayfs的挂载处理器实现方式#!/system/bin/sh MODDIR${0%/*} IMG_FILE$MODDIR/modules.img MNT_DIR$MODDIR/mnt # 若尚未挂载则挂载 ext4 image 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 实现真正的 systemless 修改支持多分区system、vendor、product、system_ext、odm、oem通过/data/adb/modules/.rw/提供读写层支持。来源标识// 来自 meta-overlayfs/src/mount.rs fsconfig_set_string(fs, source, KSU)?; // 必需这为所有 overlay 挂载设置了devKSU实现正确的挂载标识与管理。最佳实践开发 metamodule 时请注意始终将 source 设置为 KSU—— 内核 umount 与 zygisksu umount 依赖此标识才能正确卸载妥善处理错误—— 启动流程对时间敏感尊重标准标志—— 支持skip_mount和disable记录操作日志—— 使用echo或日志输出便于调试充分测试—— 挂载错误可能导致开机循环boot loop文档化行为—— 清晰说明你的 metamodule 做了什么提供迁移路径—— 帮助用户从其他方案切换过来。测试你的 Metamodule发布之前建议在全新的 KernelSU 环境中测试安装用多种类型的模块验证挂载检查兼容性与常见模块配合测试卸载与清理流程验证启动性能注意metamount.sh是阻塞执行的确保错误处理正确避免开机循环。常见问题FAQ我需要 metamodule 吗普通用户仅当你想使用需要挂载的模块时才需要。如果只用只运行脚本、不修改系统文件的模块则不需要模块开发者不需要你正常开发模块即可。只有当你的模块需要挂载时用户才需要 metamodule进阶用户仅当你想定制挂载行为或打造替代挂载实现时才需要。可以同时安装多个 metamodule 吗不可以。同一时间只能安装一个 metamodule这避免了冲突并保证行为可预测。安装流程在检测到已有 metamodule 时会拒绝安装见 module.rs 安装逻辑。卸载唯一的 metamodule 会发生什么模块将不再被挂载。设备会正常开机但模块的修改不会生效直到你安装另一个 metamodule。meta-overlayfs 是必需的吗不是。它提供与大多数模块兼容的标准 overlayfs 挂载。如果你需要不同的行为完全可以创建自己的 metamodule。参见模块开发指南 —— 通用模块开发KernelSU 与 Magisk 的差异 —— 对比 KernelSU 与 Magisk另可参考仓库内印尼语原版文档 website/docs/id_ID/guide/metamodule.md以及源码 userspace/ksud/src/metamodule.rs 与 userspace/ksud/src/init_event.rs 获取更底层的实现细节。【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考