为什么Linux和Windows下的程序不能互通?
在大致了解过一个程序是怎么被CPU执行之后,我就在思考一个问题,既然我们用高级语言写的程序最终都是机器码,而机器码又只和CPU的架构有关,所以按照这个道理,同一台电脑下的不同的系统中的程序应该是可以互通的呀!然而事实却不是这样的,如果真是这样,那Linux再也不会让我劝退了,我也就不会被迫把自己的电脑装回windows了。既然事实与我们所想不一致,那一定在高级语言转换为机器码的过程中遗漏了什么细节。询问ChatGPT(狗头)之后,问题得到了解答。我们先将CPU执行高级语言的过程给稍微细节化,高级语言通过编译,汇编,链接,装载这几个步骤之后,CPU就可以执行这个程序了。我们知道编译的过程是将高级语言转换为汇编语言(不是全部高级语言都有这个过程),汇编的过程就是将汇编语言转换为目标文件(对应CPU指令集架构的目标文件)
这三个过程,因为CPU指令集的限制,所以无论在过程中文件怎么变化,到目标文件的时候,按照理论来说Windows和Linux生成的目标文件应该都是一样的(注意是理论上)。那么可能出问题的地方就只能是后面的两步,链接和装载。先说链接,链接的目的是为了让不同文件中的程序可以被互相调用,可是如果链接的文件是Linux专属或者Windows专属的呢?那么这个程序想要跨平台运行就肯定不可能了。现在我们来谈论装载过程,装载过程是将我们的可执行文件装载到内存中,而这个过程需要装载器,问题就出在装载器上,其实在linux中,目标文件和可执行文件(链接过程之后形成的文件)用到的文件格式都是ELF,而Windows用的文件格式却是PE,所以装载器在Linux和Windows中的实现是不一样的,Linux的装载器只需要解析ELF格式的文件就可以了,而Windows的装载器只需要解析PE的格式就可以了。也正是因为可执行文件的格式不对,装载器就无法正确的将可执行文件装载到内存中,可以这样类比,比如明明是一张图片,而你却用记事本打开,得到的结果只能是乱码。既然得到的是乱码,CPU怎么可能正确的执行程序呢?所以我们又可以解释一个现象了,比如Windows中的WSL了,思考一下为什么WSL可以执行linux的命令,不就是WSL实现了ELF的装载器以及一些Linux下专有的链接库吗?如果熟悉Linux的朋友,就一定听说过Wine,他也是通过实现一个PE的装载器,来达到在Linux中,运行Windows的程序。
