Linux CPUの仕組みを徹底解説|プロセス・スケジューラ・コンテキストスイッチの全体像

はじめに

Linuxサーバを運用していると、「CPU使用率が高い」「ロードアベレージが上がっている」「コンテキストスイッチが増えている」といった状況に遭遇することがあります。しかし、それらの数値を確認できても、「CPUの内部で実際に何が起きているのか」を説明できる人は意外と多くありません。

CPUは、アプリケーションが実行する命令を処理する、コンピュータの中心的な存在です。一方でLinuxカーネルは、多数のプロセスがCPUを公平かつ効率的に利用できるように、スケジューリングや割り込み処理、システムコールなど、さまざまな仕組みを提供しています。

CPUの動作を理解すると、「なぜコンテキストスイッチが発生するのか」「なぜシステムコールが必要なのか」「割り込みはどのように処理されるのか」といったLinux内部の動きを体系的に理解できるようになります。これは、日々の運用や障害対応だけでなく、Linuxをより深く理解するための大きな助けになります。

本シリーズでは、CPUの基本的な役割から始まり、プロセスとスケジューラの関係、コンテキストスイッチ、システムコール、割り込み、CPUキャッシュ、マルチコアCPUまで、LinuxにおけるCPUの仕組みを順を追って解説していきます。

第1回となる本記事では、CPUの役割やLinuxとの関係を俯瞰しながら、シリーズ全体の土台となる「CPUの全体像」を分かりやすく解説します。

CPUとは何か

CPU(Central Processing Unit)は、コンピュータの中でプログラムの命令を実行する装置です。人間に例えると「頭脳」のような存在であり、アプリケーションから指示された処理を次々と実行していきます。

例えば、lsコマンドでディレクトリの内容を表示したり、cpコマンドでファイルをコピーしたり、systemctlコマンドでサービスを起動したりといった操作は、一見するとそれぞれ異なる処理が行われているように見えます。しかし、CPUから見ると、これらはすべてプログラムを構成する命令を実行することで実現されています。

CPUが実行する命令には、次のようなものがあります。

  • 数値の加算や減算などの演算
  • データの比較
  • メモリへの読み書き
  • 条件による分岐
  • 繰り返し処理
  • 関数の呼び出し

複雑なアプリケーションであっても、最終的にはこうした単純な命令の組み合わせによって動作しています。

CPUとメモリ・ストレージの違い

CPUは処理を実行する役割を担いますが、それだけではプログラムを動かすことはできません。実際には、メモリやストレージと連携しながら処理を進めています。

それぞれの役割は次のとおりです。

構成要素主な役割
CPUプログラムの命令を実行し、計算や制御を行う「頭脳」の役割を担う
メモリ(RAM)実行中のプログラムやデータを一時的に保存し、CPUが高速にアクセスできるようにする
ストレージ(SSD・HDD)OSやアプリケーション、各種データを電源を切っても保持する長期保存領域

例えば、ユーザーがlsコマンドを実行すると、ストレージ上の実行ファイルがプロセスの仮想アドレス空間へマッピングされ、実行に必要な命令やデータがメモリへ読み込まれます。その後、CPUが命令を順番に実行することで、ディレクトリ内の情報が取得され、結果が標準出力へ表示されます。

つまり、CPU・メモリ・ストレージはそれぞれ異なる役割を持ち、協力してコンピュータを動かしているのです。

LinuxにおけるCPUの役割

Linuxでは、多数のプロセスやスレッドが同時に実行されています。しかし、CPUが実際に命令を実行できるのは、一つのCPUコアにつき基本的に一つの処理だけです。

そこでLinuxカーネルは、「どのプロセスにCPUを割り当てるか」を管理しています。CPUを効率良く共有するために、プロセスの切り替えや優先順位の制御、割り込み処理など、さまざまな仕組みが用意されています。

こうしたLinuxとCPUの関係について順番に学びながら、「CPUはどのようにプログラムを実行しているのか」を詳しく見ていきます。

CPUを構成する主な要素

CPUは一つの部品のように見えますが、内部にはさまざまな機能を持つ回路が組み込まれています。それぞれが役割を分担することで、プログラムの命令を高速に実行しています。

ここでは、CPUを構成する代表的な要素を簡単に紹介します。

コア(Core)

コアとは、実際にプログラムの命令を実行する処理装置です。

以前のCPUは1つのコアしか持っていませんでしたが、現在では複数のコアを搭載するマルチコアCPUが一般的になっています。例えば、8個のコアを持つCPUでは、各コアで異なる命令列を並行して実行できます。そのため、複数のアプリケーションを並行して実行した場合でも、高い処理性能を発揮できます。

Linuxでは、CPUスケジューラが各コアへプロセスやスレッドを割り当てることで、CPU資源を効率よく利用しています。

スレッド(SMT / Hyper-Threading)

SMT(Simultaneous Multi-Threading)は、一つの物理コアで複数のスレッドの命令を並行して処理する技術です。Linuxからは、それぞれが論理CPUとして認識されます。IntelではHyper-Threadingという名称で知られています。

例えば、4コアCPUでHyper-Threadingが有効な場合、Linuxからは8個のCPUとして認識されます。論理CPUが増えることでCPUの空き時間を有効活用できるため、多くのワークロードで処理効率が向上します。

ただし、物理コアが8個に増えるわけではなく、同じコア内の演算器やキャッシュなど、一部の資源を共有します。

レジスタ

レジスタは、CPU内部にある非常に高速な記憶領域です。

CPUが演算を行う際は、多くの場合、メモリ上のデータをレジスタへ読み込み、レジスタ上の値を使って処理します。レジスタは容量こそ非常に小さいものの、CPU内部にあるためメモリアクセスよりも圧倒的に高速です。プログラムカウンタやスタックポインタなど、さまざまな用途のレジスタが存在します。

キャッシュ

CPUキャッシュは、CPUが利用する命令やデータを一時的に保持する高速な記憶領域です。

通常、CPUがデータを取得するにはメインメモリ(RAM)へアクセスします。しかし、メモリアクセスはCPUの処理速度と比べると遅いため、毎回メモリへアクセスすると性能が低下してしまいます。そこで、一度読み込んだデータをキャッシュへ保存しておき、再度利用する際は高速にアクセスできるようにしています。

一般的なCPUでは、L1キャッシュ、L2キャッシュ、L3キャッシュという複数階層のキャッシュが搭載されています。

制御装置(Control Unit)

制御装置は、CPU全体の動作を管理する役割を持っています。プログラムから命令を読み取り、その命令をどのように実行するかを判断し、CPU内部の各回路へ指示を出します。

例えば、「データをレジスタへ読み込む」「ALUで計算する」「メモリへ結果を書き込む」といった処理の流れを制御しています。

CPUが正しい順序で命令を実行できるのは、この制御装置が全体を管理しているためです。

ALU(算術論理演算装置)

ALU(Arithmetic Logic Unit)は、計算や比較を行う回路です。具体的には、次のような処理を担当しています。

  • 加算・減算
  • 乗算・除算(一部は専用回路が担当)
  • 大小比較
  • AND、OR、XORなどの論理演算

例えば、「1 + 2を計算する」「変数AとBを比較する」といった命令は、ALUによって実行されます。

Linuxから見たCPU

CPUはプログラムの命令を実行する装置ですが、どのプログラムをいつCPUへ割り当てるかはLinuxカーネルが管理しています。

Linuxでは、多数のプロセスやスレッドが同時に動作しています。そのため、LinuxカーネルはCPUスケジューラを使い、実行可能なプロセスやスレッドの中から次に実行する対象を選択します。

実行対象を切り替える際には、現在の状態を保存し、次に実行するプロセスやスレッドの状態を復元します。この処理をコンテキストスイッチと呼びます。

また、アプリケーションがファイルの読み書きやネットワーク通信などを行う場合は、システムコールを通じてLinuxカーネルへ処理を依頼します。

一方、ネットワークパケットの受信やストレージI/Oの完了など、デバイス側で発生したイベントは、割り込みによってCPUへ通知されます。

このようにLinuxカーネルは、CPUスケジューラ、コンテキストスイッチ、システムコール、割り込みなどの仕組みを組み合わせることで、CPUを効率的に利用しています。

CPUでプログラムが動く流れ

ここまで、CPUの役割やLinuxカーネルとの関係について説明してきました。ここでは、Linux上でプログラムを起動してからCPUで実行されるまでの全体の流れを見ていきます。

① プログラムを実行する

まず、ユーザーがLinuxコマンドを実行したり、systemdがサービスを起動したりすることで、プログラムの実行が開始されます。Linuxカーネルは、指定されたプログラムを実行するために必要な準備を行います。

② プロセス/スレッドを生成する

プログラムを実行するためのプロセスやスレッドが生成され、実行に必要な情報が準備されます。プログラムのコードやデータなどは仮想アドレス空間を通じて利用できる状態となり、CPUで実行できるようになります。

③ CPUスケジューラが実行対象を選択する

実行可能なプロセスやスレッドが、すべて同時にCPUを利用できるわけではありません。CPUスケジューラは、実行可能なプロセスやスレッドの中から、次にCPUで実行する対象を選択します。時間経過や優先度、I/O待ちなどによって実行状態が変化すると、スケジューラによって実行対象が切り替えられます。

④ CPUが命令を実行する

CPUスケジューラによって選択されたプロセスやスレッドは、CPU上で実際に命令を実行します。CPUは命令を読み取り、レジスタやALUなどを利用して演算やメモリアクセスなどの処理を行います。通常はこの処理を繰り返しながら、プログラムの実行を進めていきます。

⑤ システムコールでカーネルへ処理を依頼する

プログラムの実行中に、ファイルI/Oやネットワーク通信、メモリ確保などOSの機能が必要になることがあります。その場合、プログラムはシステムコールを利用してLinuxカーネルへ処理を依頼します。システムコールは、実行中のプログラムから発生する同期的な処理です。カーネル側の処理が完了すると、基本的にはプログラム側へ処理が戻り、実行を継続します。

⑥ 割り込みに対応する

CPUでプログラムを実行している間にも、デバイス側ではさまざまなイベントが発生します。例えば、ネットワークパケットの受信やストレージI/Oの完了などです。このようなイベントが割り込みとして通知されると、CPUは実行中の処理を一時的に中断して、必要な割り込み処理を実行します。システムコールがプログラムから要求される同期的な処理なのに対し、ハードウェア割り込みはデバイスなどから発生する非同期なイベントという違いがあります。

⑦ プログラムの実行を継続する

システムコールや割り込みなどの処理が完了すると、CPUはプログラムの実行を継続します。CPUは次の命令へ進み、命令の読み取りや演算、メモリアクセスなどを繰り返します。このようにしてプログラムの処理が進んでいきます。

⑧ コンテキストスイッチで実行対象を切り替える

CPUは、常に同じプロセスやスレッドだけを実行しているわけではありません。タイムスライスの消費やI/O待ち、より優先度の高いタスクの実行などによって、別のプロセスやスレッドへCPUを割り当てる必要があります。その際、Linuxカーネルは現在の実行状態を保存し、次に実行するプロセスやスレッドの状態を復元します。この実行対象の切り替えをコンテキストスイッチと呼びます。切り替え後は、CPUスケジューラによって選択された新しいプロセスやスレッドの実行が開始されます。

まとめ

CPUは、プログラムの命令を実行するコンピュータの中心的な装置です。しかし、CPUだけでは複数のアプリケーションを効率よく動作させることはできません。Linuxでは、CPUスケジューラによるプロセスの切り替えやコンテキストスイッチ、システムコール、割り込みなど、さまざまな仕組みが連携することで、CPUを効率的に活用しています。

本記事では、その全体像として、CPUの役割や構成要素、Linuxから見たCPUの仕組み、そしてプログラムがCPU上で実行されるまでの流れについて紹介しました。CPUの仕組みを理解することで、Linux内部で何が起きているのかを体系的に理解できるようになります。

LinuxにおけるCPUの仕組みについては、以下の書籍にまとめています。興味がありましたら、ぜひ読んでみてください。

Linux入門・図解

LinuxのCPUの仕組みを
図解で理解したい方へ

命令実行・プロセス・スケジューラ・割り込み・ キャッシュ・マルチコアなど、 LinuxにおけるCPUの仕組みを図解を中心にわかりやすく解説しています。

Kindleで書籍を見る →

コメント