プログラムが実行されるまで
これまでの要素を、1 つの流れとしてまとめる。
ビルド時#
hello.c
↓ プリプロセッサ #include, #define を展開
hello.i
↓ [[コンピュータ/言語処理系/コンパイラ|コンパイラ]] 字句→構文→意味解析→最適化
hello.s ([[アセンブリ]])
↓ アセンブラ
hello.o (オブジェクトファイル)
↓ [[リンカ]] libc などと結合
a.out ([[実行ファイル]])実行時#
シェルが fork → execve
↓ [[ローダ]]
仮想アドレス空間にマップ
↓ 動的リンカ (ld.so)
共有ライブラリを解決
↓
_start → __libc_start_main → main
↓
[[機械語]]が CPU で実行される
↓ [[コンピュータ/コンピュータアーキテクチャ/CPU|fetch-decode-execute]]各段階で何が確定するか#
| 段階 | 決まること |
|---|---|
| コンパイル | 命令列、レジスタ割り当て、最適化 |
| アセンブル | 機械語のビット列 |
| リンク | シンボルの対応、静的なアドレス |
| ロード | 実際の仮想アドレス(ASLR) |
| 実行 | 物理アドレス(ページフォルト時) |
遅く決めるほど柔軟になり、早く決めるほど速くなる。 静的リンクと動的リンク、 AOT と JIT の対比も、 すべてこの軸の上にある。
参考文献#
- Randal E. Bryant, David R. O’Hallaron. Computer Systems: A Programmer’s Perspective, 3rd ed. Pearson, 2016. https://csapp.cs.cmu.edu/
- John R. Levine. Linkers and Loaders. Morgan Kaufmann, 1999.
- Alfred V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman. Compilers: Principles, Techniques, and Tools, 2nd ed. Pearson, 2006.