Haskell程序如何在内部编译和执行?

时间:2012-09-13 21:19:02

标签: haskell compilation runtime ghc

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

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

3 个答案:

答案 0 :(得分:28)

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

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

C,Java和GHC Haskell就是这种系统的例子。在GHC的情况下,entire architecture is described here。这些作品也将单独描述并详细描述。

答案 1 :(得分:13)

我可以提供运行时的精确度。

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

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

答案 2 :(得分:8)

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

因为它会执行无法在Haskell中表达的低级别的东西。很像Linux内核是一个运行C程序的系统,但Linux内核的部分内容是用汇编语言编写的,而不是C语言。

2:为什么编译的程序需要运行时环境?据我所知,这就像Java字节码解释器。

GHCi使用几乎与Java字节码解释器完全相同的东西。 编译 GHC程序没有;编译后的程序是原始机器代码。

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

(有点像C程序编译,它是原始机器代码,但如果没有像Windows这样的操作系统,你仍然无法运行它Linux或其他东西。)

例如,每次Haskell程序内存不足时,Haskell程序就会停止运行,垃圾收集器会开始运行。垃圾收集器试图释放一些内存,一旦它有了,Haskell程序就会重新开始运行。

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

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

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