代码之家  ›  专栏  ›  技术社区  ›  Baruch

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

  •  5
  • Baruch  · 技术社区  · 14 年前

    我正在尝试学习整个构建链是如何工作的,以便更好地理解构建/链接/编译等操作时会发生什么。

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

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

    7 回复  |  直到 14 年前
        1
  •  8
  •   Michael Aaron Safyan    14 年前

    不同的操作系统支持不同的二进制格式(例如elf与coff)、不同的动态链接器(在分发二进制文件之后,运行时链接了*.so、*.dll和*.dylib文件),并为使用操作系统提供的功能提供不同的函数集和库集。

    例如,可以通过单个Unix规范/IEEE Std.1003.1(POSIX)来处理不同的功能集,该规范规定在所有操作系统中为各种操作系统任务提供一组功能(不幸的是,并非所有OSS——ahem, 窗户 --遵守)。对于二进制格式(以及CPU指令集体系结构),处理这一问题的一种方法是分发一些更高级别的二进制格式(字节码),然后对目标指令集和二进制格式进行实时转换(尽管这更多的是在去做吧…这仍然需要完成)。例如,低级虚拟机(llvm)提供了这种转换。

        2
  •  8
  •   Aaron Klotz    14 年前

    归结到操作系统的 API ABI

    不同的操作系统提供不同的 system calls 以及调用这些系统调用的不同机制。例如,当posix提供 fork execv 要创建新进程,Windows提供 CreateProcess

    此外,在组装级别上也存在差异。您使用什么程序集代码来调用函数?不同的操作系统期望不同 calling conventions . 操作系统也不一定同意可执行二进制文件的格式,也不一定同意动态链接等其他机制。

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

        3
  •  6
  •   paxdiablo    14 年前

    因为,首先,平台之间的操作系统接口能力是不一致的。即使在Linux/x86、Windows和Mac/Intel(它们可能都使用相同的CPU)之间,做事情的方式也可能大不相同。

    因此,虽然编译器可能会生成可以工作的对象文件,但一旦将这些对象链接到特定于平台的库,它们就变得不可移植。

    一个例子是内存分配。当您想从Unix下的操作系统请求更多内存时,可以使用 brk sbrk 库函数。这是 C标准库的一部分,更确切地说是一个特定于UNIX的库。

    另一方面,窗户可以提供 Win32GetMem 做同样的事情。

        4
  •  1
  •   Kim Burgaard    14 年前

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

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

    专有编译器仅与为其设计的操作系统的头文件和库捆绑在一起。另外,更不可知论的编译器(如GNUGCC)在跨不同操作系统编译到相同CPU类型时会共享大量代码。

        5
  •  0
  •   Matt Phillips    14 年前

    是的,机器代码由CPU直接运行。但是,即使是32位的“x86”指令集,也就是机器代码,多年来一直在进行修订。但一般来说,为体系结构编译的代码应该在其他系统上运行。更大的问题是编译它的编译器和操作系统

        6
  •  0
  •   cababunga    14 年前

    是的,的确如此。例如,这就是如何在Wine下运行Linux中的Windows应用程序。您可以出于一个以上的原因直接运行程序。例如,可执行文件的格式在不同的系统中是不同的,因此系统通常对如何加载和执行其他可执行文件一无所知。除此之外,大多数程序都想调用系统例程和一些库函数,这里我们讨论的是关于如何在每个系统中执行的完全不同的协议集。

        7
  •  0
  •   blue_whale    11 年前

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