37

我无法理解 Haskell (GHC) 如何编译程序,以及这些程序是如何运行的。

  1. GHC 是用 Haskell 编写的非平凡程序的典型示例。但是,GHC 的某些部分似乎不是用 Haskell 编写的,即运行时环境(C/C--)。这是为什么?性能原因?(我知道这个网站和它的朋友,但不能理解他们。)
  2. 说到运行时环境:为什么编译语言需要一个?编译的程序不应该是机器代码而没有别的吗?据我了解,运行时环境有点类似于虚拟机或字节码解释器,它处理某种形式的元代码并在此基础上进行实际计算。那么:GHC 运行时到底做了什么,为什么它首先是必要的?
  3. 关于 FFI:如何处理 C 调用?最初,我认为使用 FFI 会生成一个可执行文件,其中 Haskell 和 C 编译在一起。但是,我多次读到 GHC 程序会从程序中调用 C 函数。这对于理解 FFI 在并行编程方面的问题尤其重要。那么:FFI 函数与普通 Haskell 函数有何不同?
4

3 回答 3

38

要在库存硬件上编译和执行编程语言,您需要做很多事情:

  • 一个编译器,将你的源语言翻译成本机主机可执行的汇编代码
  • 原始语言服务的支持库(又名运行时),例如内存管理、IO 和线程管理。必须从较低级别的系统服务中利用的东西。

C、Java 和 GHC Haskell 是此类系统的示例。在 GHC 的情况下,这里描述了整个架构。这些作品也被单独详细地描述。

于 2012-09-14T12:00:02.113 回答
15

我可以提供一些关于什么是运行时的精确度。

虚拟机是“一种”运行时,但不是唯一的。运行时系统只是您的程序可以假设在执行期间存在的环境(和一组服务)。即使是像 C 和 C++ 这样的非常低级的语言也有运行时系统(想想 malloc ......某人/某事正在为您进行分配,甚至除以零检查)。

一般来说,高级语言具有更丰富的运行时(意味着运行时为执行程序提供更多服务);这些范围从内存管理(例如垃圾收集)到反射/内省基础设施(想想 ruby​​ 等......)再到数组边界检查,但几乎所有语言都有某种运行时系统(如果只有操作系统)。

于 2012-09-13T21:46:29.707 回答
12

1:为什么RTS不是用Haskell写的?

因为它做了一些不能用 Haskell 表达的低级东西。就像 Linux 内核是一个运行 C 程序的系统一样,但 Linux 内核的某些部分是用汇编而不是 C 编写的。

2:为什么编译好的程序需要运行环境?据我了解,这类似于 Java 字节码解释器。

GHCi 使用的东西几乎与 Java 字节码解释器一模一样。编译的 GHC 程序不会;编译后的程序是原始机器代码。

相反,Haskell RTS 更像是一种迷你操作系统。它进行内存管理、线程调度、异常处理的某些方面以及事务处理。每个 Haskell 程序都在这个 mini-OS 下运行。

(这有点像即使编译了 C 程序,它是原始机器代码,但如果没有 Windows 或 Linux 之类的操作系统,您仍然无法运行它。)

例如,每次 Haskell 程序内存不足时,Haskell 程序就会停止运行,而垃圾收集器开始运行。垃圾收集器尝试释放一些内存,一旦释放,Haskell 程序就会再次开始运行。

每个编译的 Haskell 程序都有这个垃圾收集器程序的副本,它只是 Haskell RTS 的一部分。类似地,多个 Haskell 线程可以在一个 OS 线程中运行,因此 RTS 内部有一个线程调度程序。我可以继续...

3:FFI如何处理?我以为这些东西都是一起编译的。

它全部编译[或者确切地说,链接]在一起。如果你编写一个 C 程序,一个 C 函数可以调用另一个 C 函数。当 Haskell 调用 C 函数时,它与调用该 C 函数的任何其他函数非常相似。根据函数调用的作用,Haskell 端会发生一些事情,这可能会增加一些开销。

于 2012-09-14T16:06:12.393 回答