この記事は、マルチタスク からの続編です。
この記事は、絵でわかる プログラムとは何か(4)~マルチタスクとメモリ~ の一記事です。
この記事のポイント
- メモリの使い方としては離散記録よりも連続記録が理想的。
- 実際には離散記録でも、カーネルは、プログラム毎に連続な仮想アドレスを、割り当てられる。
- カーネルがプログラム毎に割り当てる仮想アドレス領域を、仮想アドレス空間と言う。
- マルチタスクOSでの、プロセス毎の仮想アドレス空間などの情報をコンテキストと言う。
- マルチタスクOSのカーネルは、PCBにプロセス毎の情報を管理し、コンテキストスイッチを行う。
仮想アドレス
連続記録こそ理想像
メモリアドレスは、メモリの記録領域の先頭から順に、通常、バイト単位で連続番号が振られています。
そして基本的には、ひと続きのデータはひと続きのアドレスに記録されているのが理想的です。ひと続きのアドレスであれば、「データの先頭アドレスから何バイト分」という簡潔な指定でひと続きを一気に扱え、最小限の動作かつ最短時間で、必要データの読み書きが完了します。
逆にひと続きのデータが、飛び飛びのアドレスに分散していたら、読取も書込も、効率が悪くなります。
でも実際は離散記録が必要
しかし、様々なデータを扱っていれば、すべてが同じ大きさというわけにはいきません。
例えば、メモリの100番地から7バイトのデータ「saku-jo」を、200番地から11バイトのデータ「keshimasuyo」を削除して、それぞれ7バイトと11バイトの空き地ができたとします。
そこへちょうど7バイトのデータや11バイトのデータがまたすぐ入れられれば良いのですが、あいにく5バイトのデータ「short」と13バイトのデータ「data-length13」しか無かったとします。そして、これらも早急にメモリに入れなければなりません。
そんな時、13バイトの「data-length13」はまとめて入れられなくても、11バイトの「data-length」と2バイトの「13」に分割して、 11バイトの空き地に 11バイトの「data-length」、7バイトの空き地に2バイトの「13」と5バイトの「short」を入れれば、丸く収まります。ただし、あとでひと続きの13バイトのデータ「data-length13」として使えるよう、それぞれのアドレスは記録しておく必要があります。
- 100~104番地:short
- 105~106番地:13
- 200~210番地:data-length
しかし、たとえ記録として残しておいたとしても、マルチタスク内のユーザープログラムにこの記録を見る対応を入れるのは困難です。なぜなら、マルチタスクでのメモリ管理は、その時のOS(カーネルプログラム)にしかできないからです。
ユーザープログラムで指定する仮想アドレス
そこで、ユーザープログラムとしては、そのままひと続きのアドレスを仮定してコンパイルします。このユーザープログラムにとってひと続きと仮定されたアドレスを仮想アドレスと言います。
カーネルによる離散記録から連続データへの復元
そして、ユーザープログラムはメモリアクセスのためにシステムコールでカーネルを呼び出します。呼び出されたカーネルは、仮想アドレスを実際のメモリアドレスに変換して、メモリへアクセスします。仮想アドレスに対して、実際のメモリアドレスを物理アドレスと言います。
カーネルがアドレス変換をしてくれることで、ユーザープログラムは分散した物理アドレスを知る必要がなくなるのです。
仮想アドレス空間
カーネルアドレス空間とユーザーアドレス空間
仮想アドレスがひと続きと仮定できるようにするためには、競合する他のプログラムの存在があってはなりません。そこで、仮想アドレスには、実行中のプログラム(プロセス)ごとに、そのプログラム専用の仮想アドレス空間が割り当てられます。
カーネルプログラム専用の仮想アドレス空間をカーネルアドレス空間、ユーザープログラム専用の仮想アドレス空間をユーザーアドレス空間と言います。
カーネルが割り当てるユーザーアドレス空間と物理アドレス
プロセスの生成では、カーネルによってユーザーアドレス空間が割り当てられ、そこにプログラムとデータのマシンコードが入れられます。これがプロセスの実体になります。
マルチタスクで実際には複数のプログラムがロードされている場合でも、仮想アドレス空間は、 各プログラムごとに必ず0番地から、そのプログラムが必要とする分だけ割り当てられます。
そして、カーネルによって、それらの実際の物理アドレスは、決められた共有領域以外では、決して重なることがないように振り分けられます。
共有領域: プロセス間のデータ共有手段として確保された領域
プロセス制御ブロック(PCB)
さらにカーネルは、各プロセス毎の管理情報リストであるプロセス制御ブロック=PCB(Process Control Block)を、カーネルアドレス空間に作ります。
PCBには、
- プロセスID
- 各種レジスタの値
- アドレス情報
- 稼働状況
- 実行待ち順位
などが記録されています。
カーネルは、各プロセス毎に作られるこのPCBを使って、各プロセスの実行切り替えを行います。
コンテキストスイッチ
プロセスの実体とPCBとを合わせたプロセスの全情報をコンテキスト(context)と言います。
カーネルは、複数のプロセスが全体として効率良くコンピューターを利用できるように、実行対象のプロセスをしょっちゅう切り替えます。
つまり、プロセスが未完了で実行途中であっても、カーネル自身の実行処理を優先して割り込ませたり、他のプロセスに実行を切り替えたりします。
この時、中断したプロセスの実行をまた再開できるように、実行されていない間もメモリに保存しておくのがコンテキストということです。
このコンテキストを使ってプロセスを中断・切替・再開する仕組みをコンテキストスイッチと言います。
コンテキストスイッチは、特にシステムコールで呼び出されたカーネルに実行が移される場合や、ファイル入出力などの時間がかかる処理をプロセスが待つ間、他のプロセスにプロセッサを明け渡す場合などに行われます。
この記事のまとめ
メモリの使い方としては離散記録よりも連続記録が理想的です。しかし、実際には離散記録にせざるを得ない場合がほとんどです。それでもカーネルは、プログラム毎に連続な仮想アドレスを、割り当てます。カーネルがプログラム毎に割り当てる仮想アドレス領域を、仮想アドレス空間と言います。
マルチタスクOSでの、プロセス毎の仮想アドレス空間などの情報をコンテキストと言います。
マルチタスクOSのカーネルは、PCBにプロセス毎の情報を管理し、コンテキストスイッチを行います。
次は、メモリ管理 に進みましょう。
この記事は、絵でわかる プログラムとは何か(4)~マルチタスクとメモリ~ の一記事です。
コンピューターのしくみ全体を理解したい場合は、以下の2コースがお勧めです。
日本全国 オンラインレッスン にも対応しています。
知りたいことだけ単発で聞きたい場合は、 オンラインサポート をご利用ください。