【Linux カーネル: OS 入門3】メモリ管理

メモリとは

メモリとは、CPU が直接読み書きする領域です。
CPU で実行するプログラム (プロセス) を置いたり、実行した結果を読み書きする領域です。
Linux カーネルの機能
スポンサーリンク

メモリ管理とは

メモリ管理とはメモリ管理とは、以下のカーネルの機能のことです。
・メモリにプロセス (実行中のプログラム) を割り当てる
・メモリから不要なプロセスを開放 (スワップ、ページング、OOM Killer)
プログラムプロセスサイズが同じとは限りません

スワップ (swap) とは

スワップとは、次の2つの処理のことです。
・メモリ不足を解消するために、プロセスをメモリからスワップ領域に移動(スワップアウト)
CPU で実行するために、プロセスをスワップ領域からメモリに移動(スワップイン)

なお、「スワップ領域」は通常、「ストレージの領域の一部」に確保します。

メモリと比較して、ストレージへのアクセスはとても遅いので、スワップが発生するとコンピュータの処理は遅くなります。

ページとは

ページとは、メモリを管理する単位です。

ページサイズは以下のコマンドで確認できます。

getconf PAGESIZE
4096

ページングとは

ページングとは、スワップとほぼ同義ですが、厳密には次の違いがあります。
・スワップ:プログラム」単位でメモリとストレージ間を転送
・ページング:「ページ」単位でメモリとストレージ間を転送

歴史的には「スワッピング」はプログラム全体を二次記憶に転送(あるいは二次記憶から主記憶に転送)することを意味する[4][5]

1960年代にセグメント方式とページング方式の仮想記憶の概念が登場すると、「スワッピング」という用語はセグメント単位およびページ単位の二次記憶と主記憶間の転送を意味するようになった。今日の仮想記憶はほとんどがページング方式となったため、「スワッピング」は「ページング」とほぼ同義に使われることもある。

https://ja.wikipedia.org/wiki/%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%B0%E6%96%B9%E5%BC%8F

OOM (Out Of Memory) とは

OOM (Out Of Memory) とは、「メモリ/スワップ領域」が不足している状況で、メモリを確保すると発生するエラーです。

Linux カーネルは、メモリ上のキャッシュを解放することで Out Of Memory を回避します。

もし、開放可能なメモリが存在しない場合、OOM Killer が発生します。

OOM Killer とは

OOM Killerとは、Linux カーネルが適当なプロセスを kill(強制終了)することです。

メモリコンパクション

メモリコンパクションとは、バラバラになった空き領域を連続させることです。

物理メモリが連続しているとアクセスが早いため、次の利用に備えて空き領域を連続させます。

スポンサーリンク

仮想メモリ (Virtual Memory)

仮想メモリ仮想メモリとは、「物理メモリ」 + 「ストレージのスワップ領域」のことです。
仮想メモリと対比するために、実在するメモリを「物理メモリ」と言います。
https://www.tutorialspoint.com/operating_system/os_virtual_memory.htm

仮想メモリの役割

仮想メモリの役割は主に以下の3つです。

メモリ領域の拡張

仮想メモリは、スワップを追加の領域とすることで、物理メモリ以上にプロセスを割り当て可能です。
物理メモリが不足しているため、割り当てられない
不要なプロセスをページ単位でスワップ領域に退避

メモリ保護

メモリ保護とは、物理メモリ上に他のプロセスカーネルが存在する場合、上書きを禁止する機能です。
プログラムが指定したアドレスにそのまま上書き
仮想メモリを物理メモリの上書きを禁止
別の物理アドレスにマッピング

フラグメンテーション

フラグメンテーションとは、メモリが小さな単位に分割されてしまうことです。
フラグメンテーションは、確保していたメモリが解放されることで発生

フラグメンテーションが発生すると、大きなプロセスを割り当てるメモリがなくなります。
プロセスの割り当ては、メモリが連続している必要があります

仮想メモリでの対策

仮想メモリでは、プロセスをページ単位に分割することで、連続していないメモリ領域にプロセスを割り当て可能とします。

物理メモリは連続した領域にプロセスを配置する必要がある
仮想メモリはページに分割し、フラグメンテーションに対応

仮想アドレスと物理アドレスの変換

仮想アドレスは次の流れで物理アドレスに変換されます。

MMU (Memory Management Unit) とは

MMU とは、主に次の機能を持つ CPU の一部※です。
・「仮想アドレス」と「物理アドレス」の変換
・メモリ保護
・ページフォールト

※MMUはかつては単体でICチップなどとして提供され、主基板(マザーボード)に装着して使用したが、現代の一般的なCPU製品の多くはMMUの機能を内部に取り込み一体化している。

https://e-words.jp/w/MMU.html

TLB (Translation Lookaside Buffer) とは

TLB とは、仮想アドレスと物理アドレスの対応をキャッシュする CPU の一部です。

CPU(マイクロプロセッサ/MPU)内部に実装されている。

https://e-words.jp/w/TLB.html

ページテーブルとは

ページテーブルとは、ページごとの仮想アドレスと物理アドレスの対応表です。
ページテーブルは、メモリのカーネル領域に記憶されてます。
ページサイズが 100 Bytes の場合

プロセス終了までアクセスしない領域は、物理メモリは無駄に消費してしまいます。これを防ぐためにデマンドページングという方式が採用されてます。

デマンドページングとは
デマンドページングとは、仮想アドレスに対応するページにアクセスした時に物理アドレスを確保する方法です。

デマンドページングの処理は以下のとおりです。

  1. プロセス生成時は仮想アドレス空間に対するページのみを記録
  2. CPU がページにアクセスすると、仮想アドレスに対応する物理アドレスが無いことを検出
  3. CPU がページフォールトが発生
  4. カーネルがページに物理メモリを割り当て (ページテーブルを更新)

仮想メモリの方式

仮想メモリは、次の2種類の方式を組み合わせた「ページ化セグメンテーション」で実現します。

ページング方式とは

ページング方式とは、仮想アドレスと物理アドレスの対応をページ単位で管理する方式です。

つまり、今まで説明してきた方式です。

ページサイズが 100 Bytes の場合

セグメント方式とは

セグメント方式とは、仮想アドレスと物理アドレスの対応をセグメント単位で管理する方式です。
セグメントとは
セグメントとは、データの種類ごとの区分のことです。

プロセス (実行中のプログラム) は、次のセグメントを持ちます。

セグメント説明
テキストCPU が実行する機械語命令 (プログラム本体)
データ初期化済みの static 変数 or グローバル変数
bss初期化していない static 変数 or グローバル変数
ヒーププロセス実行時に動的に確保される領域 (malloc 等)
共有ライブラリ他のプロセスと共有するライブラリ
スタックスコープが終了すると消えるデータ (ローカル変数、関数パラメータ、メソッド等)

セグメント方式は、次のようにセグメント単位でプロセスを管理します。

ページ化セグメンテーション方式とは

ページ化セグメンテーション方式とは、ページング方式とセグメント方式を組み合わせた方式です。

セグメントをページ単位で分割して管理します。

参考資料:http://www.matlab.nitech.ac.jp/~matsuo/OS/OS10.pdf

なお、物理メモリが不足している場合は、ページング (スワップ) が行われます。

ページング対象となるページは、ページ置換アルゴリズムで選択します。

ページ置換アルゴリズム

代表的なページ置換アルゴリズム2つを紹介します。

  • First In First Out (FIFO) algorithm
  • Least Recently Used (LRU) algorithm

その他のアルゴリズムについては wiki にまとまっているのでご覧ください。

ページ置換アルゴリズム - Wikipedia

First In First Out (FIFO) algorithm

一番古いページを置き換えるアルゴリズムです。

https://www.tutorialspoint.com/operating_system/os_virtual_memory.htm

Least Recently Used (LRU) algorithm

最も長く使用していないページが置換されます。

FIFO と異なり、古いページでも最近利用されている場合は置換されません。

https://www.tutorialspoint.com/operating_system/os_virtual_memory.htm
スポンサーリンク

メモリに関するコマンド

仮想メモリの確認コマンド

cat /proc/<プロセス ID>/maps でプロセスの仮想メモリを確認できます。

sudo cat /proc/1/maps
556eb7400000-556eb755a000 r-xp 00000000 ca:01 111835                     /usr/lib/systemd/systemd
556eb775a000-556eb777d000 r--p 0015a000 ca:01 111835                     /usr/lib/systemd/systemd
556eb777d000-556eb777e000 rw-p 0017d000 ca:01 111835                     /usr/lib/systemd/systemd
556eb7d5a000-556eb7e70000 rw-p 00000000 00:00 0                          [heap]
7fd07be12000-7fd07be16000 r-xp 00000000 ca:01 12584301                   /usr/lib64/libuuid.so.1.3.0
(中略)
7ffc7809e000-7ffc780bf000 rw-p 00000000 00:00 0                          [stack]

以下のセグメントで管理されていることが確認できます。

なお、パーミッションが r-xp のものはテキストセグメント、rw-p のものはデータセグメントです。

The r-xp region at 0x400000 is your text (code) section. It's readable, and executable, but not writable.

The rw-p region at 0x600000 is your data section. It's readable and writable, but not executable.

https://stackoverflow.com/questions/19018253/content-of-proc-pid-maps

物理メモリ使用率の確認コマンド

free コマンドで物理メモリの使用率、および内訳を確認できます。

free
              total        used        free      shared  buff/cache   available
Mem:        8063684      358512     7180624         652      524548     7473952
項目説明
totalシステムに搭載されているメモリ
usedカーネルや各プロセスが利用しているメモリの総量
正確には total - free -buffers - cache
free見かけ上の空き容量
buff/cacheカーネル内にあるバッファキャッシュとページキャッシュの総量
availablefree + カーネル内メモリ領域の開放可能なメモリ
バッファキャッシュとページキャッシュの違いはこちら

関連情報

Linux カーネルの機能

参考サイト

以下のサイトを参考にしました。

Operating System - Memory Management
Operating System Memory Management - This tutorial covers concepts like overview of Operating System, Types, Services, Properties, Process Scheduling, CPU Sched...