37

Haskell (GHC) がプログラムをコンパイルする方法と、それらのプログラムがどのように実行されるかを理解するのに苦労しています。

  1. GHC は、Haskell で書かれた重要なプログラムの標準的な例です。ただし、GHC の一部、つまりランタイム環境 (C/C --) は Haskell で記述されていないようです。何故ですか?パフォーマンス上の理由? (私はこのサイトとその友達を知っていますが、あまり意味がありません.)
  2. ランタイム環境といえば、なぜコンパイル済み言語にランタイム環境が必要なのですか? コンパイルされたプログラムは機械語だけであってはいけませんか? 私の理解では、ランタイム環境は仮想マシンまたはバイトコード インタープリターにいくぶん似ており、何らかの形式のメタ コードを処理し、それに基づいて実際の計算を行います。では、GHC ランタイムは正確には何をするのでしょうか? そもそもなぜそれが必要なのでしょうか?
  3. FFI について: C 呼び出しはどのように処理されますか? 最初は、FFI を使用すると、Haskell と C が一緒にコンパイルされた単一の実行可能ファイルが生成されると考えていました。ただし、GHCプログラムがプログラムからC関数を呼び出すようなものを何度も読みました。これは、FFI が並列プログラミングで抱えている問題を理解する上で特に重要です。では、FFI 関数は通常の Haskell 関数とどう違うのでしょうか?
4

3 に答える 3

38

ストックハードウェアでプログラミング言語をコンパイルして実行するには、次のことが必要です。

  • ソース言語をネイティブホストによって実行可能なアセンブリコードに変換するコンパイラ
  • メモリ管理、IO、スレッド管理などの基本的な言語サービス用のサポートライブラリ(別名ランタイム)。下位レベルのシステムサービスから活用する必要があるもの。

C、Java、GHCHaskellはそのようなシステムの例です。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 は一種のミニ OS に似ています。メモリ管理、スレッド スケジューリング、例外処理の特定の側面、トランザクション処理を行います。すべての Haskell プログラムは、このミニ OS の下で実行されます。

(C プログラムがコンパイルされていても、それは生のマシン コードですが、 Windows や Linux などのオペレーティング システムがないと実行できないのと少し似ています。)

たとえば、Haskell プログラムがメモリ不足になるたびに、Haskell プログラムは実行を停止し、ガベージ コレクターが実行を開始します。ガベージ コレクターはメモリを解放しようとします。メモリが解放されると、Haskell プログラムが再び実行を開始します。

コンパイルされたすべての Haskell プログラムには、Haskell RTS の一部にすぎないこのガベージ コレクター プログラムのコピーがあります。同様に、1 つの OS スレッド内で複数の Haskell スレッドを実行できるため、RTS には内部にスレッド スケジューラがあります。私は続けることができました...

3: FFI はどのように扱われますか? 私はすべてのものをまとめてコンパイルしたと思った。

それすべて一緒にコンパイルされます[というか、リンクされます]。C プログラムを作成すると、ある C 関数から別の C 関数を呼び出すことができます。Haskell が C 関数を呼び出すときは、その C 関数を呼び出す他の関数とほとんど同じです。ただし、関数呼び出しの内容によっては、Haskell 側で発生することがいくつかあり、オーバーヘッドが追加される可能性があります。

于 2012-09-14T16:06:12.393 に答える