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

Dav*_*vid 31 haskell runtime compilation ghc

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

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

Don*_*art 31

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

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

C,Java和GHC Haskell就是这种系统的例子.在GHC的情况下,这里描述整个架构.这些部件也单独描述并详细描述.


Gre*_*eek 14

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

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

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


Mat*_*hid 10

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方面会发生一些事情,这可能会增加一些开销.