0

各プロセスは 4 GB の仮想アドレス空間を取得し、4 GB のうちユーザー空間は 2 GB を取得します。そして、この 2 GB から、OS によってプロセスに割り当てられたメモリのスタック全体を読み取りたいと考えています。

スタック上でサイズ 2000,000 ( char chrArray[2000000];) のローカル配列を宣言するとします。いくつか質問したいことがあります。

1) and を使用するgcccygwin、初期化せずにその内容を読み取ることができますが、その内容はほとんど空 (以前%cは配列をファイルに出力していました) であるか、この配列の最後にいくつかのジャンク データがあります。ジャンク データに存在する 1 つの文字列を取得し、メモリ ダンプ (DumpItツールで取得) で検索しましたが、この文字列はメモリ ダンプに存在しませんでした。

私の質問は、そのジャンクデータはどこから来たのですか? ハードディスクにありましたか?

2)fork()各子プロセスで char 配列を宣言するために使用することを考えましたが、親プロセスのアドレス空間全体をコピーしてCopy-on-Writeテクニックを使用するため、役に立たないようです。私はこの解釈で正しいですか?

3)私が望むのは、大きなサイズの配列を宣言し、それがいくつかの新しい物理メモリアドレスにマップされるたびに宣言することです。これは達成可能ですか?

そして、このプロセスを繰り返すことで、メモリ全体をスキャンしたいと考えています。

このプログラムを実行するスクリプトを何度も試しbashましたが、常に同じ仮想ベース アドレスから開始されます。

for(たとえば) 10 文字の配列を宣言するループを実行しようとしましたが、それらのベース アドレスを出力すると、すべての配列で同じアドレスが表示されます。

私はプログラムを使用しWindows 7Cいますが、必要な OS の知識が不足していると思います。

ありがとう。

PS誰かが私がこれをしている理由を知りたいなら、私はこの分野で研究を行っています.

4

2 に答える 2

2

セキュリティの問題を回避するために、物理ページが割り当てられる場合、ほとんどのカーネルは、物理ページにデータが含まれていないことを確認します(たとえば、ゼロで埋めます)。そうしないと、あるプロセスが機密情報(パスワードなど)でページを埋めてから解放し、別のプロセスがそのページを割り当てて機密データにアクセスする可能性があります。

したがって、アレイに表示されているジャンクは、独自のジャンクです。

プロセスが最初に開始されるとき、多くのことが通常、main()制御を取得する前に発生します。これらには、動的リンクとシステムライブラリの設定、コンストラクターの実行(C ++の場合)などが含まれます。これは、コードが実行される前にスタックに配置される(スタックから削除される)ことを意味します。これはあなたが見ているがらくたです。

于 2012-10-14T01:47:06.317 に答える
2

サイズ 2000,000 ( char chrArray[2000000];)のローカル配列を宣言するとします。

これは危険です。スタックが不足すると、プログラムがクラッシュします。

この配列の最後にいくつかのジャンク データがあります。

スタックは下に向かって成長するため、配列の最後 (上位部分) がスタックの古い部分に対応します。プログラムの開始時にデータはゼロになり、プログラムの実行時にスタックにデータが書き込まれます。したがって、「ジャンクデータ」は、呼び出した関数からの残りのローカル変数とスタックフレームのその他のビットです。(ほとんどのOSは、特殊なコピーオンライト手法を使用してプロセスメモリをゼロにします-ブロック全体がゼロであることがわかっている場合、メモリブロックを簡単にコピーできるため、「特殊化された」と言います。)

ハードディスクにありましたか?

ハードディスクからのデータは、意図的にメモリ空間にのみ表示されます。プロセスが別のプロセスからメモリを再利用する場合、メモリは最初にゼロになります。

fork() を使って各子プロセスで char 配列を宣言することも考えましたが、親プロセスのアドレス空間全体をコピーし、Copy-on-Write 手法を使用するため、役に立たないようです。私はこの解釈で正しいですか?

これは、fork()Cygwin を使用している場合を除き、Windows にタグ付けされています。Cygwin の実装についてはわかりません。あなたが何を達成しようとしているのか、または何を期待しているのかfork()はわかりませんが、それはまさに がどのように振る舞うべきかです. このfork()呼び出しは、メモリを含むプロセス全体を複製します。

私が望むのは、大きなサイズの配列を宣言し、それがいくつかの新しい物理メモリアドレスにマップされるたびに宣言することです。これは達成可能ですか?

ユーザー空間プログラムは物理メモリ アドレスでは動作せず、仮想メモリ アドレスのみで動作します。いいえ、できません。

さらに悪いことに、char arr[10000]仮想アドレス 1000 に配列を割り当て、仮想アドレス 1000 が物理アドレス 6000 に対応するとします。

  • のアドレス&arr[0]は仮想アドレス1000と物理アドレス6000です...プロセスがスワップアウトされない限り、その時点で物理アドレスはまったくありません。したがって、物理アドレスは常に存在するとは限りません。

  • プロセスが再びスワップインさ&arr[0]れると、仮想アドレスは 1000 のままですが、物理アドレスは 6000 または 8000 または 999000 になる可能性があります。

  • のアドレス&arr[1000]は常に仮想アドレス 2000 ですが、物理アドレス 10000 または 85000 またはまったく異なるものである可能性があります...誰が知っていますか?

さらに読む:オペレーティング システムの「仮想メモリ」サブシステムについて読みたいと思うかもしれません。

于 2012-10-14T01:50:51.230 に答える