はじめに
インフラエンジニアにとって、CPUやメモリといったコンピュータの基本的な仕組みを理解することは非常に重要です。しかし、日々の業務ではOSやミドルウェアの設定・運用に携わることが多く、CPUが内部でどのように命令を実行し、メモリを利用しているのかを意識する機会は少ないかもしれません。
一方で、Linuxカーネルが行うプロセス管理やメモリ管理、デバイス管理などのあらゆる処理は、最終的にはCPUによる命令実行とメモリアクセスによって実現されています。そのため、CPUの基本動作を理解することは、Linuxカーネルの仕組みを学ぶための土台となります。
本章では、CPUがプログラムを実行する際の基本的な流れである「フェッチ(Fetch)→デコード(Decode)→エグゼキュート(Execute)」について解説します。また、命令の実行に伴ってメモリがどのように利用されるのかを具体例を交えながら説明し、Linuxを理解するために必要な基礎知識を身につけていきます。
CPUの動作原理
CPUの動作原理はシンプルで、フェッチ(Fetch)、デコード(Decode)、エグゼキュート(Execute)という3つの処理が基本となります。それに加えて、命令の内容によってはロード(Load)、ストア(Store)が実行されます。

- フェッチ(Fetch)
メモリ上に保存されている命令を参照します。 - デコード(Decode)
命令デコーダにて命令を解読します。 - エグゼキュート(Execute)
解読した命令を実行します。演算が必要な場合はALU(算術論理演算器)によって処理されます。 - ロード(Load)
メモリ上のデータを使う命令が実行された場合に、メモリ上のデータを読み込みます。 - ストア(Store)
メモリ上にデータを保存する命令が実行された場合、データをメモリに格納します。
CPU処理におけるメモリ利用
もう少し具体的にCPUの処理の流れを見ながら、メモリの使われ方を理解してみましょう。CPUは「メモリアドレス」と呼ばれる番号でメモリ上の位置を指定し、そこに格納された命令やデータを読み書きしながら処理を進めていきます。イメージをつかみやすくするために、ここでは「数値の足し算」を例に、メモリがどのように使われるのかを見ていきましょう。
□データの読み込み①
まず、メモリに格納されているデータ「5」を汎用レジスタに読み込みます。
レジスタはCPU内部にある非常に高速な記憶領域です。演算対象のデータや計算結果を一時的に保持します。

1. 命令の参照・読み込み(フェッチ)
CPUがメモリ上に保存されている命令を参照します。この際、プログラムカウンタ(※)に保存されているメモリアドレスに対応する命令を参照する動作となります。本例では、アドレス「0x00000000」に対応する命令「READ X, 0x00001000」を参照して、CPU上の命令レジスタに読み込みます。命令レジスタに「READ X, 0x00001000」が格納されます。
2. 命令の解読(デコード)
命令デコーダにて命令の内容「READ X, 0x00001000」を解読し、命令を実行するための制御信号を生成します。
3. 命令の実行(エグゼキュート)
命令「READ X, 0x00001000」が実行され、汎用レジスタにデータ「5」が格納されます。(ロード)
※プログラムカウンタ:CPU内部に存在するレジスタの一種であり、「次に実行する命令が格納されているメモリアドレス」を保持しています。
□データの読み込み②
同様に、メモリに格納されているデータ「10」を汎用レジスタに読み込みます。処理の流れは先ほどと同じです。

4. プログラムカウンタ更新
プログラムカウンタを「0x00000000」から「0x00000001」に更新します。
5. 命令の参照・読み込み(フェッチ)
本例では、アドレス「0x00000001」に対応する命令「READ Y, 0x00001001」を参照し、CPU上の命令レジスタ(CPUが現在実行している命令を一時的に保持するレジスタ)に読み込みます。命令レジスタに「READ Y, 0x00001001」が格納されます。
6. 命令の解読(デコード)
命令デコーダにて命令の内容「READ Y, 0x00001001」を解読し、命令を実行するための制御信号を生成します。
7. 命令の実行(エグゼキュート)
命令「READ Y, 0x00001001」が実行され、汎用レジスタにデータ「10」が格納されます。
□演算結果の格納
続いて、ALU(算術論理演算器)によって演算を行い、汎用レジスタに演算結果を格納します。

8. プログラムカウンタ更新
プログラムカウンタを「0x00000001」から「0x00000010」に更新します。
9. 命令の参照・読み込み(フェッチ)
本例では、アドレス「0x00000010」に対応する命令「ADD X, Y」を参照し、CPU上の命令レジスタに読み込みます。命令レジスタに「ADD X, Y」が格納されます。
10. 命令の解読(デコード)
命令デコーダにて命令の内容「ADD X, Y」を解読し、命令を実行するための制御信号を生成します。
11. 命令の実行(エグゼキュート)
命令「ADD X, Y」が実行されるとALUにて演算が実行され、汎用レジスタに演算結果「15」が格納されます。

最後に、演算した結果をメモリに書き込みます。
12. プログラムカウンタ更新
プログラムカウンタを「0x00000010」から「0x00000011」に更新します。
13. 命令の参照・読み込み(フェッチ)
本例では、アドレス「0x00000011」に対応する命令「WRITE 0x00001002, Z」を参照し、CPU上の命令レジスタに読み込みます。命令レジスタに「WRITE 0x00001002, Z」が格納されます。
14. 命令の解読(デコード)
命令デコーダにて命令の内容「WRITE 0x00001002, Z」を解読し、命令を実行するための制御信号を生成します。
15. 命令の実行(エグゼキュート)
命令「WRITE 0x00001002, Z」が実行されると、汎用レジスタに格納されていたデータがメモリ上に書き込まれます。(ストア)
※実際にはCPUは毎回メインメモリへアクセスしているわけではなく、高速なキャッシュメモリを経由して処理を行うことで性能を向上させています。
まとめ
本章では、CPUが「フェッチ(Fetch)→デコード(Decode)→エグゼキュート(Execute)」という一連の処理を繰り返しながらプログラムを実行していることを学びました。また、命令の内容に応じてメモリからデータを読み込むロード(Load)や、演算結果をメモリへ書き込むストア(Store)が行われることも確認しました。
CPUはレジスタやメモリを利用しながら命令を順番に実行しており、私たちが普段利用しているLinuxやアプリケーションも、この基本動作の上で動いています。Linuxカーネルが行うプロセス管理やメモリ管理、システムコールの処理も、最終的にはCPUが命令を実行することで実現されています。
CPUの動作原理を理解しておくことで、Linuxカーネルがどのようにプログラムを実行し、システム全体を管理しているのかをより深く理解できるようになります。
Linuxのプロセス管理ついて、他の記事でもまとめているのでぜひ見てみてください。
【インフラエンジニア入門】Linuxのプロセス管理をわかりやすく解説|プロセスの生成および状態遷移
【インフラエンジニア入門】Linuxのプロセス管理をわかりやすく解説|リソース制限
【インフラエンジニア入門】Linuxのプロセス管理をわかりやすく解説|スケジューラ機能
参考文献





コメント