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


21

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

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

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

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

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


回答:


23

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)でプロセスが死ぬ方法です。ロジックはロジックで改善されたプロセスが何をしているかに基づいて、存在から削除する処理とどのように古いことがあります。アンドロイドのプロセスは単に何もするのを止めますが、バックグラウンドに座っていると、「メモリ不足のキラー」が新しいプロセスにメモリを必要とするときにそれらを殺します。


9

これは、メモリの使用方法の順序で答える方が簡単だと思います。

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

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

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.