[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[plamo:21935] Re: 物理メモリサイズを取得する方法を教えて下さい



# 仕事では、4GB のマシンで malloc() failed を出したりします :-)。

From: Iwasa Dai <iwasad@alpha.co.jp>
Message-Id: <20040205.120622.41626489.uaitne@dream.com>

> > 下記の様なプログラムで,PCに実装されているRAMの内,
> > ユーザプログラムから使えるサイズを取得したいのですが,
> > どうも,RAM領域を越えてしまいます。
> > 64MBを持つPCで,実効しますと。
> > Linuxでは,SWAP分も加わるような傾向です。(約200MB)

少なくともユーザプロセスに対しては、1セグメント 4GB の仮想メモリ空間が
当てがわれます (i386 Linux の場合)。さらに、この 4GB の空間を 3つに分
割して管理しています。頭1GB分の空間がカーネルに割り当てられて、以下
2GB がスタック + mmap、最後の 1GB が heap + text に割り当てられます
(CONFIG_HIGHMEM=n の場合)。

CONFIG_HIGHMEM=n は「実メモリ 1GB 以下の人用」となっているのは、このメ
モリマップ (text + heap が 1GB しか取ってない) に起因しています。

有限の実メモリは、各プロセスごとに持っているセグメント空間のどこかに振
られていることになりますが、実際にこの空間のうちのどこが実メモリにマッ
プされて、どこがスワップに逃げていて、どこが空白地帯になっているか(正
確には、共有メモリ空間とか、ディスクキャッシュとか、shmfs 等の RAMディ
スクもある)は、ユーザプロセスからは見えません。仮想メモリ、というくら
いなので、わかっちゃまずいんですが。裏でカーネルが按配よく手配してくれ
ているのです。

ただ、カーネルについては、必ず常に実メモリに載っていて、どのプロセスの
セグメントにも現れている、という特性があります。

>   そもそも、「実際に取ってみる」ってどうなのでしょう?

というわけで、裏でカーネルがこれだけの仕事をやっている以上、「実際に取っ
てみる」というのは、「とりあえず実メモリをかき集めてきて mmap か heap
に貼り付ける」というだけの話なので、何ら意味はないことになりますよね。

もっとも、経験上、malloc() 1回で取れるメモリブロックは、とりあえず全部
実メモリに載っていて、かつ、物理アドレスとして連続しているんじゃないか、
と思っています(嘘かも)。

# 例えば、2G 一気に malloc() できなくても、1G ずつ 2回だとよかったり、
# 1M ずつなら 2700回以上 OK だったりするので。まぁ、この場合は古いブロッ
# クはスワップに押し出されるんでしょうけど。

実際には、実メモリにはカーネルが居座ってますし、スタックもそう簡単にス
ワップアウトしませんので、相当数目減りします。また、他のプロセスが動い
ている以上、その分にぽつぽつ食われる部分があって、どうしても連続領域を
確保するのは大変みたいです。

>   実際にallocateされてしまうと、他のprocessにとっては無いも
> 同然なわけで、例えば、

これもちょっと違うんですよね。あるプロセスが malloc() してぎってきても、
他のプロセスで必要になれば、剥されてスワップに出されるかもしれません。

あるないの問題ではなくて、プロセスからは本当に意識できないんですよ。
スワップの状態はカーネルが内部で管理してます。実際にはそこのアドレスに
はメモリが載っていない状態ですが、ここに CPU がアクセスするとメモリフォ
ルトが発生して、カーネルが仕事(メモリマップを見て、スワップにあれば戻
すし、本当になければ SEGV を送る)を始めます。

>   それでも、実際にRAM限定でallocしてみるのであれば、malloc
> する前に、mlockall(2)を使って、
> 
>     mlockall(MCL_FUTURE);
> 
> とかすると、良いかも知れません。

あー、これはいいですね。あいかわらずスワップはメモリを圧迫してくれます
けど。あと、malloc するのであれば、128KB 以上のブロックでとってあげた
方がいいです。このへんは、mmap と heap の使い方の癖に関わってくるんで
すが。

# まぁ、実メモリが 1G を超えない限りはここが問題になることはないのです
# が :-)

> |    printf("\n chk-ram ms=%d, v=%d", ms, v);
> |    if(mlockall(MCL_FUTURE)){printf("mlockall error!\n"); exit(1)} <---
> |
> |    i = check_ram_size(ms, v);
> |    printf("\n check_ram_size (result): %d[MB]\n", i);
> 
> と一行いれ、ついでにmallocの直前にmalloc sizeを表示するprintf
> をいれて、RAM 1024M, SWAP 2GのPCで実行してみたところ、973Mま
> で行ったところで、daemonやらktermやらが落ちまくってしまい、
> コマンドの終了が見届けられませんでした。

これも、1GB の壁に当たってるように見えるので、その問題に関係してるんじゃ
ないかなぁ。ようするに、text+heap はメモリマップ上で 1G 分に制限されて
て、128KB 未満の malloc() はこちらからしか取らないのです。

大きいブロックは、その上の mmap + スタックの領域(2G)から取ってきます。
これが溢れると heap も使いますので、「取れるだけ取る」のであれば、
128KB でぎっていくのが正解。

>   Subjectの「物理メモリサイズの取得」は、本文とニュアンスが違
> う気がしますが、Subject通りなら、/proc/meminfoやsysinfo(2)で
> わかるだろうと思います。

ですね。ユーザプロセスから関知できない以上、管理しているカーネルに聞く
のが正解ですよ。libgtop とか、xosview とか、GkRellm とか、このへんを実
装しているものはいくらでもあるので、教材には事欠かないと思います。
_______________________________
田原 俊一   jado@flowernet.gr.jp, shunichi_tahara@zenrin.co.jp
                                  http://flowernet.gr.jp/jado/
FingerPrint:  16 9E 70 3B 05 86 5D 08  B8 4C 47 3A E7 E9 8E D9
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

Follow-Ups
[plamo:21938] Re: 物理メモリサイズを取得する方法を教えて下さい, Iwasa Dai
References
[plamo:21933] 物理メモリサイズを取得する方法を教えて下さい, H.Shiozaki
[plamo:21934] Re: 物理メモリサイズを取得する方法を教えて下さい, Iwasa Dai

[検索ページ] [メール一覧]
Plamo ML 公開システム