コンパイラー、リンカー、ローダーの意味と動作を詳細に知りたいと思いました。任意の言語、できればc ++を参照します。
=====> COMPILATION PROCESS <======
|
|----> Input is Source file(.c)
|
V
+=================+
| |
| C Preprocessor |
| |
+=================+
|
| ---> Pure C file ( comd:cc -E <file.name> )
|
V
+=================+
| |
| Lexical Analyzer|
| |
+-----------------+
| |
| Syntax Analyzer |
| |
+-----------------+
| |
| Semantic Analyze|
| |
+-----------------+
| |
| Pre Optimization|
| |
+-----------------+
| |
| Code generation |
| |
+-----------------+
| |
| Post Optimize |
| |
+=================+
|
|---> Assembly code (comd: cc -S <file.name> )
|
V
+=================+
| |
| Assembler |
| |
+=================+
|
|---> Object file (.obj) (comd: cc -c <file.name>)
|
V
+=================+
| Linker |
| and |
| loader |
+=================+
|
|---> Executable (.Exe/a.out) (com:cc <file.name> )
|
V
Executable file(a.out)
Cプリプロセスは、コンパイルの最初のステップです。以下を処理します。
#define
ステートメント。#include
ステートメント。このユニットの目的は、Cソースファイルを純粋なCコードファイルに変換することです。
ユニットには6つのステップがあります。
ソースファイル内の文字を組み合わせて、「トークン」を形成します。トークンは、「スペース」、「タブ」、「改行」を含まない文字のセットです。したがって、このコンパイル単位は「トークン化機能」とも呼ばれます。また、コメントを削除し、シンボルテーブルと再配置テーブルのエントリを生成します。
このユニットは、コード内の構文をチェックします。例:
{
int a;
int b;
int c;
int d;
d = a + b - c * ;
}
上記のコードは、方程式のバランスが取れていないため、解析エラーを生成します。このユニットは、次のようにパーサーツリーを生成することにより、これを内部的にチェックします。
=
/ \
d -
/ \
+ *
/ \ / \
a b c ?
したがって、このユニットはPARSERとも呼ばれます。
このユニットは、ステートメントの意味をチェックします。例:
{
int i;
int *p;
p = i;
-----
-----
-----
}
上記のコードは、「互換性のないタイプの割り当て」というエラーを生成します。
このユニットはCPUから独立しています。つまり、2種類の最適化があります
このユニットは、次の形式でコードを最適化します。
例:
{
int a = 10;
if ( a > 5 ) {
/*
...
*/
} else {
/*
...
*/
}
}
ここで、コンパイラはコンパイル時に 'a'の値を知っているため、if条件が常に真であることも知っています。したがって、コード内のelse部分は削除されます。
例:
{
int a, b, c;
int x, y;
/*
...
*/
x = a + b;
y = a + b + c;
/*
...
*/
}
次のように最適化できます。
{
int a, b, c;
int x, y;
/*
...
*/
x = a + b;
y = x + c; // a + b is replaced by x
/*
...
*/
}
例:
{
int a;
for (i = 0; i < 1000; i++ ) {
/*
...
*/
a = 10;
/*
...
*/
}
}
上記のコードで、「a」がローカルでループで使用されていない場合、次のように最適化できます。
{
int a;
a = 10;
for (i = 0; i < 1000; i++ ) {
/*
...
*/
}
}
ここで、コンパイラはアセンブリコードを生成し、より頻繁に使用される変数がレジスタに格納されるようにします。
ここで、最適化はCPUに依存します。コードに複数のジャンプがある場合、それらは次のように1つに変換されます。
-----
jmp:<addr1>
<addr1> jmp:<addr2>
-----
-----
コントロールは直接ジャンプします。
最後のフェーズはリンクです(実行可能ファイルまたはライブラリを作成します)。実行可能ファイルを実行すると、必要なライブラリがロードされます。
ASCII表現:
[Source Code] ---> Compiler ---> [Object code] --*
|
[Source Code] ---> Compiler ---> [Object code] --*--> Linker --> [Executable] ---> Loader
| |
[Source Code] ---> Compiler ---> [Object code] --* |
| |
[Library file]--* V
[Running Executable in Memory]
これがもう少し役立つことを願っています。
まず、次の図をご覧ください。
(img source->internet)
コードを作成してファイル(ソースコード)を保存し、
前処理:-名前が示すように、それはコンパイルの一部ではありません。実際のコンパイルの前に必要な前処理を行うようコンパイラーに指示します。このフェーズのテキスト置換を呼び出すか、#で示される特別なプリプロセッサディレクティブを解釈できます。
Compilation:-コンパイルは、ある言語で書かれたプログラムが別のターゲット言語に翻訳されるプロセスです。エラーがある場合、コンパイラはそれらを検出して報告します。
Assemble:-アセンブルコードはマシンコードに変換されます。アセンブラーを特別なタイプのコンパイラーと呼ぶことができます。
Linking:-これらのコードが他のソースファイルをリンクする必要がある場合、リンカはそれらをリンクして実行可能ファイルにします。
その後に起こる多くのプロセスがあります。はい、あなたはここにローダーの役割が来ると推測しました:
Loader:-実行可能コードをメモリにロードします。プログラムとデータスタックが作成され、レジスタが初期化されます。
少し余分な情報: http://www.geeksforgeeks.org/memory-layout-of-c-program/ 、そこにメモリレイアウトを見ることができます。
コンパイラ:これは、高水準言語プログラムを機械語プログラムに翻訳するプログラムです。コンパイラーはアセンブラーよりもインテリジェントです。あらゆる種類の制限、範囲、エラーなどをチェックします。しかし、プログラムの実行時間は長く、メモリの大部分を占めます。速度が遅い。コンパイラはプログラム全体を調べてから、プログラム全体をマシンコードに変換するからです。コンパイラーがコンピューターで実行され、同じコンピューターのマシンコードを生成する場合、それは自己コンパイラーまたは常駐コンパイラーと呼ばれます。一方、コンパイラーがコンピューターで実行され、他のコンピューターのマシンコードを生成する場合、それはクロスコンパイラーとして知られています。
リンカー:高レベル言語では、一部の組み込みヘッダーファイルまたはライブラリが保存されます。これらのライブラリは事前定義されており、プログラムの実行に不可欠な基本機能が含まれています。これらの関数は、リンカーと呼ばれるプログラムによってライブラリにリンクされています。リンカが関数のライブラリを見つけられない場合、コンパイラに通知し、コンパイラがエラーを生成します。コンパイラーは、プログラムをコンパイルする最後のステップとしてリンカーを自動的に呼び出します。ライブラリに組み込まれていませんが、ユーザー定義関数をユーザー定義ライブラリにリンクします。通常、長いプログラムは、モジュールと呼ばれる小さなサブプログラムに分割されます。そして、これらのモジュールを組み合わせてプログラムを実行する必要があります。モジュールを結合するプロセスは、リンカーによって行われます。
ローダー:ローダーは、プログラムのマシンコードをシステムメモリにロードするプログラムです。コンピューティングでは、ローダーはプログラムの読み込みを担当するオペレーティングシステムの一部です。プログラムを開始するプロセスの重要な段階の1つです。プログラムをメモリに配置し、実行のために準備するためです。プログラムを読み込むには、実行可能ファイルの内容をメモリに読み込む必要があります。ロードが完了すると、オペレーティングシステムは、ロードされたプログラムコードに制御を渡すことによってプログラムを開始します。プログラムの読み込みをサポートするすべてのオペレーティングシステムにはローダーがあります。多くのオペレーティングシステムでは、ローダーは永続的にメモリに常駐しています。
ウィキペディアには良い答えがあるはずです。私の考えは次のとおりです。
.cまたは.cppなどのタイプのソースファイルを読み取り、それをオブジェクトファイルとして呼び出される.oファイルに変換します。
複数のソースファイル用に生成される複数の.oファイルを実行可能ファイル(GCCのELF形式)に結合します。リンクには2つのタイプがあります。
実行可能ファイルをマシンのプライマリメモリにロードするプログラム。
Linuxでのプログラム実行のこれら3つの段階に関する詳細な調査については、 こちらをお読みください をご覧ください。
*
*
リンカーとローダー LinuxJournalがこの概念を明確に説明しています。また、古典的な名前a.outの由来も説明しています。 (アセンブラー出力)
簡単な要約、
c program --> [compiler] --> objectFile --> [linker] --> executable file (say, a.out)
実行可能ファイルを入手し、このファイルを友人またはこのソフトウェアを必要としている顧客に提供します:)
彼らがこのソフトウェアを実行するとき、例えばコマンドラインでそれをタイプすることによって./a.out
execute in command line ./a.out --> [Loader] --> [execve] --> program is loaded in memory
プログラムがメモリにロードされると、PC(プログラムカウンター)がa.out
の最初の命令を指すようにすることにより、制御がこのプログラムに転送されます。
オペレーティングシステム:オペレーティングシステム(OS)は、コンピューターハードウェアとソフトウェアリソースを管理し、コンピュータープログラムに共通のサービスを提供するシステムソフトウェアです。オペレーティングシステムは、コンピューターシステムのシステムソフトウェアのコンポーネントです。通常、アプリケーションプログラムを機能させるにはオペレーティングシステムが必要です。
コンパイラー:コンパイラーは、プログラミング言語(ソース言語)で記述されたソースコードを別のコンピューター言語(ターゲット言語)に変換するコンピュータープログラム(またはプログラムセット)です。後者は、多くの場合、オブジェクトとして知られるバイナリ形式です。コード。
インタープリター:インタープリターは、機械語プログラムにコンパイルすることなく、プログラミング言語またはスクリプト言語で記述された命令を直接実行、つまり実行するコンピュータープログラムです。
アセンブラー:アセンブラーは、基本的なコンピューター命令を受け取り、コンピューターのプロセッサーがその基本操作の実行に使用できるビットのパターンに変換するプログラムです。
ローダー:ローダーは、プログラムやライブラリのロードを担当するオペレーティングシステムの一部です。プログラムをメモリに配置し、実行のために準備するため、プログラムを開始するプロセスの重要な段階の1つです。
リンカー:リンカーは、オブジェクトモジュールを組み合わせて実行可能プログラムを形成するプログラムです。
Preproccesor:Preproccesorはテキスト置換ツールであり、実際のコンパイルの前に必要な前処理を行うようコンパイラーに指示します。
コンパイラは、プログラムのソースコードファイルを実行可能プログラムにコンパイルするソフトウェアプログラムです。ほとんどのプログラミングソフトウェアパッケージに統合開発環境IDEの一部として含まれています。コンパイラは、C、BASIC、Javaなどの高レベル言語で記述されたソースコードファイルを取得し、コードをマシンコードやアセンブリコードなどの低レベル言語にコンパイルします。このコードは、Intel PentiumやPowerPCなどの特定のプロセッサタイプ用に作成されます。その後、プログラムはプロセッサによって認識され、オペレーティングシステムから実行されます。
ローダーは、プログラムをストレージデバイスからメインメモリにコピーして実行できるオペレーティングシステムユーティリティです。プログラムをメインメモリにコピーするだけでなく、ローダーは仮想アドレスを物理アドレスに置き換えることもできます。ほとんどのローダーは透過的です。つまり、直接実行することはできませんが、オペレーティングシステムは必要に応じてそれらを使用します。
リンカーは、2つ以上の機械語プログラムセグメントを調整して、1つのユニットとして同時にロードおよび実行できるようにするプログラムです。リンカーは、リンクエディターおよびバインダーとも呼ばれ、オブジェクトモジュールを組み合わせて実行可能プログラムを形成するプログラムです。多くのプログラミング言語では、モジュールと呼ばれるさまざまなコードを個別に記述することができます。これにより、大きなプログラムをより管理しやすい小さな断片に分割できるため、プログラミングタスクが簡素化されます。ただし、最終的には、すべてのモジュールをまとめる必要があります。これがリンカの仕事です。
コンパイラの変更は、ソースコードのエラーをチェックし、オブジェクトコードに変更します。これは、オペレーティングシステムが実行するコードです。
多くの場合、プログラム全体を単一ファイルに記述しないため、リンカーはすべてのオブジェクトコードファイルをリンクします。
あなたのプログラムはメインメモリにない限り実行されません
リンカーとインタープリターは相互に排他的なインタープリターであり、コードを1行ずつ取得し、1行ずつ実行します。
コンパイラ:プログラム、オブジェクトファイル、メッセージなどのエラーを修正するシステムソフトウェアです
リンカ:1つまたは複数のオブジェクトファイルと可能なライブラリコードを、実行可能なライブラリまたはエラーのリストに結合するシステムソフトウェアです。
ローダー:実行可能ファイルをマシンのプライマリメモリにロードするプログラム
A Compilerコード行をプログラミング言語から機械語に変換します。
リンカーは、2つのプログラム間のリンクを作成します。
ローダープログラムをメインデータベース、プログラムなどのメモリにロードします。
コンパイラーは、特定のプログラミング言語で記述されたステートメントを処理し、コンピューターのプロセッサーが使用する機械語または「コード」に変換する特別なプログラムです。