尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

KernelSU 元模块(Metamodule)完全指南:从概念到自定义挂载实现

KernelSU 元模块(Metamodule)完全指南:从概念到自定义挂载实现 KernelSU 元模块Metamodule完全指南从概念到自定义挂载实现【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU元模块Metamodule是 KernelSU 引入的插件化模块管理机制它将模块系统的安装与挂载核心逻辑从内核守护进程ksud中解耦交给一个可插拔的普通模块承担。本文基于官方文档并结合仓库内ksud的 Rust 源码userspace/ksud/src/metamodule.rs、userspace/ksud/src/init_event.rs 等逐层剖析元模块的识别方式、三个专用钩子脚本、启动执行顺序与meta-overlayfs参考实现帮助普通用户正确安装/卸载元模块也帮助模块开发者与高级用户编写属于自己的自定义挂载实现。什么是元模块元模块是一种特殊的 KernelSU 模块它为模块系统提供核心基础设施能力。与修改系统文件的普通模块不同元模块控制的是普通模块**“如何被安装”和“如何被挂载”**。从架构上看元模块是一种基于插件的扩展机制允许完全自定义 KernelSU 的模块管理基础设施。通过把挂载与安装逻辑委托给元模块KernelSU 自身不再执行任何挂载操作从而避免成为脆弱的检测点同时让多样化的实现策略成为可能。这一架构转变在维持 KernelSU 稳定性与安全性的同时释放了模块生态更大的创新空间。核心特征基础设施角色元模块提供普通模块所依赖的服务单实例约束同一时刻只能安装一个元模块优先执行元模块脚本总是先于普通模块脚本执行专用钩子提供安装、挂载、清理三个钩子脚本。这些特征在源码中有直接对应is_metamodule()通过读取module.prop中的metamodule属性来判定模块类型get_metamodule_path()通过/data/adb/metamodule符号链接定位当前激活的元模块而exec_mount_script、exec_metauninstall_script等函数则负责在对应时机调用钩子脚本见 userspace/ksud/src/metamodule.rs。为什么需要元模块传统 Root 解决方案把挂载逻辑内嵌在核心中既容易被检测也难以演进。KernelSU 的元模块架构通过关注点分离解决了这些问题。战略优势减少检测面KernelSU 自身不执行挂载检测向量随之减少稳定性核心守护进程保持稳定挂载实现可以持续演进创新空间社区无需 fork KernelSU 即可开发替代挂载策略用户选择权用户可以选择最适合自己需求的实现。挂载灵活性不挂载仅使用无挂载mountless模块的用户可以完全避免挂载开销OverlayFS 挂载支持读写层的传统方案通过meta-overlayfsMagic MountMagisk 兼容挂载以获得更好的应用兼容性自定义实现FUSE 覆盖层、自定义 VFS 挂载或完全新颖的方案。超越挂载本身可扩展性无需修改核心 KernelSU 即可增加内核模块支持等功能模块化实现可以独立于 KernelSU 版本更新定制化可以为特定设备或使用场景创建专用方案。::: warning 重要 如果未安装元模块模块将不会被挂载。全新的 KernelSU 安装需要先安装一个元模块如meta-overlayfs模块才能正常工作。 :::这一警告在源码中得到印证ksud 只有在检测到激活的元模块且存在metamount.sh时才会执行挂载脚本见 userspace/ksud/src/metamodule.rs 中的exec_mount_script其内部通过check_metamodule_script检查元模块是否存在、是否被禁用、脚本是否存在。面向普通用户元模块的安装与卸载安装元模块元模块的安装方式与普通模块完全一致下载元模块 ZIP 文件例如meta-overlayfs.zip打开 KernelSU Manager 应用点击悬浮操作按钮➕选择元模块 ZIP 文件重启设备。meta-overlayfs是官方参考实现提供基于 overlayfs、支持 ext4 镜像的模块挂载。查看当前激活的元模块打开 KernelSU Manager 的“模块”页面当前激活的元模块会以特殊标识显示在模块列表中可直接查看。卸载元模块::: danger 警告 卸载元模块会影响所有模块。移除后在安装另一个元模块之前所有模块都不会再被挂载。 :::卸载步骤打开 KernelSU Manager在模块列表中找到元模块点击卸载会显示特殊警告确认操作重启设备。卸载后如果希望模块继续生效需要安装另一个元模块。源码层面的卸载流程值得注意ksud 的prune_modules()见 userspace/ksud/src/module.rs在移除带remove标记的模块时会先判断该模块是否为元模块——若是元模块则调用remove_symlink()移除/data/adb/metamodule符号链接若是普通模块则先执行元模块的metauninstall.sh钩子再执行模块自身的uninstall.sh最后清理模块目录。单元模块约束与切换同一时间只能安装一个元模块。尝试安装第二个元模块时KernelSU 会阻止安装以避免冲突。这一逻辑实现在install_module_to_system中当检测到已存在元模块且其 ID 与待安装模块不同时直接以Cannot install multiple metamodules终止安装见 userspace/ksud/src/module.rs。切换元模块的步骤卸载所有普通模块卸载当前元模块重启安装新的元模块重新安装普通模块再次重启。面向模块开发者普通模块无需改动如果你在开发普通 KernelSU 模块基本无需关心元模块。只要用户安装了兼容的元模块如meta-overlayfs你的模块即可正常工作。需要知道的两点挂载依赖元模块模块中的system目录只有在用户安装了提供挂载能力的元模块时才会被挂载无需修改代码现有模块无需任何改动即可继续工作。::: tip 如果你熟悉 Magisk 模块开发那么在安装元模块后由于元模块提供了 Magisk 兼容挂载你的模块在 KernelSU 上的表现与在 Magisk 上一致。 :::从实现上看ksud 在安装普通模块时会调用get_install_script()若存在激活且未被禁用的元模块并且元模块目录下存在metainstall.sh则会把该脚本内容拼接到内置安装器脚本之后执行见 userspace/ksud/src/metamodule.rs。这意味着普通模块的安装流程本身就可能被元模块接管因此模块开发者应保持模块符合标准结构。面向元模块开发者自定义安装、挂载与卸载创建元模块可以自定义 KernelSU 处理模块安装、挂载和卸载的方式。基本要求module.prop 中的 metamodule 标记元模块通过module.prop中的特殊属性来标识idmeta-example nameMy Custom Metamodule version1.0 versionCode1 authorYour Name descriptionCustom module mounting implementation metamodule1关键要求metamodule1或metamoduletrue属性将该模块标记为元模块。缺少此属性时模块会被当作普通模块处理。源码中的判定逻辑为trimmed 1 || trimmed.eq_ignore_ascii_case(true)见 userspace/ksud/src/metamodule.rs命名约定强烈建议元模块 ID 以meta-开头例如meta-overlayfs、meta-magicmount、meta-custom这有助于用户识别元模块并避免与普通模块产生命名冲突。文件结构元模块的完整目录结构如下meta-example/ ├── module.prop (必须包含 metamodule1) │ │ *** 元模块专用钩子 *** ├── 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 (元模块自身的卸载脚本) └── [其他任意文件]元模块除了特殊的元模块钩子之外还可以使用所有标准模块功能生命周期脚本等。三个专用钩子脚本的文件名常量定义于 userspace/ksud/src/defs.rsmetamount.sh、metainstall.sh、metauninstall.sh。钩子脚本详解元模块最多可以提供三个专用钩子脚本。1. metamount.sh —— 挂载处理器用途控制模块在启动过程中如何被挂载。执行时机在post-fs-data阶段、所有模块脚本执行之后具体顺序见下文“执行顺序”。环境变量MODDIR元模块的目录路径例如/data/adb/modules/meta-example所有标准 KernelSU 环境变量。从源码看exec_mount_script(module_dir)还会额外注入MODULE_DIR环境变量指向模块目录见 userspace/ksud/src/metamodule.rs供挂载脚本确定需要挂载的模块集合。职责以 systemless 方式挂载所有已启用的模块检查skip_mount标记处理模块特有的挂载需求。::: danger 关键要求 执行挂载操作时必须将 source/device 名称设置为KSU以标识该挂载属于 KernelSU。示例正确mount -t overlay -o lowerdir/lower,upperdir/upper,workdir/work KSU /target对于新版挂载 API设置 source 字符串fsconfig_set_string(fs, source, KSU)?;这对于 KernelSU 正确识别和管理其挂载至关重要。 :::示例脚本#!/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 —— 安装钩子用途自定义普通模块的安装方式。执行时机模块安装期间文件解压之后、安装完成之前。与customize.sh的工作方式类似该脚本由内置安装器source导入执行而非独立执行。环境变量与函数脚本继承内置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移动模块文件校验模块兼容性建立特殊目录结构初始化模块专属资源。注意安装元模块自身时不会调用此脚本。这一行为在源码中有明确分支get_install_script()中当is_metamodule为真时直接使用默认安装器见 userspace/ksud/src/metamodule.rs。3. metauninstall.sh —— 清理钩子用途当普通模块被卸载时清理相关资源。执行时机模块卸载期间、模块目录被删除之前。环境变量MODULE_ID被卸载模块的 ID。源码中该变量通过.env(MODULE_ID, module_id)注入见 userspace/ksud/src/metamodule.rs。典型用途处理文件清理符号链接释放已分配的资源更新内部追踪记录。示例脚本#!/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启动执行顺序理解启动执行顺序对元模块开发至关重要。以下顺序与 userspace/ksud/src/init_event.rs 中post_fs_data的实现以及run_stage()的通用逻辑一致post-fs-data 阶段 1. 执行公共 post-fs-data.d 脚本 2. 清理prune模块、restorecon、加载 sepolicy.rule 3. 执行元模块的 post-fs-data.sh若存在 4. 执行普通模块的 post-fs-data.sh 5. 加载 system.prop 6. 执行元模块的 metamount.sh └─ 以 systemless 方式挂载所有模块 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阶段在挂载完成之后运行。这些顺序在源码中均有对应init_event.rs中依次调用exec_common_scripts(post-fs-data.d)→metamodule::exec_stage_script(post-fs-data)→module::exec_stage_script(post-fs-data)→load_system_prop()→metamodule::exec_mount_script(module_dir)而通用的run_stage()则统一执行“公共脚本 → 元模块阶段脚本 → 普通模块阶段脚本”三级顺序见 userspace/ksud/src/init_event.rs。值得注意的细节module::exec_stage_script()会通过canonicalize比较并跳过元模块目录本身避免元模块脚本被重复执行见 userspace/ksud/src/module.rs。符号链接机制安装元模块时KernelSU 会创建符号链接/data/adb/metamodule - /data/adb/modules/metamodule_id这为访问当前激活的元模块提供了稳定的路径无论其 ID 如何变化。优点一致的访问路径易于检测激活的元模块简化配置。该机制实现在ensure_symlink()与remove_symlink()中安装元模块后立即创建链接见 userspace/ksud/src/module.rs卸载时移除而get_metamodule_path()首先尝试解析该符号链接若链接失效则回退到在模块目录中扫描metamodule1属性见 userspace/ksud/src/metamodule.rs。实战范例meta-overlayfsmeta-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 实现真正的 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从而支持正确识别。最佳实践开发元模块时挂载操作始终将 source 设为 KSU—— 内核卸载kernel umount和 zygisksu 卸载依赖此标识才能正确卸载优雅处理错误—— 启动流程对时间敏感尊重标准标记—— 支持skip_mount和disable记录操作日志—— 使用echo或日志输出便于调试充分测试—— 挂载错误可能导致启动循环文档化行为—— 清楚说明元模块的功能提供迁移路径—— 帮助用户从其他方案切换。测试你的元模块发布之前在全新的 KernelSU 环境上测试安装用各种模块类型验证挂载检查与常见模块的兼容性测试卸载与清理验证启动性能metamount.sh是阻塞执行的确保正确的错误处理以避免启动循环。常见问题我需要元模块吗普通用户仅当你想使用需要挂载的模块时才需要。如果只使用运行脚本而不修改系统文件的模块则不需要元模块。模块开发者不需要你正常开发模块即可。只有当你的模块需要挂载时用户才需要元模块。高级用户仅当你想自定义挂载行为或创建替代挂载实现时才需要。可以安装多个元模块吗不可以。同一时间只能安装一个元模块这可以防止冲突并确保行为可预测。ksud 在安装阶段即对此进行拦截见 userspace/ksud/src/module.rs。卸载唯一的元模块会发生什么模块将不再被挂载。设备会正常启动但在安装另一个元模块之前模块的修改不会生效。meta-overlayfs 是必须的吗不是。它提供与大多数模块兼容的标准 overlayfs 挂载。如果你需要不同行为可以创建自己的元模块。延伸阅读模块指南 —— 通用模块开发与 Magisk 的区别 —— KernelSU 与 Magisk 对比若需深入源码可阅读 userspace/ksud/src/metamodule.rs元模块管理核心、userspace/ksud/src/init_event.rs启动事件与执行顺序、userspace/ksud/src/module.rs模块安装/卸载主流程以及 userspace/ksud/src/defs.rs路径与脚本名常量定义。【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表