• ベストアンサー

スレッド?

kaz-sugiの回答

  • ベストアンサー
  • kaz-sugi
  • ベストアンサー率50% (3/6)
回答No.3

shmでメモリを共有した時に、プロセス数*共有メモリサイズを 使用するということはありません。 LinuxのOSとしてのメモリ管理の内部実装はよくは知りませんが、 今時のまっとうなUNIXであれば、共有メモリの実装は、 1つのメモリオブジェクトを複数のプロセスからポイントする、 というように実装されているかと思います。 普通の状態では、仮想アドレス空間から物理アドレス空間への 変換テーブルをプロセスごとユニークなものを持ちます。 メモリオブジェクトとはその変換テーブルを管理するOS内の資源の単位で、 おおざっぱに言えば、プロセスが使用するメモリ空間の、 テキスト領域(プログラムのコードを格納する領域)、 データ領域(グローバル変数を格納する領域)、スタック領域(ローカル 変数を格納する領域)、という単位でオブジェクトが作られます。 つまり、1プロセスにつき、この3種類の領域に対応する 3つのメモリオブジェクトへのポインタを持っていて、 それぞれのオブジェクトは変換テーブルを持ちます。 別プロセス間でメモリを共有するという状態は、 共有している領域へのメモリオブジェクトへのポインタが 同じメモリオブジェクトを指している状態であります。 ですから、メモリオブジェクトはまさに「共有/共用」されており、 プロセス数分メモリを消費するということはありません。 但し、わずかですが管理領域分はプロセス数分使うでしょう。。 あと、cloneで作成した子プロセスが親プロセスより先に終了すると ご指摘のとおりdefunct(ゾンビ)ができます。 こいつを消すには親がwaitしてあげるしかなさそうです。。。 signal(SIGCHLD, SIG_IGN)をしてみましたが、ダメでしたね。。。 pthread_createで作られたスレッド(cloneプロセス)では、 pthreadライブラリの中で上手に解決しているらしく、 defunctはできませんでしたので、こちらを使うほうがお手軽のようです。 もう、ここまできたらついでなので、サンプルを紹介します。 -- clone --- #include <sched.h> #include <signal.h> char stk[4096]; main() { int xx(); int arg[1]; signal(SIGCHLD, SIG_IGN); arg[0] = 555; __clone(xx, stk+4096, CLONE_VM|CLONE_SIGHAND, (void *)arg); while (1); } int xx(void *arg) { int x; x = (int)((int *)arg)[0]; printf("x=%d\n", x); } -- clone --- 単にccして、実行できます。 親側はwhileで止まっていますので、ps -ef で見ると defunctが残っているのがわかります -- pthread -- #include <pthread.h> int main() { void *xx(); pthread_t pth; int arg[1]; arg[0]=555; pthread_create(&pth, NULL, xx, (void*)arg); while (1); } void* xx(void *arg) { int x; x = (int)((int *)arg)[0]; printf("x=%d\n", x); } -- pthread -- ccするときに、-lpthread を指定してください。 同じように親は止まっていますが、今度はゾンビが ないのがわかると思います。 -- shmget/shmat メモリ提供側 -- #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #define DSIZE 1000000 int main(int argc, char **argv) { key_t key = 123; int shmid; int *p; int i; if (argc > 1) key = atoi(argv[1]); if ((shmid = shmget(key, sizeof(int)*DSIZE, IPC_CREAT|SHM_R|SHM_W)) == -1) { fprintf(stderr, "Can't get shmid\n"); exit(1); } printf("shmid=%d\n", shmid); if ((p = (int*) shmat(shmid, 0, SHM_RND)) == (int*)-1) { fprintf(stderr, "Can't attach shmid\n"); exit(1); } printf("p=%08x\n", p); for (i = 0; i < 100; i++) { *p = i; p++; } while (1); return 0; } -- shmget/shmat メモリ提供側 -- -- shmget/shmat メモリ共有側 -- #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #define DSIZE 1000000 int main(int argc, char **argv) { key_t key = 123; int shmid; int *p; int i; if (argc > 1) key = atoi(argv[1]); if ((shmid = shmget(key, sizeof(int)*DSIZE, SHM_R)) == -1) { fprintf(stderr, "Can't get shmid\n"); exit(1); } printf("shmid=%d\n", shmid); if ((p = (int*) shmat(shmid, 0, SHM_RND)) == (int*)-1) { fprintf(stderr, "Can't attach shmid\n"); exit(1); } printf("p=%08x\n", p); for (i = 0; i < 100; i++) { printf("%d\n", *p); p++; } shmdt(p); return 0; } -- shmget/shmat メモリ共有側 -- 単にccで実行できます。 端末を2つ開いて、提供側を実行しておいてから、 共有側を実行すると、値が共有されているのが わかると思います。 数千のプロセスですか、ネットワーク対戦ゲームでも 作成されるのでしょうか? 楽しみですね。 ところで、数千のプロセスはたぶんシステムのプロセス数上限に あたり実行できないと思います。 上限設定を変えて実行できたとしても、Linuxはプロセススケジューラが ガタガタなので、まともに動作しないでしょう。 工夫が必要です。

zukka
質問者

お礼

これまでの質問に対する回答大変ありがとうございました。 とても的確で分かりやすい回答でした。 また、何か分からないことがあったら、質問に答えてください。 cloneでゾンビプロセスを回避する方法が分かりました。 __clone(xx, stk+4096, CLONE_VM|CLONE_SIGHAND, (void *)arg); を __clone(xx, stk+4096, CLONE_VM|CLONE_SIGHAND|SIGCHLD, (void *)arg); にすると、クローンのプロセスが終了した時にSIGCHLDシグナルが親プロセスに送信されゾンビプロセスが出来ませんでした。

関連するQ&A

  • windowsでのプログラミングについてなんですけど。

    UNIXの本を読んでると、プログラムはexitシステムコールが呼ばれると、 freeregを呼び出し、malloc済みメモリをすべて開放し、共有メモリについても 参照が0になったら解放するようになっていて、仮にメモリリークする プログラムで会ってもプロセスを殺せば、そのプログラムのリークした分は すべて解放されるんですよ~~~それと同じ感覚で、windowsでプログラム やってる友達に聞いたら、プロセスを殺してもnewでリークしたのしっぱなしに なるっぽいよ~って言ってたんですよ。それって本当なんですか? てか本当ならあえてそうしてるメリットってあるんでしょうか?

  • スレッドの意味

    マルチスレッドについて良い資料が見当たらず、教えて下さい。 OSにおけるマルチスレッドと言うと、同一プロセス内でメモリ空間を 共有して独立に動く一連の手続き、と捉えています。(シングルCPU シングルコアだとOSで時分割によって作られた仮想的な並列計算) Javaのようなマルチスレッドのプログラミング言語では「一つの プログラムから作られた二つの一連の手続き」と言うイメージが あります。※裏側の動作ではOSに依頼してJavaのプロセス内で OSのスレッドを生成して処理を渡しているだけ?と思っています。 CPUコアの内部で説明される「マルチスレッド」と言うのは、 どのようなレベルのスレッド(何が並列処理?何処まで並列?) なのでしょうか。

  • Linuxでのスレッド間メッセージについて

    Linuxでスレッドを複数生成し、スレッド間でメッセージのやり取りをしたいと思っています。 ネットで色々検索したのですが、欲しい情報にめぐり合えていません。 # WindowsのPostThreadMessage()みたいなものを探しています。 #「プロセス間通信」というものは発見しましたが・・・ 何か方法はありますでしょうか? スレッド間のメッセージのやり取りの方法がない場合は代替案も教えて頂きたいです。 # セマフォを用いて共有メモリアクセスかな?と思っています。

  • パフォーマンスモニタのメモリについて

    1.パフォーマンスモニタであるPrivate Bytes、Working Setがいまいち理解できませんが、下記の認識であっておりますでしょうか。 (1) 仮想メモリ 物理メモリが不足したときに使用するハードディスク上に設定した仮想メモリ(ページングファイル) (2) Private Bytes : ほかのプロセスから共有されない仮想メモリサイズ (3) Working Set : プロセスが使用している物理メモリサイズ 2.認識があっている場合、Working Setは、他のプロセスと共有されていますでしょうか。 Working Setがほかのプロセス共有されていないとのことでしたら、Private Bytesと Working Setを足した値がそのプロセスが使用しているメモリの合計ということでしょうか。

  • 二重起動チェックについて

    Solarisで、プロセスの二重起動チェックを行いたい のですが、システムコールの使用など簡単に行える 方法はないでしょうか? よろしくお願い致します。

  • 実行中のプロセスのシステムコールフックについて

    表題の通り,実行中のプロセスのシステムコールのフックについて質問があります. 現在,Linux上の全てのプロセスがどんなシステムコールを使って,どんなリソースにアクセスをしているのか調査しているのですが 具体的には以下のURLのソフトと同じものを,Linux上でC言語を用いて作りたいと考えています. [Process Monitor] http://www.microsoft.com/technet/sysinternals/utilities/processmonitor.mspx いろいろ調べていく中で strace http://www.netadmintools.com/html/1strace.man.html を使うと目的としている調査が実装できそうだということでさっそくいじってみたのですが, strace では既に実行されているプロセスのシステムコールの呼び出しをトレースすることはできないようでした. そこで1点質問なのですが,既に実行中のプロセスのシステムコールをフックするにはどのような方法を使えばいいのでしょうか. お分かりになるかたご回答よろしくお願いします. こちらの開発環境は以下です. OS: Debian 4.0 Kernel: 2.6.20-16 gcc: 4.1.2 (3つとも11/9現在の最新版を使用しています)

  • 共有メモリの同時アクセスについて教えてください。

    2つのプロセスが同時に同じ共有メモリにアクセスすることは可能ですか? ミューテックスや、セマフォなどの排他制御を外せばできたりしませんか? 片方のプロセスで共有メモリから、データの一部をHDDに保存しつつ、それと同時に、もう片方のプロセスで共有メモリからデータの中身を表示させたいのですが・・・。

  • CPU使用率が100%になってしまいます

    ファンの稼動が激しいため、タスクマネージャをみたところ、CPU使用率が100%のまま変わりません。プロセスのiexpore.exeが90~99でメモリ使用量が36104Kになっています。普段は、たしか、System Idle Processが90~99なはずなのですが、このようにCPU使用率が100%の時は、System Idle ProcessのCPUが0で、メモリ使用量は、16Kになってます。CPU使用率を下げる方法はありますでしょうか?

  • 32ビットCPUのメモリについて

    32ビットCPUの場合、アドレス空間の制限で1プロセスにつき4GBまでしか使用できないことになっていると思いますが、このうち2GBはシステム用、その他2GBがアプリケーション用と聞いたことがあります。1プロセスで使用する度にOSに2GBほどのメモリを使用することがあるのでしょうか?(プロセスが多くなる度にOSで使用されるメモリ量も増大すると考えてよろしいでしょうか?)

  • Windowsのメモリ使用量が稼働プロセスと不一致

    Windows で使用しているメモリ量をプロセスごとに把握する際に、 検算としてリソースモニタのメモリタブに表示されるプロセスのメモリ量を合計してみましたが、 その容量がリソースモニタで表示されている物理メモリの使用サイズと一致しません。 ■使用マシン  OS : Windows Server 2008 R2 Enterprise 64bit  物理メモリ容量 : 16 GB ■リソースモニタでの出力内容  物理メモリ使用量 : 11241 MB  リソースモニタに表示されるプロセスの全メモリ合計(ワーキングセット) : 8306 MB  リソースモニタに表示されるプロセスの全メモリ合計(コミット) : 9509 MB タスクマネージャや tasklist コマンドで表示されるプロセスのメモリを合計しても、 同様に「物理メモリ使用量」の値に届かないため、プロセス外の何らかのものが メモリを使用していると推測されますが、実際はどうなのでしょうか? (共有メモリなど特定のプロセスに属さないメモリ領域など??) また、そういうものがあった場合、そのメモリ使用量をどのように確認すればよいでしょうか?