フラットメモリモデルとセグメントメモリモデルを理解しようとしています。
フラットメモリモデルとセグメントメモリモデルは、CPUアーキテクチャまたはOS、あるいはその両方によって決定されますか?
または、CPUアーキテクチャとOSのいずれかによって決定されるのではなく、CPUアーキテクチャとインストールされたOSを備えた任意のコンピューターのプログラマーが利用できるオプションですか?
後者の場合、フラットメモリモデルとセグメントメモリモデルを考慮する必要があるプログラミングの種類は何ですか?アセンブリ、Cおよび/または他の高級プログラミング言語?
これが私を混乱させるウィキペディアからの引用です。
から http://en.wikipedia.org/wiki/Address_space#Memory_models :
初期のx86コンピュータは、メモリセグメントとそのセグメント内のオフセットという2つの数値の組み合わせに基づいて、セグメント化されたメモリモデルアドレスを使用していました。一部のセグメントは、命令、スタックセグメント、または通常のデータセグメント専用のコードセグメントとして暗黙的に扱われていました。使用法は異なりますが、これを反映してセグメントには異なるメモリ保護がありませんでした。
現在、多くのプログラマーは、すべてのセグメント(セグメントレジスタ)が一般にゼロに設定され、オフセットのみが可変であるフラットメモリモデルを使用することを好みます。
から http://en.wikipedia.org/wiki/Flat_memory_model#Comparison :
フラットメモリモデル
- 追加のメモリ管理ハードウェア/ソフトウェアで強化されない限り、一般的なコンピューティングまたはマルチタスクオペレーティングシステムには適していません。しかし、これはほとんどの場合、フラットメモリモデル上に高度なメモリ管理および保護テクノロジを実装する最新のCISCプロセッサに当てはまります。 Linux例:フラットメモリモデルを使用して、X86_memory_segmentation#Practicesを比較します。
セグメント化されたメモリモデル
- オリジナルのIntel8086、8088、80186、80286に実装され、80386およびその後のすべてのx86マシンから現在のPentiumおよびCore2プロセッサまでサポートされています。このメモリモデルは、x86マシンで使用されて以来、マルチモード動作を提供し、互換性のあるセグメントモードで動作することはめったにありません。
使用中のメモリモデルは、次の2つの要素によって決定されます。
プログラマーの観点からは、カーネルコードに取り組んでいない限り、OSが提供するものを手に入れることができます。最新のオペレーティングシステムでは、これはページメモリモデルです。
ユーザースペースの最新のオペレーティングシステムで実行されるコードの場合、メモリモデルプロセスに関する限りはフラットです。これは、OSがプロセスに仮想メモリ空間を提供し、メモリに発生する可能性のあるすべてのページング、スワッピング、およびその他のことを隠すためです。この抽象化レイヤーは、プログラマーがシステム全体の利益のためにメモリを使ってニースをプレイすることを強制しないため、非常に便利です。
歴史的に、これは常にそうではありませんでした。
Windows 3.1x、MacOSからv9、およびNovell NetWareはすべて、Linux/Windows/OSXで当然のことと思われるメモリ保護の一部を欠いていました。特にNetWareには、実行中のすべてのコードに1つの大きなメモリスペースが提供されていたため、実際に割り当てられていないメモリにアクセスしようとした1つのバグが実際にそのメモリを取得し、システム全体をクラッシュさせることがよくありました。この理由から、NetWare用にプログラミングするプログラマーはメモリ管理に非常に注意する必要があり、Linux/windows/OSXプログラマーが気にする必要はありません。
それでも、NetWareはメモリのページモデルを使用していましたが、各プロセスに仮想メモリ空間を提供するのではなく、実際のメモリ空間を提供していました。
使用中のメモリモデルは、すべてのプログラミングに柔軟に対応できるわけではありませんが、ハードウェアに最も近いものです。カーネルプログラミングと組み込みデバイスプログラミングは、そのようなことが非常に重要な分野です。
「メモリモデル」は、低レベルの概念であると同時に(比較的)高レベルの概念でもあります。
昔は、セグメント化されたメモリモデルを備えたプロセッサと「ページング」または「マップされた」メモリモデルを備えたプロセッサの間で、少し「戦争」が起こっていました。バロースB5000シリーズマシンとPlessey250は、「機能」(または「記述子」)を備えたセグメント化されたメモリモデルを使用していました。つまり、物理ストレージは概念的な固定サイズのページとしてではなく、可変長のセグメントとして管理され、各セグメントは何らかの論理エンティティ(プロシージャやオブジェクトなど)に対応していました。セグメント間でアドレス指定するために、保護された方法でのみロードでき、セグメントの物理アドレス、セグメントの長さ、および実行する認証(読み取り/書き込み/実行など)を含む「機能レジスタ」が使用されました。セグメントを参照するためのプログラムが提供されました。
これらのシステムは、「ページングされた」システムがまだ軌道に乗るのに苦労しているときに、問題なく実行されていました。
オリジナルのPCは、貧乏人のセグメント化されたアーキテクチャをサポートするように設計された8086プロセッサに基づいていました。 IIRCには、16ビットの汎用レジスタ値に追加して20ビットのアドレスを生成するために選択できる4つのセグメントレジスタがありました。理論は、これらのレジスタは、BurroughsおよびPlesseyシステムがもう少しハードウェアサポートを使用してそれらを管理する方法とやや類似したソフトウェアで管理されるというものでした。しかし、この機能を利用するための優れたソフトウェアを作成する前に、DOSは8086に詰め込まれていたため、この機能が実際に効果的に使用されることはありませんでした。
セグメント化されたモデルは「実際の」(非実験的な)環境には存在しないため、どちらが優れているかについては、もう問題ではありません。しかし、当時は、セグメント化されたモデルのパフォーマンスが一般的に向上し、OSの堅牢性が向上していました。主なマイナス要因は、コンパイラーと、ある程度、当時および現在の多くのプログラマーの「ワイルドウェスト」の態度と一致しないプログラマーに制限を課したことでした。
「ページング」モデルは、アドレス空間が特定のサイズの「ページ」に分割されていることを前提としています(ただし、いくつかの異なるページサイズがサポートされている場合もあります)。通常、ページサイズは256バイトから64kバイトの間です(常に2の累乗)。また、「論理」アドレス(プログラムの「アドレス空間」内のアドレス)を「物理」アドレス(RAM内のアドレス)にマップできるように、ハードウェアに何らかのアドレス変換サポートが含まれていることも前提としています。
ページモデルは、次の2つの主な理由で実装できます。
読み取り/書き込み/実行権限の設定、一部のページをプロセス/スレッド間で「共有」できるようにするなど、使用できるページ変換ハードウェアのマイナーな機能もあります。
おそらく最初のコンピュータメモリモデルであったハーバードモデルを無視すると、フラットフォンノイマンストレージモデルは、一般的に使用される最初のモデルでした。これは基本的には、アドレス0から始まり、使用可能なメモリの「トップ」まで続く、区別のつかない単語の「フラットな」アドレス空間(ゲームの後半までバイトではない)です。メモリの「下部」または「上部」にあるメモリの一部は、ある種の「ローダー」用に予約され、残りは単一の実行プログラムで使用できます。一度に1つのプログラムが実行され、プログラムはその小さな予約済みRAM領域を除くすべてを使用できました。
物事はゆっくりと変化し、小さな予約領域が大きくなり、ある種のオペレーティングシステムを保持していましたが、それでも一度に1つのプログラムしかありませんでした。時間がさらに進むにつれて、たとえば、特定の特殊なプログラムをメモリの「コーナー」で実行したり、スプーリングプログラムなどをユーザーのプログラムと共存させたりできるようにするために、さまざまなトリックが考案されました。
しかし、「マルチプログラミング」の推進は圧力をかけていました。一部のシステムでは、大まかなアドレスマッピングハードウェアを追加して、複数のプログラムがそれぞれ独自のアドレス空間を持つことができるようにしました。他のシステムでは、プログラムを「自己再配置」して、特定のアドレスに「リンク」するのではなく、メモリ内のどこでも実行できるようにする必要がありました。
初期のUnix(とりわけ)は、プログラムを「スワップイン」および「スワップアウト」することによってマルチプログラミングジョブを処理しました。プログラム(アドレス0でロード)は、I/Oを実行するために「ブロック」されるまで実行され、その後、(全体(すべてのコードとデータを含む)をディスクと別のプログラムに「スワップ」します。
しかし、ほとんどの場合、これらの手法は、さまざまな形式のページマッピングストレージモデルにゆっくりと進化しました(またはおそらく進化しました)。
私はプログラマーですが、実際にこのレベルでメモリモデルを処理する必要がある組み込みプログラマーではないので、私が言うことを一粒の塩で理解してください。
私の理解では、メモリモデルはプロセッサアーキテクチャによって決定されます。これらは、アセンブリ、低レベルC、またはハードウェアに近いものを操作するプログラマーに最も関連性があります。 JavaやC#などの多くの高級言語では、これらのような詳細を隠す抽象化があるため、通常、ハードウェアメモリモデルについて考える必要はありません。
それが出てくる奇妙な時があります。 32ビットx86プロセッサ(少なくとも過去10年間)はセグメントを使用して4GBを超えるメモリにアクセスできることを理解しています( PAEモード )、多くの32ビットOSがそれをサポートしていますが、ほとんどのプログラムはフラットメモリモデルを期待しているため、1つのプロセスで使用できるメモリの最大量は4GBに制限されています(最近の多くのOSでは他のものを期待できるとは思えません)。
引用を明確にするには:
初期のx86プロセッサには、小さな番号のコンパートメントを備えた番号付きの引き出しのセットによく似たメモリモデルがありました。少しのメモリにアクセスするには、コンパートメント番号とともに引き出し番号を指定する必要があります。すべてのドロワーは同じであり、一部のプログラマーは1つのドロワーをコードに使用し、別のドロワーをデータなどに使用することを決定しましたが、これらの決定はプロセッサーアーキテクチャーによって決定されませんでした。フラットメモリモデルは、引き出しが1つしかないようなものなので、コンパートメント番号を使用するだけです。
追加機能(あるプログラムが別のプログラムのメモリを使用できないようにする機能など)がなければ、フラットメモリモデルは最新のオペレーティングシステムには適していませんが、最新のデスクトップ/サーバープロセッサはすべてこれらの機能を数十年にわたって備えています。
すべてのx86プロセッサには、下位互換性のために8086、80286などのようにメモリにアクセスするモードがありますが、これらは廃止されています。ほとんど誰もそれらを使用しなくなり、常により新しいモードに切り替わります。
お役に立てれば。
メモリセグメンテーションは、コンピュータのプライマリメモリをセグメントまたはセクションに分割することです。セグメントまたはセクションは、コンパイルされたプログラムのオブジェクトファイルで、プログラムイメージにリンクされている場合、またはイメージがメモリにロードされている場合にも使用されます。セグメンテーションを使用するコンピュータシステムでは、メモリ位置への参照には、セグメントを識別する値とそのセグメント内のオフセットが含まれます。異なるプログラムモジュール、またはコードやデータセグメントなどの異なるクラスのメモリ使用量に対して、異なるセグメントを作成できます。特定のセグメントはプログラム間で共有される場合もあります