web-dev-qa-db-ja.com

スタックとヒープのサイズはOSによってどのように制限されますか?

:回答できる特定のOSを検討する必要がある場合は、Linuxを検討してください。

プログラムを実行するたびに、実行用の仮想メモリ空​​間が与えられます。スタック用の領域とヒープ用の領域があります。

質問1:スタックとヒープに静的なサイズ制限があります(たとえば、それぞれ2ギガバイト)、またはこの制限は動的で、プログラムの実行中にメモリ割り当てに従って変化します(つまり、両方で合計4ギガバイトを使用するので、プログラムがスタックのみを使用する場合は、4ギガバイトのスタックを使用できます)?

質問2:制限はどのように定義されますか?利用可能な合計RAMメモリですか?

質問:テキスト(コード)およびデータセクションはどうですか、どのように制限されますか?

21
Daniel Scocco

2つの異なるメモリ制限があります。仮想メモリ制限と物理メモリ制限。

仮想メモリ

仮想メモリは、使用可能なアドレス空間のサイズとレイアウトによって制限されます。通常、最初は実行可能コードと静的データ、およびヒープが大きくなる過去ですが、最後はカーネルによって予約された領域であり、その前に共有ライブラリとスタック(ほとんどのプラットフォームでは大きくなります)があります。これにより、ヒープとスタックの空き領域が増加し、他の領域はプロセスの起動時に認識され、修正されます。

空き仮想メモリは、最初は使用可能としてマークされていませんが、割り当て中にそのようにマークされています。ヒープは利用可能なすべてのメモリまで拡張できますが、ほとんどのシステムはスタックを自動拡張しません。スタックのIIRCデフォルト制限は、Linuxでは8MiB、Windowsでは1MiBであり、両方のシステムで変更できます。仮想メモリには、メモリマップファイルとハードウェアも含まれます。

スタックを(任意に)自動拡張できない理由の1つは、マルチスレッドプログラムがスレッドごとに個別のスタックを必要とするため、最終的には相互に干渉することです。

32ビットプラットフォームでは、仮想メモリの総容量は4GiBであり、通常、LinuxとWindowsの両方がカーネル用に最後の1GiBを予約しているため、最大で3GiBのアドレススペースを使用できます。完全な4GiBを提供するものを予約しない特別なバージョンのLinuxがあります。これは、最後の1GiBが1日を節約する大規模なデータベースのまれなケースに役立ちますが、通常の使用では、追加のページテーブルの再読み込みのために少し遅くなります。

64ビットプラットフォームでは、仮想メモリは64EiBであり、そのことを考慮する必要はありません。

物理メモリ

物理メモリは通常、プロセスがアクセスする必要がある場合にのみオペレーティングシステムによって割り当てられます。プロセスが使用している物理メモリの量は非常にあいまいな数値です。一部のメモリはプロセス間で共有されるため(コード、共有ライブラリ、およびその他のマップされたファイル)、ファイルからのデータはオンデマンドでメモリにロードされ、メモリ不足が発生すると破棄されます。 「匿名の」メモリ(ファイルにバッキングされていないメモリ)は交換できます。

Linuxでは、物理メモリが不足するとどうなるかはvm.overcommit_memory システム設定。デフォルトはオーバーコミットです。システムにメモリを割り当てるように要求すると、メモリは割り当てられますが、仮想メモリのみが割り当てられます。実際にメモリにアクセスすると、一部の物理メモリを使用しようとし、必要に応じて再読み取り可能なデータを破棄したり、交換したりします。何も解放できないことが判明した場合は、プロセスを存在から削除するだけです(その反応にはより多くのメモリが必要になる可能性があり、無限ループにつながる可能性があるため、反応する方法はありません)。

これは、プロセスがAndroid=(これもLinuxです)で終了する方法です。ロジックはwhichプロセスで改善され、プロセスの実行内容に基づいて存在から削除されます。 Androidプロセスよりもプロセスは何もしないで単純にバックグラウンドで待機し、「メモリ不足キラー」は新しいメモリにメモリが必要なときにそれらを強制終了します。

23
Jan Hudec

メモリの使い方の順番で答える方が簡単だと思います。

質問3:テキスト(コード)とデータセクションについてはどうですか、どのように制限されていますか?テキストとデータはコンパイラによって準備されます。コンパイラーの要件は、それらがアクセス可能であることを確認し、それらをアドレス・スペースの下部にパックすることです。アクセス可能なアドレス空間は、ハードウェアによって制限されます。命令ポインタレジスタが32ビットの場合、テキストアドレス空間は4 GiBになります。

質問2:制限はどのように定義されていますか?利用可能な合計はありますかRAM memory?テキストとデータの後、その上の領域はヒープです。仮想メモリでは、ヒープは、実質的に最大アドレス空間に近づくupことができます。

質問1:スタックとヒープに静的なサイズ制限(たとえば、それぞれ2ギガバイト)があるか、またはこの制限は動的であり、プログラムの実行中にメモリ割り当てに従って変化します(つまり、合計4ギガバイト)両方で使用されるため、プログラムがスタックのみを使用する場合は、4ギガバイトのスタックを作成できます)?プロセスアドレス空間の最後のセグメントはスタックです。スタックはアドレス空間の最後のセグメントを取得し、最後から開始してdownに成長します。

ヒープが大きくなり、スタックが大きくなるため、基本的には互いに制限します。また、両方のタイプのセグメントが書き込み可能であるため、境界の1つが境界を超えることは必ずしも違反ではなく、バッファまたはスタックのオーバーフローが発生する可能性があります。今、それらを防ぐためのメカニズムがあります。

開始する各プロセスには、ヒープ(スタック)の制限が設定されています。この制限は、実行時に変更できます(brk()/ sbrk()を使用)。基本的には、プロセスがより多くのヒープスペースを必要とし、割り当てられたスペースが不足すると、標準ライブラリがOSへの呼び出しを発行します。 OSはページを割り当てます。これは通常、プログラムが使用するユーザーライブラリによって管理されます。つまりプログラムが1 KiBを必要とする場合、OSはさらに4 KiBを提供し、ライブラリはプログラムに1 KiBを提供し、プログラムが次に要求するときに使用するために3 KiBを残します。

ほとんどの場合、レイアウトはテキスト、データ、ヒープ(拡大)、割り当てられていないスペース、最後にスタック(拡大)になります。それらはすべて同じアドレス空間を共有します。

9
imel96