不仅仅在操作系统层面,在整个IT行业,通用性和性能,一直都是天平的两端。硬件层面,通用的CPU,性能远不如各种专用的ASIC芯片;CPU内部,通用的整数指令性能远不如各种专用运算指令如浮点、SIMD、加解密等指令。软件层面,通常也是一个流程写到底,比多次调用各种通用的封装好的基础函数性能要好。
今天很多各种虚拟机语言如Java、.Net,脚本语言如PHP、Python,以及以HTML/CSS、XML、JavaScript结合的Web应用这类大量实时文本解析的技术普及,前提是今天的硬件性能比日常应用的性能需求高的多。我举个例子,大家今天依然很常用的一些系统操作、文档处理等应用,早了不说,其实和Win95+Office95,可以说90%常用功能一致的。Win95+Office95的硬件需求才多高?不说刚上市发布时的最低配置要求,哪怕后来相对普及时的主流硬件配置,不过奔腾MMX 166,32M内存。如果按照大家更熟悉也和今天体系更接近的Windows 2000+Office 2000,发布时很常见的奔腾3 733/800+128M内存也是跑得很流畅了。而今天的主流硬件性能,不说和老旧的奔腾MMX 166比,哪怕和奔腾3 800比,单核性能也少说提升十多二十倍,多核性能就更不用说了。
所以现在我们看到的操作系统没有“完全”屏蔽底层,为软件环境提供统一运行环境,具体来说是几个原因:
1、历史遗留。今天大家常见的操作系统都不算太年轻,毕竟开源的Linux成熟之后,想搞个操作系统自己定制改拨下,总比从头开发一个,解决各种硬件驱动问题要方便得多。而Linux是1991年开始开发,当时的主流硬件最新也就是486 33/50 MHz,并没有足够的性能余量去追求通用性。Java出现是1995年,开始流行是2000年之后,这个时候主流CPU主频已经突破1 GHz了,但这个时期,性能依然是阻碍Java普及的一大原因。
2、硬件性能还不够。对于文档处理这样的日常应用来说,今天的硬件性能是过剩了,可以去追求通用性,这也是今天很多系统、应用以Web APP形式出现的前提。但还有大量的多媒体创作、高性能计算以及多种需要处理大量数据运算、用户请求的企业应用仍然是性能渴求的。这些应用目前为止还无法以牺牲性能为代价去追求通用性,反而是为了性能还需要牺牲通用性,例如用类似汇编的intrinsics来编程。
3、x86在2005-2015年期间的强势。随着Intel在1998年推出至强,x86开始进入服务器市场。便宜的价格,加上集群技术的成熟,很多以前代表着高性能、高可用性的CPU,例如Alpha,SPARC,POWER等都被抢掉了相当部分市场,同时先进制程的芯片研发、生产成本越发高昂,这些CPU都在逐渐走向消亡——到了今天,仅仅剩下IBM的POWER凭着兼容性和高可用性、以及商业机构客户提供的高昂利润还在坚持。事实上,Windows NT一直到Windows 2000的BETA版,都是同时支持x86、Alpha、MIPS和PowerPC的,虽然还做不到题主所说的应用与硬件无关,但一份代码在多个平台上分别编译后运行是可能的。随着这些x86以外的指令集架构的CPU消亡,操作系统和其他软件开发商自然也没有动力去做跨硬件平台的工作——直到这几年ARM凭借低功耗在移动平台一枝独秀,加上智能手机、平板电脑这些移动设备的流行,快速迭代终于摸到了x86的尾巴,服务器市场、移动计算市场都出现了极少量的ARM设备,才又有了这种跨平台的需求出现。
因为慢。安卓的Java就是屏蔽了底层架构,为应用软件提供了统一的运行环境。但是,在安卓上跑游戏,用Java不够快,所以游戏厂商纷纷选择直接接触底层架构,用NDK/C/C++直接开发ARM原生库,然后挂接到Java中使用。有的游戏甚至整个引擎都是C/C++写的,Java只做为启动部分,加载完ARM原生库,绘图工作转移出去之后就不再有动作了,所有3D/绘图操作全部由ARM原生库完成,这样才能在手机上达到想要的性能。
当然,如果你愿意接受一半的续航、一半的帧数、两倍的发热,在安卓上直接用Java跑大型游戏也不是不可以。如果某个大型游戏是纯Java写的,没用任何原生库,那它就能百分之百与x86电脑上的安卓模拟器兼容。但是代价是什么呢?在手机上运行的时候,估计就只有旗舰机能勉强流畅游玩了,更低配的手机可能会直接卡成PPT。
不过,小游戏,特别是非3D游戏,完全没这种问题,Java显然能满足它们的性能需求。但如果他们最终没选择用Java开发,那么唯一的担心可能是:Java太容易破解了。而C/C++要破解起来就难很多,外挂的技术门槛就要更高。
备注:Kotlin也是Java虚拟机语言,在安卓内,和Java运行在同样的虚拟机里,所以上面所有对Java的表述也同样适用于Kotlin。
而Kotlin在iOS上是直接编译为目标平台机器码(比如ARM指令集),此时它就不符合题设条件了,换一种CPU就不能运行,所以不用考虑这种情况。
这其实是个伪命题。
操作系统给应用软件提供的API,本来就是统一运行环境。操作系统一直都在努力给软件提供一个统一的运行环境。他们确实是这样想的。
如果为x86Windows写的代码全都能在armWindows上面运行,微软开心不开心啊?当然开心,睡觉都要笑醒。——所以操作系统产商当然有动力提供统一运行环境。
但是呢?实际上应用软件的开发者有千千万万,需求有形形色色,人的行为总会有多样性。所以实际上他们做出的事情就不可预期。
举个例子:Android 系统。一开始就设计为使用java虚拟机,这,总该是非常统一的运行环境了吧?
然而实际上呢?由于有相当多的现有代码使用C或者C++开发,要复用这些代码必须使用NDK。另外就是,java虚拟机并没有提供足够完备的功能,比如串口通讯就必须依赖C写的库。jvm无法完成。
各种原因敦促了 android 必须开放NDK编译,然而NDK意味着,不同的CPU架构必定会生成不同的代码(除非是实时编译)。
为了解决这个问题,最常见的办法是:将所有可支持架构的编译结果都打包到程序中,程序运行的时候判断当前CPU架构决定加载哪一份代码。
比如,苹果当年切换到intel处理器的时候,就是这么做,要求开发者打包应用的时候将新旧两个体系的应用都打包进去。
Google有没有这么要求?有:Google 要求 NDK 开发者对 arm,arm64,mips,x86 等架构全都进行打包,而安卓的安装器在安装app到目标设备的时候,会根据目标设备的实际架构,只选择目标架构安装上去。
我们看到,Google的想法是好的,实际上呢?实际上,开发者们根本就不愿意打包所有架构,往往都偷懒只打包 armeabi 架构。
然而现实是:7年来生产的所有新款手机都是 arm64 架构的。而Android Studio从3.4开始就默认只打包手机对应架构的ndk包(对于手机来说,这意味着AS默认只打包arm64架构,除非你在gradle设定中强制设定ndkfilter)。
可是相当多的开发者依然,宁可在gradle中强制设定ndkfilter,也不愿意提供arm64版本的包。——当然,他们同样也没有提供 x86,没有提供 mips 的包。
那么问题来了,操作系统能不能只接受源代码,然后,到不同平台架构上实时编译,这样确实就什么架构都能跑了?
答案是:操作系统确实能够这么做,但软件开发商不愿意啊。
如果你的代码支持让操作系统实时的到目标机去编译,那么你这个代码就相当于完全没有加密的,很容易被破译,从公司管理的角度,这样暴露自己的IP(智力财产)是不合规的。
我的看法:理论上可以这么做,只要规定软件发布必须把主流CPU架构都打包就好。但实际上只有苹果能做到这一点。苹果可以规定你不按照我的要求打包就不让你发布。安卓跟Windows就不行。
这大概就是自由的代价吧。允许软件开发有更多自由,就必然没法阻止开发者使用或者只提供某个特定架构才能用的库。操作系统如果无法从软件发布的源头上管控软件发布,那么就没有办法支持所有的情况。
在操作系统看来,它是把cpu直接共享给了应用程序,而不是把cpu抽象成什么东西来间接供应用程序使用
应用程序使用cpu并不需要它来代劳,它只是在各个程序之间做一个调度而已
如何使用cpu是你自己的事,我不管也不关心你是咋用的,更没有所谓的“屏蔽底层架构”的概念。你要想实现这种特性,那就你自己来搞,我不想掺和这种事
本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度,google,bing,sogou 等
© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有