从软件工程的角度,谈模块为什么总是不兼容

news/2024/11/28 13:53:48/文章来源:https://www.cnblogs.com/oldsaltfish/p/18570812

前言

今天刚刷上Apatch,发现其没有提供Zygisk,又去酷安搜了一搜,似乎有人反应刷Lsposed不起作用,大致了解了一下,并查了些资料。下面我开始猜测以及进行理论。
说是从软件工程出发,但是实际上我并不算一个好学生,更无法代表软件工程,这或许很标题党,但是我确实想以这个名称命名。

一言蔽之,Apatch和KernelSu之类的本来就只是Root解决方案,只不过Magisk太流行了,如果不对magisk模块进行一些兼容,没人会去使用KernelSu之类的软件。事实上直到如今,Root管理器中占有率最高的依然是面具。

铺垫

在此之前,我们可以说一说接口和继承这个老生常谈的问题。当然,我无法代表软件工程,所有的见解只是个人思考和猜测,甚至很可能出现大量错误,权当我胡说,当个笑话看看就好。
我说说我对接口和继承的简单理解。
继承:"普通人类和机器人都是人"。
接口:"小米手机和OPPO手机都是手机"。

这个例子也许不是很好,我其实在尽力地使这篇文章变得有趣起来,我想表达的是,继承通常是允许扩展的,允许添加新功能的,而接口我们通常不允许扩展,该有什么功能就应该实现什么功能。至于怎么实现和如何实现,我不管你。

从代码的编写上来说,继承通常是允许新的方法出现的,他允许子类(派生类)拥有其他子类未拥有的方法,大家可以有非常多的不同点。
而接口不同,我们通常实现接口都是只实现接口所约定的方法,而不去写新的方法,除非我们让这个类去同时实现另一个接口。或者换句话来说,接口不关心其他的方法。

对于不熟悉代码的同学,我们可以简单的把接口理解为功能,而父类子类简单理解为父与子。

事实上接口完全允许其他的方法存在,但是大家都不太会去为一个实现了接口的类实现接口之外的方法。原因也很简单,因为单一职责原则

为什么

说到这里,我的用意就很明显了,各个root管理器更像是继承了某个父类的不同子类,而非实现接口。

其实既不是继承也不是接口,因为他们的开发者本就不同,根本就没有进行约定的义务,他们爱写什么写什么,你管不着。

早期,我们只希望拥有root管理器,SuperSu就是这个需求的一种实现。
image

后来,supersu不更新了,不支持新的系统,于是magisk出现了。
很遗憾我并不清楚magisk的完整历史,但是假设magisk初期就提供了模块化支持。(至少我接触的时候就已经有模块了)
模块是个好东西,magisk出现就占据了大量市场,大家都对magisk赞不绝口。
此时我们再假设,假如历史长河中,出现了一款名为UltraSu(neta SuperSu)的软件,他提供插件化支持,就像浏览器插件那样。由于二者出现时间相近,而当时大家的需求是root,从来没想过模块的问题。
那么magisk模块和UltraSu互不兼容就是可以预想的事情了,到这里我的核心思想已经表现出来了。你自然可以丢下这篇文章不管。

不过我可要继续说下去了。
大家都知道,根本没有UltraSu这个东西,至少有很长一段时间,大家都在使用magisk而不是什么别的管理器。
magisk也衍生出了别的版本,广为人知的就是Alpha和Delta(现在叫kitsume)。
vvb2060https://github.com/vvb2060
Alpha的作者自不必多说,我认识面具的时候隐隐约约就知道他是面具的维护者之一,而且他还是Lsposed的维护者。
image
那么兼容性好是可以预见的。
delta我其实不太清楚,无论如何,兼容性应该也不会比Alpha好。

如果再说回前面的继承和接口,这俩就类似继承,他们从magisk分支出来,提供了新的功能。

扯远了,让我们再拉回时间线,现在magisk火的一塌糊涂,在那之前,还有一款软件也很火爆。

xposed

我不太清楚xposed是什么时候流行起来的(远古级xp模块上帝模式,他在这个时期非常受欢迎,哪怕是edxp时期),但是这对本文没什么影响。我们假设xposed和magisk是近乎同时流行的。(印象中xposed更早)
这时,magisk和xposed还是互不相干的两个项目。发展了一段时间,大家的需求变成了root以及xposed模块,由于magisk的流行,大家也离不开magisk模块了。
这时候大家的需求如下:
0. 不修改system(最早由面具实现了)

  1. root(SuperSu时期就已经实现,更早的不考虑)
  2. xposed模块
  3. magisk模块
  4. 隐藏root等一系列环境?
    于是,不知何时,EdXposed出现了。
    项目地址
    https://github.com/ElderDrivers/EdXposed
    他的出现主要解决的问题就是,如何在不修改系统的情况下,使用xposed框架。至于系统兼容性是顺带解决的,EdXposed通过刷入Ruri模块(提供运行环境),实现了Xposed框架实现的功能,与此同时,由于模块不修改系统,需求完美地解决了。

其实这时候我才初步接触Xposed。至少当我认识Edxp的时候,他已经是使用模块的方式安装了,早期xposed是用installer安装的,和magisk没有什么交集。

Edxp同样非常流行,可以说是一统江湖,直接替代了xposed。
印象中,SuperSu+Xposed -> Magisk + Edxposed。
而后某一天,LSPosed出现了,他的出现让人意外,因为他的出现不是由市场催生的,而是由社区呼吁而成。(还是仅为猜测)
EdXposed和原来的Xposed都存在一个问题,无论目标应用是否正在运行,xposed的环境都会注入,这会导致性能问题,因此,Lsposed实现了作用域功能,使得模块仅对某些应用生效。

我合理地进行猜测,早期Lsposed使用Ruri提供环境注入。(官方术语为zygote)
而后期,Magisk项目提供了Zygisk(zygote注入的一种实现,Zygisk的目的是隐藏Root环境,也就是MagiskHide),于是Lsposed也去适配Zygisk。

下图为Lsposed在github的更新日志,
image
再后来,Magisk的作者topjohnwu https://github.com/topjohnwu
他被谷歌收编,虽然能够继续开发Magisk,但是似乎不被允许更新Zygisk。
相近地,KernelSu等框架横空出世,他们没有Zygisk之类的注入环境,如果用户需要使用Lsp等xp框架,KernelSu没有办法。
这也是Zygisk Next https://github.com/Dr-TSNG/ZygiskNext 出现的原因

作者
https://github.com/Dr-TSNG
(他曾参与Lsposed的开发)
下面这张图是开了网页翻译(考虑到文章的可读性)
image

他的出现间接地帮助了所有的Root管理器(除了死去的SuperSu),因为早期的Ruri https://github.com/RikkaApps/Riru 已经不更新了。
image

大规模弃更事件

而且,由于一些众所周知的令人气愤而又无奈的原因,Lsposed团队的多个项目也不再更新(归档了)。

也许有人不明白不再更新的意义是什么。我说一个最浅显的表现,这些项目将很有可能不能在较新的机型上使用,比如如今的Android15机型

可以说这个事件造成了非常坏的影响,祸不单行,小米很快更新了解锁的条件,具体是什么大家都清楚。

时间先后我记不得了,我只记得这两件事发生的时间很近,不超过一年。

我知道有很多人会说,哪怕没有这些开发者,也会有Root的实现。没有SuperSu,也会出现UltraSu;没有Ruri,也会有Zygisk。你看Zygisk Next不是出现了吗。

那我确实没法反对,根据客观规律,有需求就有市场,上面这段话是对的。但是这种话是最不该对Lsposed团队说的,因为Lsposed是被社区推动的,可以说近乎是浪漫的产物;同时期下EdXposed依然在被使用,他们完全可以不开发这个东西。

可以看到,EdXposed并没有归档,只是不再更新了
image
为什么不更新呢?因为显而易见,别人的项目Lsposed更好,维护EdXposed没有意义了。几个EdXposed的维护者全跑去更新Lsposed了。

假如EdXposed还在维护,你会去用Lsposed吗?

题外话

如果你细心观察,你会发现,搞root框架和相关的环境的维护者,来回就那么几个。
如果你说搞这些项目是为了给自己镀金。
人家招聘的问你会什么,你说你参与开发了Magisk,我听着都想笑。
所有手机厂商都是不鼓励你root的,因为用户的权利和厂商的权利往往站在对立面。
我开发一个软件,如果我想让他按照我预想中的执行,最好的办法就是用户什么都干不了,用户的权限越大我的风险就越高,我不让解锁了。维护的版本越多bug就越多,那我强制更新不就好了。(很多软件的做法)

因此显然,鼓捣这些东西去工作时没什么用的。而且说难听点,项目维护很大程度上都是体力活,费时间而没有什么技术含量。

回到正题

我们再拉回时间线。现在magisk依然如火如荼,Lsp依然如日中天(因为Android15并未普及),这两者的出现都是一统江湖的,没什么竞争对手。(在当时)
而现在,出现了KernelSu和Apatch这两个竞争者,我们可以重新梳理一下当前用户的需求。

Root

除了SuperSu,这几款软件都实现了Magisk模块

  1. SuperSu(不再更新)
  2. Magisk
    https://github.com/topjohnwu/Magisk
  3. KernelSu(作者是太极和虚拟框架的作者weishu)
    https://github.com/tiann/KernelSU
  4. Apatch
    https://github.com/bmax121/APatch

提供Zygote注入环境

现在Zygote注入实现只剩下Zygisk方式了,不出意外以后不会再有Ruri

  1. Magisk官方提供的Zygisk以及MagiskHide(已经过时)
  2. Ruri(EdXp时期,以及Lsp的前期)
    https://github.com/RikkaApps/Riru
    叫琉璃的人太多,猜不出来是谁,或许只是一个泛称
  3. Zygisk Next(唯一幸存者)
    https://github.com/Dr-TSNG/ZygiskNext

隐藏Root(隐藏注入器)

我不太清楚Zygisk什么时候出现的。
KernelSu和Apatch都实现了隐藏su(也就是Root),但是如果你使用了Zygisk(Zygote注入的实现),你还需要隐藏Zygisk。

  1. Zygisk环境下,使用MagiskHide(自带,停止更新)
  2. Shamiko(MagiskHide的一种实现?停止更新)

Shamiko借用的依然是官方Magisk的配置排除列表,需要Zygisk环境,默认是黑名单模式,也就是对列表中的应用隐藏Root。
Shamiko应该是夏美子,街角魔族的主角。(没人比我更懂二次元.jpg)
image

  1. MagiskHide模块?(我没用过)
  2. 其他的,有很多,但我不太了解......

Xposed模块实现/管理器

除了早期的Xposed Installer,这些必须有Zygote注入环境

  1. Xposed Installer和Manager(过时)
  2. Edxposed(过时)
    https://github.com/ElderDrivers/EdXposed
  3. Lsposed(停止维护)
    https://github.com/LSPosed
  4. Lsposed Mod(下一代)
    https://github.com/mywalkb/LSPosed_mod

回到正题

虽然很简单,但是我讲了一大堆(而且很乱)。
兼容性最强的自然是各个实现只实现它本该实现的功能。
但是我们先说说兼容性最差的情况,假设某个zip直接包含了全部的环境(以上的全部需求),是不是很强很方便?但是,首先没有人有这么大的精力去整合所有项目,其次,如果集成在一起,你如何知道哪个部分出了问题?
我们再说兼容性最强的方案,假设每个功能都以单独模块出现,那其实也很糟糕,假设Magisk分成了多个部分,比如把Root管理和模块管理分离,再把排除应用列表分离。那么你从前卡刷面具这一步,就会复杂成刷好几个模块,安装好几个应用。
其次,假设你只实现了Root管理,我凭什么用你Magisk?一个应用只有解决了某个需求才会有人去用,才有意义,假设许多应用都只干同一件事,那么想要获得用户只能靠宣发了。而开源应用和宣发基本上沾不上边,因为宣发是要钱的。搞开源已经很费钱了(时间也是钱),哪来的钱搞宣发。

还有一个原因,Magisk本身也在积极地更新,假如某个模块使用了Magisk的新功能,自然会存在不兼容Apatch和KernelSu。(而且Apatch之类的和Magisk的环境也不同,而之前的模块都是以Magisk环境为准的)
而Apatch和KernelSu如果花时间去兼容Magisk,完全是不务正业,而且吃力不讨好,因为旧的写法通常比新的多,为了5%的模块去花50%的时间并不值得。

所以这个问题无解,除非Magisk模块功能被单独实现,但是这就更不可能了,因为Magisk的核心功能就是模块,他是用模块来解决问题的,倒不如说Root才是顺带的。

原谅我长篇大论一大堆说了这么些浅显的道理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/841900.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uml用例图-2024/11/26

超市进销存管理系统

MySQL报错:sql_mode=only_full_group_by解决方法

MySQL报错:sql_mode=only_full_group_by解决方法 登录mysql之后,执行命令查看当前的sql_mode配置 select @@global.sql_mode;​​ 可以发现MySQL的sql_mode是开启了ONLY_FULL_GROUP_NY。 解决方法 把 sql_mode 中的 ONLY_FULL_GROUP_NY​去掉,其他不变即可。 找到MySQL的配置…

使用Lombok导致打印的tostring中缺少父类的属性

背景 实体类UserDto extends BaseEntity,两个类的上方都有标注,Lombok的@Data注解,但是使用时UserDto的实例对象调用toString方法时发现,只打印出来自身子类的属性信息,并没有打印出来父类的信息。@Data public class UserDto extends BaseEntity { /*** 姓名*/@TableFiel…

20222322 2024-2025-1 《网络与系统攻防技术》实验五实验报告

1.实验内容 1.1实验要求 (1)从www.besti.edu.cn、baidu.com、sina.com.cn中选择一个DNS域名进行查询,获取相关信息。 (2)尝试获取BBS、论坛、QQ、MSN中某一好友的IP地址,并查询获取该好友所在的具体地理位置。 (3)使用nmap开源软件对靶机环境进行扫描,回答以下问题并给…

华为鸿蒙智家品牌升级背后:开拓者,引领者,赋能者

今天,华为重磅推出全新品牌“华为鸿蒙智家”亮相华为Mate品牌盛典。 华为作为产业的开拓者,一直引领产业进化,带动产业从懵懂到成熟。这一次品牌升级将借势鸿蒙,为空间智能产业打开更大的想象空间。持续进化,带来更高阶的智感 作为一个热门赛道,科技巨头和家电企业均积极…

Threejs的三维坐标系

在三维空间中,所有的物体和相机都需要基于一个统一的坐标系来进行定位和操作。理解坐标系的基本概念,对于创建稳定、准确的三维效果至关重要。 基础 Three.js 采用的是右手坐标系,这意味着如果你将右手的三个手指伸直,分别指向 X、Y 和 Z 轴的方向,你的拇指指向的方向即为…

图像尺寸变换scalepadding方法

在深度学习中,当需要将图像调整到特定尺寸时,直接resize可能会导致图像失真,特别是当目标尺寸与原始图像的宽高比不一致时。为了解决这个问题,一种最常见的方法是首先按照原始图像的宽高比将图像调整到与目标尺寸最接近的尺寸,然后在剩余的空间中使用padding进行填充,以得…

笔记本电脑复活记

0.前言 一次偶然的停电让我蒙受了巨大的损失。恢复供电之后发现笔记本电脑无法正常启动,经检查发现硬盘坏了。经过检查确认是硬件坏了,但没有损伤盘片。决定通过数据恢复拯救损失的数据。与此同时,电脑的散热风扇已经响了很久了,决定这一次也更换了它。 经过几天的折腾,笔…

某水准测量工具 vb6 程序注册分析

某水准测量工具 vb6 程序注册分析 目录某水准测量工具 vb6 程序注册分析文件信息VB Decompiler Pro注册点击事件 Command1_ClickRJZC.UncrypStrpypsvb 程序,接触不多,仅作记录文件信息 PE32操作系统: Windows(95)[I386, 32 位, GUI]链接程序: Microsoft Linker(6.0)编译器: M…

WinUI(WASDK)使用BotSharp框架开发多智能体桌面机器人管理助手(生图开关灯不在话下)

前言 大语言模型(Large Language Models, LLMs)近年来在各行各业中展现出了巨大的潜力和影响力。从自然语言处理到自动化客服,从内容生成到智能助手,LLMs正在改变我们与技术互动的方式。随着技术的不断进步,LLMs的应用场景也在不断扩展,成为未来发展的重要趋势。这篇文章…

【C++编程】五个分区: 堆、栈、静态(全区)区、 常量区 代码区

在C++中,程序的内存管理被分为几个区域,这些区域每个都有其特定的用途。下面是你提到的五个分区的详细描述: 一、栈区(Stack) 用途:用于存储局部变量和函数调用时的上下文(如返回地址与参数等)。 特点: 采用先进后出(LIFO)原则进行管理。 内存由编译器自动分配和释放…

突破自我

1.寻找红利 红利大抵有以下几种:城市红利、行业红利、时代红利。 城市红利,一个高速发展、人口长期净流入的城市就有城市红利,城市红利主要体现在两点:房产、认知信息、人脉差。有红利的城市在过去20年房价一路向上,安家了基本就等于资产不断升值。有红利的城市带来的认知…