了解不同平台编译器的需求

时间:2010-11-10 07:22:12

标签: compiler-construction operating-system

我正在努力学习整个构建链是如何工作的,这样我就可以更好地理解构建/链接/编译等时发生的事情。

我遇到问题的一点是:如果编译器将源转换为本机程序集,为什么不能在不同的OS上运行相同的程序?是不是直接由CPU运行程序集?所以相同的机器代码应该在每个操作系统上运行,只要它是相同的架构,不是吗?为什么不呢?

编辑:到目前为止,大多数答案都是关于调用操作系统的 API 。这显然是个问题。我的问题是直机器代码。是否直接传递给CPU?如果我在汇编中编写了一个程序,我还需要为每个操作系统单独编译吗? (侧点:如果我使用标准的c ++ cin / cout,是否依赖于操作系统,编译为直接汇编I / O,或答案取决于编译器?)

7 个答案:

答案 0 :(得分:8)

不同的操作系统支持不同的二进制格式(例如ELF与COFF),不同的动态链接器(在您分发二进制文件后,* .so,*。dll和* .dylib文件在运行时链接),以及为使用OS提供的功能提供不同的功能和库集。

不同的功能集可以通过例如Single UNIX Specification / IEEE Std来解决。 1003.1(POSIX),它规定了在所有操作系统中为各种操作系统任务提供的一组功能(遗憾的是并非所有操作系统 - 嗯, Windows - 遵守)。关于二进制格式(以及CPU指令集架构),解决这个问题的一种方法是分发一些更高级别的二进制格式(字节码),然后对目标指令集进行即时转换。二进制格式(虽然这更多的是关于改变时...它仍然需要完成)。例如,低级虚拟机(LLVM)提供了这种转换。

答案 1 :(得分:8)

归结为操作系统的APIABI

不同的操作系统提供不同的system calls,以及调用这些系统调用的不同机制。例如,虽然POSIX提供了forkexecv来创建新流程,但Windows提供了CreateProcess

此外,装配层面也存在差异。你用什么汇编代码来调用函数?不同的操作系统需要不同的calling conventions。操作系统也不一定就可执行二进制文件的格式达成一致,也不同意其他机制,如动态链接。

需要考虑的另一点是并发性以及操作系统如何处理这种情况。某些操作系统在内核级别识别线程,而其他操作系统则不识别。有些人可能只是喜欢使用多个进程,有些人可能会使用完全不同的模型。 API不同,抽象可能不同。例如,一个操作系统可能使用锁和信号量,另一个可能使用消息传递。

答案 2 :(得分:6)

因为,一方面,与操作系统接口的能力在平台之间不一致。即使在Linux / x86,Windows和Mac / Intel(可能都使用相同的CPU)之间,处理方式也可能大不相同。

因此,虽然编译器可能会生成可用的目标文件,但只要将这些对象链接到特定于平台的库,它们就会变得非常不可移植。

一个例子是内存分配。如果要在UNIX下从操作系统请求更多内存,可以使用brksbrk库函数。这是 C标准库的一部分,更像是UNIX特定的库。

另一方面,Windows可能会提供Win32GetMem功能来执行相同的操作。

答案 3 :(得分:1)

你是对的,编译器只关心为特定目标CPU生成正确的汇编程序指令。但编译器并不孤立 - 应用程序通常必须与主机操作系统连接才能正常运行。

所以问题不在于编译器本身,而在于每个操作系统提供的标准库集合,用于访问文件,分配内存或与图形窗口系统交互等常见内容。虽然Windows XP和Solaris x86的代码将被编译为同一组机器代码指令,但代码必须对操作系统的接口进行不同的调用。

专有编译器仅与它们所针对的操作系统的标头和库捆绑在一起。其他更加不可知的编译器(如GNU GCC)会共享大量代码,以便在不同的操作系统中编译为相同的CPU类型。

答案 4 :(得分:0)

是机器代码由CPU直接运行。但是,即使作为机器代码的32位“x86”指令集也经历了多年的修订。但通常,为体系结构编译的代码应该在其他系统上运行。一个更大的问题是它在

中编译的编译器和操作系统

答案 5 :(得分:0)

是的,确实如此。例如,这就是你可以在Wine下运行Windows应用程序的方法。您可以直接运行该程序,原因不止一个。例如,您的可执行文件的格式在不同的系统中是不同的,因此系统通常没有任何想法如何加载和执行其他可执行文件。除了大多数程序都希望调用系统例程并调用一些库函数,这里我们讨论的是关于如何在每个系统中完成它们的完全不同的协议集。

答案 6 :(得分:0)

你的问题,“所以相同的机器代码应该在每个操作系统上运行,只要它是相同的架构,不是吗?”是不正确的。 机器代码在不在操作系统上的硬件上运行。 OS为用户/系统程序提供服务,并且在每个OS中以不同方式实现这些服务。为了论证,如果你从程序“A”的操作系统“X”获取程序的机器代码并将其直接输入到操作系统“Y”并且具有相同的拱形“A”的系统,则cpu将能够执行指令但这可能(并且几乎总是)会导致程序崩溃(因为其他人已经提到过不同的实现问题)。