KernelSU Metamodule(元模块)完全指南:架构原理、三个 Hook 脚本开发与 meta-overlayfs 参考实现
2026/9/13 12:48:37 网站建设 项目流程

KernelSU Metamodule(元模块)完全指南:架构原理、三个 Hook 脚本开发与 meta-overlayfs 参考实现

【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU

Metamodule(元模块)是 KernelSU 引入的一种插件化扩展机制:它将传统 root 方案内置在守护进程核心中的模块安装/挂载逻辑,抽离为可独立安装、可替换的特殊模块。本文以官方文档为主线,结合ksud守护进程源码,系统讲解 metamodule 的设计动机、用户操作流程、hook 脚本开发规范、启动执行顺序,以及官方参考实现meta-overlayfs的架构细节,帮助普通用户正确使用、模块开发者理解兼容性边界、进阶开发者写出可上线的自定义 metamodule。

什么是 Metamodule

Metamodule 是一种特殊的 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-overlayfs);
  • Magic mount:兼容 Magisk 的挂载方式,应用兼容性更好;
  • 自定义实现:基于 FUSE 的 overlay、自定义 VFS 挂载,或全新的方案。

超越挂载本身的价值:

  • 可扩展:无需修改 KernelSU 核心即可添加内核模块支持等新特性;
  • 模块化:挂载实现可以独立于 KernelSU 版本单独更新;
  • 定制化:可为特定设备或特定场景打造专用解决方案。

重要提示:如果没有安装 metamodule,普通模块将不会被挂载。全新安装的 KernelSU 必须安装一个 metamodule(如meta-overlayfs)才能使模块生效。

用户指南

安装 Metamodule

安装 metamodule 的方式与安装普通模块完全相同:

  1. 下载 metamodule 的 ZIP 文件(例如meta-overlayfs.zip);
  2. 打开 KernelSU Manager 应用;
  3. 点击悬浮操作按钮(➕);
  4. 选择 metamodule 的 ZIP 文件;
  5. 重启设备。

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,查找metamodule=1的模块。

卸载 Metamodule

警告:卸载 metamodule 将影响所有模块。卸载后,所有普通模块将不再被挂载,直到安装另一个 metamodule。

卸载步骤:

  1. 打开 KernelSU Manager;
  2. 在模块列表中找到 metamodule;
  3. 点击卸载(此时会看到特殊警告提示);
  4. 确认操作;
  5. 重启设备。

卸载后,如果希望模块继续工作,必须安装另一个 metamodule。卸载流程对应源码 module.rs 中的处理:若卸载的是 metamodule,则调用metamodule::remove_symlink()移除/data/adb/metamodule符号链接;若卸载的是普通模块,则先执行 metamodule 提供的metauninstall.sh清理钩子。

单实例限制与切换流程

同一时间只能安装一个 metamodule。如果尝试安装第二个,KernelSU 会阻止该安装以避免冲突。安装流程中会调用 metamodule.rs 的check_install_safety(),并在检测到已有 metamodule 时直接终止安装,提示用户先卸载当前 metamodule。

切换 metamodule 的推荐流程:

  1. 卸载所有普通模块;
  2. 卸载当前的 metamodule;
  3. 重启;
  4. 安装新的 metamodule;
  5. 重新安装普通模块;
  6. 再次重启。

模块开发者视角

如果你开发的是普通 KernelSU 模块,无需为 metamodule 操心。只要用户安装了兼容的 metamodule(如meta-overlayfs),你的模块就能正常工作。

需要了解的两点:

  • 挂载依赖 metamodule:模块中的system目录只有在用户安装了提供挂载功能的 metamodule 时才会被挂载;
  • 无需修改代码:已有模块无需任何改动即可继续工作。

提示:如果你熟悉 Magisk 模块开发,那么安装了 metamodule 的 KernelSU 中,你的模块将以完全相同的方式工作——因为 metamodule 提供了兼容 Magisk 的挂载。

Metamodule 开发者指南

创建 metamodule 可以完全自定义 KernelSU 处理模块安装、挂载和卸载的方式。

基本要求:module.prop

metamodule 通过在module.prop中加入特殊属性来标识:

id=meta-example name=My Custom Metamodule version=1.0 versionCode=1 author=Your Name description=Custom module mounting implementation metamodule=1

关键要求:

  • metamodule=1(或metamodule=true)属性将该模块标记为 metamodule。缺少此属性时,模块按普通模块处理——这正是 metamodule.rs 中is_metamodule()的判定逻辑;
  • 命名约定:强烈建议 metamodule 的 ID 以meta-开头(如meta-overlayfsmeta-magicmountmeta-custom),便于用户识别,也避免与普通模块产生命名冲突。

文件结构

一个 metamodule 的典型目录结构:

meta-example/ ├── module.prop (必须包含 metamodule=1) │ │ *** 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.shmetainstall.shmetauninstall.sh

1. metamount.sh —— 挂载处理器

作用:控制模块在启动过程中的挂载方式。

执行时机post-fs-data阶段,在所有模块脚本运行之前(准确顺序见下文"启动执行顺序")。源码 init_event.rs 在加载完system.prop后调用metamodule::exec_mount_script();late_load.rs 中同样会在加载流程中执行 metamodule 挂载脚本,随后进入post-mount阶段。

环境变量

  • MODDIR:metamodule 的目录路径(如/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 # 使用 source=KSU 挂载(必需!) mount -o bind,dev=KSU "$module/system" /system fi done
2. metainstall.sh —— 安装钩子

作用:定制普通模块的安装过程。

执行时机:模块安装期间,文件解压之后、安装完成之前。该脚本由内置安装器source(而非直接执行),与customize.sh的工作方式类似。

源码层面,metamodule.rs 的get_install_script()展示了其拼接逻辑:安装普通模块时,若检测到已激活的 metamodule 且存在metainstall.sh,则将其内容拼接到内置安装器脚本之后、exit 0之前组合执行;若 metamodule 被禁用(存在disable标记)或没有metainstall.sh,则回退使用默认安装器。

继承的环境变量与函数(来自内置install.sh):

  • 变量MODPATHTMPDIRZIPFILEARCHAPIIS64BITKSUKSU_VERKSU_VER_CODEKSU_UAPI_VERKSU_RUNTIME_MODEKSU_LATE_LOADBOOTMODE等;
  • 函数
    • 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.shservice.shboot-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-overlayfs

meta-overlayfs是官方参考实现,展示了 metamodule 开发的最佳实践。

双目录架构

meta-overlayfs采用双目录架构

  1. 元数据目录/data/adb/modules/

    • 存放module.propdisableskip_mount标记;
    • 启动时扫描快速;
    • 存储占用小。
  2. 内容目录/data/adb/metamodule/mnt/

    • 存放模块的实际文件(system、vendor、product 等);
    • 存储在 ext4 image(modules.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 挂载设置了dev=KSU,实现正确的挂载标识与管理。

最佳实践

开发 metamodule 时请注意:

  1. 始终将 source 设置为 "KSU"—— 内核 umount 与 zygisksu umount 依赖此标识才能正确卸载;
  2. 妥善处理错误—— 启动流程对时间敏感;
  3. 尊重标准标志—— 支持skip_mountdisable
  4. 记录操作日志—— 使用echo或日志输出便于调试;
  5. 充分测试—— 挂载错误可能导致开机循环(boot loop);
  6. 文档化行为—— 清晰说明你的 metamodule 做了什么;
  7. 提供迁移路径—— 帮助用户从其他方案切换过来。

测试你的 Metamodule

发布之前,建议:

  1. 在全新的 KernelSU 环境中测试安装
  2. 用多种类型的模块验证挂载
  3. 检查兼容性(与常见模块配合);
  4. 测试卸载与清理流程;
  5. 验证启动性能(注意metamount.sh是阻塞执行的);
  6. 确保错误处理正确,避免开机循环。

常见问题(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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询