针对不同OS编译的程序之间的差异


8

从已编译的代码角度来看,为一个操作系统与另一个操作系统(例如Linux与Windows)编译的程序之间有什么区别。程序不直接在CPU上运行吗?还是因为程序需要引用操作系统特定的库?

Answers:


6

普通的已编译程序确实可以在CPU上“直接运行”,但是程序不能在真空中运行:

  1. 许多程序依赖于外部动态加载的库(DLLs.so库)。链接它们的方式取决于编译器/链接器,并且每个OS都有不同的标准。但是,也有“静态链接”程序提供所有自己的代码。

  2. 现代操作系统无法完全控制正在运行的程序的计算机。程序依赖于“系统调用”来进行I / O,访问硬件以及诸如信号之类的事情并进入睡眠状态。可用的服务和接口由操作系统定义。操作系统还控制允许程序使用系统的哪些部分(内存,寄存器,中断)。

  3. GUI程序还必须在图形用户环境中工作,以便在屏幕上绘制自己。但是您可能已经考虑过了。

由于这些原因,与OS无关的应用程序必须依赖某种“虚拟机”,例如java运行时提供的那种。至关重要的是,VM为OS资源(I / O,信号等)提供了标准接口。当然,java或python也会解释“字节码”,而不是处理Intel指令集的怪癖。但这是一个不同的故事。


此外,不同的操作系统在堆栈布局,内存对齐方式等方面有不同的标准,因此,即使是纯数字/计算代码,也可能需要在一个操作系统与下一个操作系统之间有所不同。
Daniel R Hicks

这些差异是否会阻止执行静态编译的代码?不知道..
亚历克西斯

这可能只是一个理论问题,因为其他一些不兼容会首先使您受益。但是,操作系统通常对堆栈框架的对齐方式,寄存器的存储位置等抱有期望。对于相同的硬件体系结构,这些可能因一个操作系统而异。从理论上讲,您可能可以运行纯粹是计算性的“外部”代码,但您永远无法启动它,也永远无法干净地结束它。
Daniel R Hicks

5

不同的操作系统也具有不同的功能。Windows具有I / O完成端口,Linux没有。FreeBSD有kqueue,Linux没有。Linux有能力,Windows没有。他们也有不同的方式来做相同的事情-您打开文件时传递了哪些参数?他们按什么顺序?您如何具体调用操作系统的“打开文件”功能?


好的,这是有道理的,但通常来说,程序是否将程序加载到内存中并在cpu上运行,还是操作系统“对该程序进行了控制”
agz 2013年

1
@agovizer:两者都有。它们不是互斥的。通常,操作系统将设置受控环境,并安排硬件在特定时间内中断程序,然后将内核移交给程序。但是,一旦程序遇到任何条件(例如页面错误,I / O操作等),OS就会再次接管。
David Schwartz

5

通常,由于其应用程序二进制接口(ABI)的差异,程序不兼容。

程序不直接在CPU上运行吗?

!这是操作系统的工作,可以防止应用程序在CPU上“直接”运行。通常,在最低级别(即构建OS API的级别)上,应用程序与操作系统的内核交互。

是否因为编译后的程序本身需要引用操作系统特定的库?

是的。编写了许多OS库来促进与操作系统本身的接口,但是有很多跨平台的。这些隐藏了与开发人员的低级OS接口,并假定该OS的编译版本将在运行时可用(请参见下文)。

尽管可以跨平台的方式编写库,但是在编译时不能跨平台运行它们。仍然需要针对特定​​目标操作系统重新编译它们,以再次利用操作系统(内核)的特定基础组件。

一个操作系统与另一个操作系统的已编译程序有什么区别?

最后,可执行文件本身通常包含非常特定的二进制加载标头等等,例如Windows 的PE可执行文件格式[.exe,.dll等...],Linux的ELF文件格式[none,.o,.so等等...])。这些还可以包括用于加载特定软件库的已编译OS特定二进制文件的代码。


最后,从程序员的角度来看:调用Convention。编译后的代码以给定的方式(即通过寄存器或堆栈)以非常特定的顺序将变量传递给函数。即使这样,也需要就谁负责“清理”函数调用(调用方或被调用方?)达成共识。尽管有几种标准且使用广泛的x86调用约定,但某些操作系统可能不支持某些约定(这是ABI的一部分)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.