问题

很好奇,为什么软件要直接运行在CPU上?

回答
你想了解为什么软件要直接“跑”在CPU上,对吧?这问题挺有意思的,因为背后涉及到计算机最核心的工作原理。我尽量给你讲得明白点,不整那些空洞的概念。

咱们先想象一下,电脑就像一个厨房,而CPU就是那个最忙碌的厨师。你想做一顿饭(运行一个软件),总得有人来动手切菜、炒菜、调味,对吧?CPU就是这个厨师。它负责执行你告诉它要做的一切指令。

那么,为什么它要“直接”跑在CPU上呢?这背后其实是效率和控制的极致追求。

1. CPU是指令的执行者,这是它的“本职工作”

你可以把软件想象成一份超级详细的菜谱,里面写满了“把番茄切块”,“往锅里倒油”,“加入盐,翻炒均匀”之类的指令。CPU的唯一使命,就是按照这份菜谱(也就是软件的指令)一步步地去执行。它擅长的就是快速地理解这些指令,然后用它内部的电路(你可以想象成厨具和炉灶)去完成动作。

2. 没有中间商赚差价,速度更快

如果软件不直接跑在CPU上,那它会跑在哪里呢?你可以想象有个中间人,比如一个“代理厨师”。你告诉代理厨师你想做什么,他再去告诉真正的厨师(CPU)。这样一来,信息的传递就会多一个环节,信息传递过程中还可能出错,而且中间人本身也要占用时间和资源。

直接跑在CPU上,就像你直接把菜谱递给厨师一样,信息传递最直接,也最有效率。软件的每一个指令都被翻译成CPU能懂的机器语言(就是一串串0和1),然后CPU就能立马执行。这就像厨师一眼就能看懂菜谱上的每一个字一样,效率自然高。

3. 硬件的“语言”就是CPU的指令

电脑里的所有硬件,比如内存、硬盘、显卡,它们之间沟通的方式最终都要通过CPU来协调。CPU是整个计算机系统的“大脑”,它发出指令,其他硬件配合。软件写出来的内容,本质上也是为了让CPU知道要做什么,然后CPU再通过发送信号给其他硬件去完成任务。

比如,你想从硬盘里读一张照片到内存里,这个过程的指令其实是这样的:CPU收到“读取照片”的指令 > CPU告诉硬盘“把这张照片的数据给我” > 硬盘找到照片数据,通过总线传给CPU > CPU再把这些数据放到内存里,或者直接传给显卡显示。整个过程,CPU都在中间协调和指挥。

4. 精确的控制权

直接在CPU上运行,意味着软件开发者能够对计算机的底层资源有最精细的控制。比如,什么时候用多少内存,什么时候进行计算,什么时候等待输入输出,这些都可以通过CPU上的指令来精确管理。这种精细的控制对于优化性能、处理复杂任务至关重要。

试想一下,如果你想让一道菜的味道达到极致,你可能需要精准控制火候、调料的加入顺序和量。CPU上的指令就像这些精细的操作,能让你对整个“烹饪过程”有绝对的掌控。

5. 历史的必然

早期的计算机,资源非常有限。把每一条指令都直接交给CPU去执行,是当时最节省资源、最有效的方式。随着技术的发展,虽然有了操作系统这样的“管理者”来调度和协调,但最终执行命令的“主力军”还是CPU。操作系统更像是厨房的“大管家”,负责分配任务给厨师(CPU),安排厨师什么时候做什么,但具体怎么切菜、怎么炒菜,还得是厨师(CPU)自己来完成。

总结一下:

软件之所以要直接运行在CPU上,最根本的原因是CPU就是计算机里的那个核心执行者,它是唯一能够真正理解和执行机器指令的部件。将软件指令直接交给CPU,能够最大程度地减少信息传递的损耗,提高执行效率,并且赋予了软件对计算机硬件最直接、最精细的控制权。就像你要让事情办成,最直接的方式就是直接找那个能办事的人一样,软件直接找CPU,就是因为它能“懂”和能“做”。

希望我这样讲,能让你明白为什么CPU是软件运行的“主战场”了。

网友意见

user avatar

其他的跨ISA、跨ABI、跨API之类的回答已经很多了。

我看了一下题主的各种评论,我觉得最核心的就是这里了吧?

如果这些人力物力 都由系统去承担,而不是一个个的软件开发商承担,是不是就好多了?

就只回答这个点。

题主的想法就是由os厂商提供原生的跨ISA(指令集)的虚拟化的vm,让所有app都运行于这个标准化的vm里,从而做到跨ISA执行。但很可惜的是,虽然这在技术上实现起来没什么问题,然而,在商业上,这是不现实的。

事实上,以vm为核心的os,强制所有app必须运行于vm内的os,历史上还真的有过:早期的android就是这样的(只有Dalvik可用,而且还不开放jni)。然而事实就是,它因为运行效率稀烂而被同期的ios按在地上摩擦得很惨(各种所谓的android性能不行,耗电很高,待机很短的一系列刻板印象实际上就源于此——甚至遗祸至今)。后来痛定思痛,才开放了jni(jni已经是本地机器码了)。到后来jni都不够了,于是就有了AOT技术的ART——而这个ART,和原来Dalvik的最大区别,就在app安装时就已经把中间字节码转译成了本地机器码,于是每次运行都是真正的本地执行。


所以,题主所设想的是很美好的:

如果系统把这一块做好

然而现实中,系统“把这块做好”的方法,恰恰就是抛弃中间字节码,拥抱本地机器码……

user avatar

首先,有这样的软件,跑在Java JVM上的、运行时解释的等等,但这些不是主流,也不是楼主想问的,所以我们刨除这些特例。

其次,不存在"直接运行在CPU上"这种说法

(一)原(zhuang)因(bi)部分

影响一个应用程序兼容性的因素主要有几个:ISA、ABI、API,同时做到才能无缝切换。

1)ISA,Instruction Set Architecture,指令集架构。x86,x86-64,arm,mips,JVM的指令集,这些都不相同,也不可能相同。一个需要编译后运行的软件,编译时必须决定自己要选择哪个指令集,选定之后就只能运行在可解释该指令集的"东西"上,不管这种东西是硬的CPU、虚拟的CPU、仿真的CPU、Java虚拟层、直接支持Java ISA的硬CPU(真有研究干这个的)。所以,谁有资格说自己的ISA是全球通用的?ISA变化,不能运行是一定的。

2)从应用程序层面看真正和OS绑定的是ABI,Application Binary Interface,应用程序二进制接口,主要类似参数传递、数据格式等等的协定,这个其实在一族OS上可以做到轻易一致而且也会选择一致。这个对应是楼主说的运行在系统上的意思,和ISA两者不是一个层次的事情,不能对比,也不能相互替代,不是说统一了ABI就能不管ISA。(比如JVM,虚拟层级比较高,直接一起抹平了ISA和ABI)

3)另外从开发者层面看的另一个是API兼容,都知道而且和楼主要问的也无关,就不多说了,各类底层库换代导致向后/向前不兼容的惨案大家都懂。

要兼容,以上三者缺一不可。现在苹果换了M1,突变的只有ISA,也就是最无法提前统一的东西,原因见下。

(二)楼主的问题部分

为什么大家一开始不采用一样的ISA(比如上帝用一天创造了某个类似与JVM的虚拟层SXM)呢?很简单,ISA(简单理解为CPU吧)很多年都是稳定的,开发者没有动力干这个事。

比如一个厂商要选择开发一个应用,时间一年。

1)ISA兼容x86,性能可以跑到100分,可以卖100块,但只能在x86上跑

2)选择SXM的ISA,因为多了一层中间层,性能只跑到95分,只能卖95块。但这个可以在x86的SXM上跑,也能在arm的SXM上跑

现在问题来了,在ARM主打便携性能搓搓的那些十几年里,PC和便携平台的处理器交集几乎为0,PC清一色都是x86,那么你觉得厂商会脑子抽抽了自损八百来考虑跨ISA的兼容性么?

然后事情发生了变化,牛b哄哄的M1出现了,采用ARM指令集的处理器应用范围第一次和x86发生了重叠,跨ISA的需求才真正(大规模)浮现出来。所以现在你问什么情况下才会提前有这个准备,那我后知后觉的告诉你,可能就是:全世界的开发人员提前N年精准预测到ARM团伙里会蹦出个能叫板x86的M1。

这个问题的等价版本就是,

任正非既然坐拥华为,为什么不能选择不要倒插门让自己儿子姓孟?

user avatar

软件本来就是运行在操作系统上的。所谓的中间抽象层确实存在。

但即便如此,你的设想也并不成立。

多加一个中间层其实解决不了根本问题。不同硬件始终是需要独立调试的。哪怕是Java这种跑虚拟机的代码,不同硬件不同操作系统依然还是存在一些表现上的不同。也不可能所有软件都完全意义上的跨平台。

也就是说,跨平台无论如何都需要付出人力,只不过不同架构的情况下付出的人力多还是少有区别。

就算根本没有中间层,事实上大多数编程语言都是源码级跨平台的。软件只需要重新编译一下就可以。可是没有人维护,没有人做这个工作,就不行。

换cpu就有一批软件不能用的根本原因,在于软件没有人维护。而不在于有没有中间抽象层。有人维护的软件才能持续使用。换CPU这些都是小问题。

user avatar

旁友,你知道Java吗?



在我指出他的逻辑思维能力存在瑕疵后,提问者表示,他一开始问的就是:

不要转移话题OK? 我一开始问的是 系统为什么不承担虚拟机的职责,


所以我重新把问题排查了一下,在当前时刻,问题是长这个样子的:

很好奇,为什么软件要直接运行在CPU上?
为什么现在的软件都要直接运行在CPU上, 导致出现了很多问题,比如这次苹果换M1,就有很多软件运行不起来了。
为什么不干脆让系统作为一个平台,让软件在这个系统上运行呢,这样软件跟CPU就不用直接打交道了, 也就不存在上面的问题了。


我觉得,这进一步的表达了其逻辑思维和表达能力的瑕疵。

很显然问题的描述中描述的是:

为什么不让系统作为一个平台,让软件在这个系统上运行。

而不是:

为什么系统不是一个平台,让软件都在这个系统上运行。


很显然这两者存在着巨大的差异。

当你问为什么你不去厕所拉屎的时候,我当然只能回答你,我可以去厕所拉屎,但是现在我并没有排泄物。也就是说,软件当然可以跑在Java上,只不过现阶段他们没有跑在Java上

当我告诉他,软件当然能够跑在JRE上的时候。他竟然提出了一个更蠢的问题,为什么现在没有跑在JRE上的软件不能跑在JRE上……这让我语塞……



抱歉,我真的很难和无法区分能不能和是不是的人沟通。



当问题的逻辑理清后,事实上问题并不复杂,无非是历史遗留口味选择

虚拟机技术的性能在很长一段时间里面是被人所诟病的,而操作系统在很长一段时间内并不像如今的手机操作系统一样大包大揽。很大程度上来说,早期的桌面操作系统和其他应用并没有本质的区别,各种架构图上会画出操作系统作为应用和硬件设备的中间层,这没错,除了驱动程序之外,应用在大部分情况下的确是通过操作系统和硬件设备打交道的,但也只有访问外部设备的时候才通过操作系统。业务逻辑是应用自己写的,也就是说CPU和内存这种非外部设备是不由操作系统管理的,如果CPU推出了新的指令集,也必须升级应用自身才能享受到性能的提升。

这就是历史遗留问题,桌面操作系统本来就只提供最基本的服务,在这种环境下应用当然会面向CPU研发,而CPU产商甚至在CPU内部隔离出了虚拟层(也就是指令集,没错,指令集并不是最终执行的微码,译码器说白了其实就是个中间层),使得应用可以在同一指令集架构下的CPU上正常运行。

更进一步的也不难想到,如果操作系统把CPU虚拟化,那还有什么Wintel联盟,微软说了算就好了啊。这种事情大家都不想的嘛,苹果他一直不能自己造CPU,所以没办法老换架构。现在苹果自己能造CPU了,直接CPU内部隔离中间层不就够了没必要软件层面上隔离啊。


第二个原因就是口味选择,有没有把CPU虚拟化来兼容应用的做法?有啊,很多解决方案都是这么干的,譬如说模拟器,但是指令集之间的软翻译性能相当感人。更重要的是指令集过于低级了,所以在程序编译成指令集之前做了太多的优化,而在虚拟化CPU上这些优化很可能有毒或者毫无意义。

更好的方式是重新设计一套像Java字节码那样的中间语言,让应用都跑在中间层上,这就是.NET战略,当然这个事情最终来讲连微软都没有将自家的应用彻底虚拟化。原因有很多,性能是其中一个重要的原因但是并不能笼统的说就是性能问题……

所以我更倾向于说,这是一个口味的问题。而我觉得随着算力的过剩,事实上中间层带来的性能问题也可以在很大程度上得到解决,毕竟现在UI渲染基本都用浏览器引擎了也没觉得有啥大问题……

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有