リンクとロード、プログラムの性質
原始プログラムが「コンパイラ→リンカ→ローダ」を経て実行されるまでの流れと、それぞれの道具の役割を区別できるようになる。あわせて、再入可能・再使用可能・再配置可能・再帰的という4つの性質を、選択肢の説明文から正しく選べるようになる。
「〜の機能として適切なものはどれか」と聞かれ、隣の道具の説明が選択肢に並ぶ、典型的な暗記問題です。特にプログラムの性質は公開過去問で18回(うち免除15回)観測されており、表を1枚覚えれば確実に1点取れます。
このレッスンで稽古する(用語チェック・過去問)結論:翻訳から実行までは3段のリレー
書いたプログラムがそのまま動くわけではありません。コンパイラ → リンカ → ローダの順に受け渡され、最後に主記憶(メモリ)に載ってCPUが実行します。どの道具が何を受け取って何を出すか、の入出力を覚えれば流れ図の問題は解けます。
flowchart LR
A["原始プログラム"] --> B["コンパイラ"]
B --> C["目的プログラム"]
C --> D["リンカ"]
L["ライブラリモジュール"] --> D
D --> E["ロードモジュール"]
E --> F["ローダ"]
F --> G["主記憶に載って実行"]
- 原始プログラム(ソースプログラム):人が書いたプログラム。
- 目的プログラム(目的モジュール・オブジェクトモジュール):コンパイラが機械語に翻訳した部品。単体ではまだ動かない。
- ライブラリモジュール:よく使う処理を部品としてまとめて保管しておいたもの。
- ロードモジュール:部品をつなぎ合わせた、実行できる完成形。
「目的」が先、「ロード」が後、と名前で覚えます。ロードモジュールは「ローダに渡す(ロードする)ためのモジュール」だからローダの直前です。
リンカとローダ、まぎらわしい周辺の道具
リンカ(連係編集プログラム)は、複数の目的モジュールやライブラリモジュールを結合し、1つのロードモジュールを作ります。その際、部品Aが部品Bの処理を呼んでいる、といった相互参照(部品どうしの呼び先)を実際の場所に結び付けます。本の各章を1冊に製本し、「詳しくは第3章参照」を実際のページ番号に書き換える作業に似ています。
試験では、リンカの選択肢に次の道具の説明が混ぜられます。
| 道具 | やること | キーワード |
|---|---|---|
| コンパイラ | 原始プログラムを目的プログラムに一括翻訳 | 翻訳 |
| リンカ | 目的モジュールなどを結合し、相互参照を解決してロードモジュールを作る | 結合・相互参照・ロードモジュールを生成 |
| ローダ | ロードモジュールを主記憶に読み込む | 主記憶にロード |
| ライブラリアン | 作ったプログラムをライブラリに登録・管理する | ライブラリに登録 |
| デバッガ/トレーサ | 実行を監視し、ステップごとの結果を記録する | 監視・記録 |
もう1つ、OS周りの役割を区別する問題も出ています。
| 役割 | やること |
|---|---|
| デバイスドライバ | アプリの要求に従って、プリンタやディスクなどのハードウェアを直接制御するOSの部品 |
| スケジューラ(タスク管理) | 実行待ちのタスクから次に動かすものを決める |
| ウィンドウマネージャ | 画面上の複数ウィンドウの表示状態を管理する |
| シェル(コマンドインタプリタ) | 入力されたコマンド文字列を解釈してプログラムを起動する |
静的リンキングと動的リンキング
リンクするタイミングの違いです。実行前にまとめて結合するのが静的、実行時に必要になってから結合するのが動的です。
| 方式 | 結合のタイミング | 特徴 |
|---|---|---|
| 静的リンキング | 実行前(リンカがロードモジュールを作るとき) | 必要なライブラリモジュールがロードモジュールに組み込まれる(実行時に別ファイルを必要としない) |
| 動的リンキング | 実行時 | 共有ライブラリ(WindowsのDLLなど)を実行中に結合する。複数プログラムで部品を共有でき、ライブラリの差し替えも再リンク不要 |
「実行時に結合」と書いてあれば動的リンキングです。選択肢にはオーバレイ(主記憶が小さいとき、必要な部分を補助記憶から順に同じ領域へ読み込んで使う手法)や、インタプリタ(1行ずつ解釈実行する言語処理系)が並びますが、どちらも「モジュールの結合」の話ではありません。
プログラムの4つの性質(最頻出)
「再〜可能」が4つ並ぶので、何を「再」するのかで区別します。ここは表ごと覚えてください。
| 性質 | カタカナ | 何ができるか | 見分けるキーワード |
|---|---|---|---|
| 再入可能 | リエントラント | 複数のプロセス(タスク)から同時に呼ばれても、互いに干渉せずそれぞれに正しい結果を返す | 同時・並行・干渉しない・処理が終わっていないうちに再度呼ばれる |
| 再使用可能 | リユーザブル | 一度実行したあと、主記憶にロードし直さずにもう一度実行しても正しく動く(同時ではなく順番に) | 再ロード不要・一度実行後に再び |
| 再配置可能 | リロケータブル | 主記憶のどのアドレスに置いても実行できる | どこのアドレスでも・配置 |
| 再帰的 | リカーシブ | 手続きの中から自分自身を呼び出せる | 自分自身を呼ぶ |
再入可能のしくみは、料理教室のたとえで考えると分かりやすいです。レシピ(命令部分)は全員で1枚を共有し、まな板(データ・変数)は1人1枚ずつ用意します。まな板を共有すると、別の人が切った材料が混ざって結果が狂う(干渉する)ので、データを呼び出し元ごとに分けておくのが再入可能の条件です。
関係も押さえておくと安心です。同時に呼ばれても大丈夫な再入可能プログラムは、順番に使い回す再使用可能の条件も満たします。また、再帰的に自分を呼ぶと「処理が終わっていないのに再度呼ばれる」状態になるため、再帰的プログラムは再入可能に作る必要があります。
試験での問われ方
- 性質の名前を選ぶ型:説明文が先に出て「この性質は何か」。「同時」「終了していないときに再度」が出たら**再入可能(リエントラント)**一択です。
- 説明文を選ぶ型:「再入可能の特徴はどれか」。選択肢に再配置可能(どのアドレスでも)・再帰的(自分自身を呼ぶ)・オーバレイ(補助記憶から読み込みながら)の説明が並びます。
- 道具の機能を選ぶ型:「リンカの機能は?」。ローダ(主記憶にロード)・ライブラリアン(ライブラリに登録)・デバッガ(ステップごとに記録)の説明が並びます。
- 流れ図の穴埋め型:a・b・cに目的プログラム/ライブラリモジュール/ロードモジュールを入れる。目的プログラムとロードモジュールを入れ替えた選択肢が罠です。
流れ図の a・b・c を埋める
ア a=目的プログラム,b=ライブラリモジュール,c=ロードモジュール
イ a=ライブラリモジュール,b=ロードモジュール,c=目的プログラム
ウ a=ロードモジュール,b=目的プログラム,c=ライブラリモジュール
エ a=ロードモジュール,b=ライブラリモジュール,c=目的プログラム
解き方と答えを見る
- コンパイラの出力 a を考える。コンパイラは原始プログラムを翻訳して「目的プログラム」を出す。よって a=目的プログラム。この時点で a がロードモジュールやライブラリモジュールになっているイ・ウ・エは消える。
- リンカへ上から入るもう1つの入力 b を考える。リンカは目的プログラムに、よく使う部品を結合する。その部品が「ライブラリモジュール」なので b=ライブラリモジュール。
- リンカの出力 c を考える。結合して作るのは実行できる完成形の「ロードモジュール」。そしてそれがローダに渡される流れとも一致する。よって c=ロードモジュール。
- a=目的プログラム、b=ライブラリモジュール、c=ロードモジュールの組合せはア。
答え:ア(a=目的プログラム、b=ライブラリモジュール、c=ロードモジュール)
再入可能プログラムの特徴を消去法で選ぶ
ア 主記憶上のどこのアドレスに配置しても,実行することができる。
イ 手続の内部から自分自身を呼び出すことができる。
ウ 必要な部分を補助記憶装置から読み込みながら動作する。主記憶領域の大きさに制限があるときに,有効な手法である。
エ 複数のタスクからの呼出しに対して,並行して実行されても,それぞれのタスクに正しい結果を返す。
解き方と答えを見る
- ア「どこのアドレスに配置しても実行できる」→ 配置の話なので再配置可能(リロケータブル)。除外。
- イ「内部から自分自身を呼び出せる」→ 自分を呼ぶので再帰的(リカーシブ)。除外。
- ウ「必要な部分を補助記憶装置から読み込みながら動作」→ 主記憶が小さいときの手法なのでオーバレイ。除外。
- エ「複数のタスクから並行して呼ばれても、それぞれに正しい結果を返す」→ 同時・並行・干渉しないので再入可能(リエントラント)。
答え:エ
要点(試験直前に読む)
- 流れは 原始プログラム →コンパイラ→ 目的プログラム →リンカ(+ライブラリモジュール)→ ロードモジュール →ローダ→ 主記憶で実行。
- リンカ=結合して相互参照を解決し、ロードモジュールを生成。ローダ=主記憶にロード。ライブラリアン=ライブラリに登録。
- 実行時に結合するのが動的リンキング、実行前に結合するのが静的リンキング。
- 再入可能=同時に呼ばれても干渉しない/再使用可能=再ロードなしで再実行できる/再配置可能=どのアドレスでも動く/再帰的=自分自身を呼ぶ。
- 再入可能はデータを呼び出し元ごとに分けて、命令部分だけを共有する。
- デバイスドライバはハードウェアを直接制御するOSの部品。
ひっかけ
- 目的プログラムとロードモジュールの入れ替え:コンパイラの直後が目的、ローダの直前がロードと位置で確認する。
- リンカの選択肢に「ロードモジュールを主記憶にロード」が混ざる:それはローダ。リンカは『作る』まで。
- 「処理が終わっていないうちに別のプログラムから再度呼ばれても正しく動く」を再帰的と誤る:自分自身を呼ぶ話ではないので再入可能。
- 再入可能の説明問題にオーバレイ(補助記憶から読み込みながら動作)や再配置可能(どのアドレスでも)の説明が混ざる:キーワード『同時・並行・干渉しない』だけを探す。
- 実行時の結合を問う問題にオーバレイやインタプリタが並ぶ:『モジュールの結合』を実行時に行うのは動的リンキングだけ。
用語(16)
人がプログラム言語で書いた、翻訳前のプログラム。
⚠ 目的プログラムは翻訳後のもの。「原始」は一番最初と覚える。
コンパイラが原始プログラムを機械語に翻訳した部品で、単体ではまだ実行できないもの。
⚠ ロードモジュールは結合済みで実行できる完成形。目的プログラム→リンカ→ロードモジュールの順。
よく使う処理を再利用できるよう部品として保管したもので、リンカで目的プログラムと結合される。
⚠ 流れ図ではリンカへの『もう1つの入力』として横や上から入る。
リンカが部品を結合して作った、実行可能な形式のプログラム。
⚠ 目的プログラムと取り違えやすい。ローダに渡す直前のものがロードモジュール。
原始プログラムをまとめて機械語に翻訳し、目的プログラムを出力する言語処理プログラム。
⚠ インタプリタは1行ずつ解釈しながら実行し、目的プログラムを作らない。
複数の目的モジュールやライブラリモジュールを結合し、相互参照を解決して1つのロードモジュールを作るプログラム。
⚠ ローダは主記憶に読み込む係。「生成・結合」ならリンカ、「主記憶にロード」ならローダ。
ロードモジュールを実行に先立って主記憶に読み込むプログラム。
⚠ リンカと混同しやすい。ローダはロードモジュールを作らない。
作成したプログラムをライブラリに登録・管理するプログラム。
⚠ リンカの誤答選択肢「ライブラリに登録する」の正体。
アプリケーションの要求に従い、周辺機器などのハードウェアを直接制御するOSの部品。
⚠ 次のタスクを決めるのはスケジューラ、コマンドを解釈するのはシェル、ウィンドウ表示を管理するのはウィンドウマネージャ。
実行前にリンカが必要なライブラリモジュールを結合し、ロードモジュールに組み込んでおく方式。
⚠ 動的リンキングは実行時に結合する。
プログラムを構成するモジュールの結合を、実行時に行う方式。
⚠ オーバレイは主記憶の領域を使い回す手法で、結合の方式ではない。
主記憶が小さいとき、プログラムを分割し、必要な部分を補助記憶から同じ領域に読み込みながら実行する手法。
⚠ 再入可能の誤答選択肢として「補助記憶から読み込みながら動作」の形で出る。
複数のプロセスから同時に呼ばれても、互いに干渉せずそれぞれに正しい結果を返せる性質。
⚠ 再使用可能は『順番に』使い回せる性質で、同時実行は保証しない。「同時・並行」なら再入可能。
一度実行した後、主記憶にロードし直さずに再び実行しても正しく動く性質。
⚠ 再入可能と混同しやすい。再使用可能は逐次(1つずつ)の使い回し。
主記憶上のどのアドレスに配置しても実行できる性質。
⚠ 「アドレス・配置」が出たら再配置可能。
手続きの内部から自分自身を呼び出すことができる性質。
⚠ 「別のプログラムから再度呼ばれる」は再入可能。「自分自身を呼ぶ」が再帰的。
このレッスンの過去問
- 言語処理プログラムの入出力(コンパイラ・リンカ・ローダ)平成27年度 秋期 基本情報技術者試験 午前 問11
- リンカの機能平成30年度 秋期 基本情報技術者試験 午前 問20
- 動的リンキングの定義平成24年度 秋期 基本情報技術者試験 午前 問20
- プログラムの性質(再入可能・再使用可能・再配置可能・再帰的)平成31年度 春期 基本情報技術者試験 午前 問8