Linuxのカーネルの開発に関する世界観(メモリ管理)です。
C/C++でプログラムを書いた場合、言語の文法通りにそのプログラムが動くように、コンパイラがそのソースコードから機械語の実行バイナリファイルを翻訳して吐き出す。
OSはこの機械語のプログラムがきちんと動くように、プログラムにメモリ領域を割り当て、ページングとセグメンテーションによって分割されたメモリ領域を管理する。
また、プログラムがアクセスするメモリアドレスについて、論理アドレスを物理アドレスに翻訳し、同時にプログラムのコードを短期間で別々に切り替えて「タイムスライス」を与えることで、CPUとメモリがたとえひとつしかなくても、複数のプロセスを同時に並列的に実行できるようにする。
実際のところ、レジスタとはCPU内部の高速なメモリに過ぎません。ですが、レジスタは機械語で命令の処理に使われるため、小さく、少なく、そしてプログラムの実行にとって重要です。そのため、レジスタは少ない領域のものを、プロセスを切り替えるたびに「読み込んだり退避したり」します。
これに対して、メモリは低速で、大容量です。このため、それぞれの領域に分割して、プロセスがそれぞれのアドレス空間を持ち、機械語の命令としてメモリにプロセスがアクセスしようとした時は、カーネルが仲介して論理アドレスを物理アドレスに翻訳するのです。
そのため、コンテキストの切り替えは比較的容易です。ソフトウェアだけで実現できます。
メモリ管理を行うためには、ハードウェアの機能を用いてカーネルが仲介し、論理アドレスをリニアアドレス・物理アドレスに変換します。この時、ハードウェアのセグメンテーション回路とページング回路を利用します。また、それぞれのメモリ領域はページと呼ばれる単位でカーネルによって管理されます。
自分の書いたブログ「わたしの名はフレイ」2020/06/26より。
また、メモリ領域については、カーネルがハードウェアのMMUという機構を上手く使うことで、プログラムが実際のメモリ領域(論理アドレスやリニアアドレスと呼ぶ)にアクセスした段階で、カーネルがそれを物理アドレスに翻訳する。
このようにすることで、カーネルはメモリ領域を全てのプログラムに「個別に与える」ことができる。
このような仕組みを「仮想アドレス空間」と呼ぶ。
後日注記:Intel x86には仮想メモリを実現するために、セグメント機構とページング機構の2つがあり、冗長であるため、Linuxでは基本的にページング機構だけを使い、必要な場合にだけセグメント機構を使っている。
(詳しくはふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道、詳解 Linuxカーネル 第2版が参考になります。)
自分の書いたブログ「わたしの名はフレイ」2020/06/26より。
アドレス空間には、
・テキスト領域(機械語のプログラムコードが入る)
・ヒープ領域(malloc()が管理する)
・スタック領域(ローカル変数や関数の引数)
などがあり(ほかにデータ領域やBSS領域がある)、プロセスが作られると割り当てられる。
基本的に、プロセスを実行すると、そのプロセスに対してテキスト領域、ヒープ領域、スタック領域が割り当てられることを知っておけば良い。
(詳しくはふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道が参考になります。)
メモリは断片化する。断片化を解決するために、Linuxカーネルでは、ページと呼ばれる固定長の単位でメモリ領域を管理している。これをページングと言う。
Linuxカーネル(ページング・メモリ断片化)を参照のこと。
2023.10.10
(以下はオペレーティングシステム―設計と理論およびMINIXによる実装を参考に執筆しました。)
多くの場合、OSにひとつしか仮想アドレス空間が存在しないよりも、それぞれ独立したアドレス空間が複数あったほうがいいことが多い。
論理的に区分されたエンティティに従い、アドレス空間を分割する方法を「セグメント」と呼ぶ。
ページングは固定サイズのメモリ区分だが、セグメントは論理的なエンティティによる可変長の区分であるという違いがある。
以下の書籍が参考になります。
また、以下のページに参考になる内容があります。日本語版もあります。
MINIX本では、メモリ管理について詳細が記述されています。
メモリ管理ユニット (MMU)は、仮想メモリを実現するためのハードウェア部品。CPUと連携することで、仮想アドレスと物理アドレスを変換したり、メモリを保護したりできる。
現代的なOSでは、MMUとカーネルが連携して仮想アドレス空間を実現している。
後日注記:MMUが必ずマシンにあるとは限らない(組み込みなどの場合)ため、一部のOSカーネルや軽量libcなどではMMUのないシステムにも対応している。
メモリ管理アルゴリズムについては以下が参考になる。
以下のスライドがとても参考になる。必見。
Linuxカーネル(プロセス)も参照のこと。
メモリも参照のこと。