• ベストアンサー

メッセージキューのFIFOの保証

Solaris10を使用しています。 プロセスAがメッセージキューXに対してメッセージを投げます。 プロセスBがキューXからメッセージを受け取り、処理をします。 プロセスBは複数プロセス(B-1,B-2・・・)あり、すべてがキューXでメッセージを受け取り処理をします。(A:B=1:多になる) この場合 (1)メッセージキューXのFIFO(先入先出)は普通保証されるでしょうか。 (2)プロセスBはメッセージ取得順にメッセージの割り当てが行われるでしょうか。(つまりB-1が先でB-2が後から取りに行ったらB-1に先にメッセージを渡すのが保証されるかどうか。) (3)上記を行うためには、キューの作成もしくはOSのパラメータの設定が必要か、必要ならどれを設定すればいいか。 よろしくお願いします。

  • quoth
  • お礼率84% (65/77)

質問者が選んだベストアンサー

  • ベストアンサー
  • noocyte
  • ベストアンサー率58% (171/291)
回答No.3

>「B-1、B-2...が皆同じように口を開けて待っていて、 > キューイングされたら早い者勝ちでデキューする」 > B-1が先でB-2が後から取りに行ったらB-1に先にメッセージを渡すのが > 保証されるかどうか。) マニュアルには,それに関する記述がない (少なくとも私は見つけられなかった) ので,それに頼らないように設計する必要があると思います. Solaris 10 Software Developer Collection - Japanese >> プログラミングインタフェース >> 6.プロセス間通信 >> System V IPC http://docs.sun.com/app/docs/doc/819-0392/6n2qr17j1?l=ja&a=view >> System V メッセージ このマニュアルによると,複数の受け手がいる場合には,メッセージタイプで 宛先を指定するという使い方を想定しているようなので (確か私も昔そういう 作り方をしたと思います),1つのメッセージを複数の受け手が奪い合うという 使い方はそもそも想定していないと思います. それともう一つ問題が….B-k がメッセージを受信し,C-k に送信しようとした が C-k または通信路のトラブルで送信できなかった場合,そのメッセージは 破棄していいんでしょうか? それとも別の C-j に送信すべきなんでしょうか? 後者の場合,B-1 ~ B-n を別プロセスにしておくとかなり面倒なことになると思います. そこで次のようにしてはどうでしょうか? これだと負荷分散も,上記の障害対策もしやすいと思うのですが. ・Bは単一プロセス,マルチスレッドとする. ・C-k ごとに1つの送信スレッドを用意する. ・メインスレッドはメッセージキューからメッセージを取り出し,  負荷状況を考慮して各送信スレッドにメッセージを振り分ける. ・ある送信スレッドiで通信が途絶した場合は,それが送ろうとしていた  メッセージを別の送信スレッドjに割り当てる.  (ただしこの場合,スレッドjが C-j に送信するメッセージの順序が逆転する可能性もある.)

その他の回答 (2)

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.2

> プロセスBの負荷分散(ある特定のプロセスB(たとえばB-1だけ) > に処理が集中することがないようすること)が目的です。 > プロセスB-1からプロセスB-nまでに、それなりに平均的に分散させる形で > 処理をさせたいということです。 プロセスを複数に分けても,それらが同一の CPU 上で実行されるのであれば 意味がないどころか,プロセス切替えのオーバーヘッドの分だけ CPU の負荷が 増えるのではありませんか? それともマルチ CPU のマシンなんでしょうか?

quoth
質問者

補足

言葉が足りなかったようで申し訳ありません。補足させていただきます。 実はプロセスB群はさらにその後に別サーバのプロセスC群と結びついています。 たとえばB-1はC-1へ、B-2はC-2、・・・、B-8はC-8へメッセージを投げるように紐付けされています。このC群はB群とは別サーバーですが、C群の中でも負荷分散を行っており、C-1~C-4までがサーバー1とC-5~C-8までがサーバー2で動くような設計となっています。(Bの動くサーバー0からCの動くサーバー1とサーバー2に対して分散してメッセージを送ると言うことです。) B群の入っているサーバーはそれなりに十分な能力があるので、いまのところ複数立ち上げることでのCPU負荷は気にしていません。 C群へ分散させることを直接プロセスAが行うことは、(機能の混合を避けるため)考えていません。 お手数ですが、よろしくお願いします。

  • DT200
  • ベストアンサー率38% (63/164)
回答No.1

(1) メッセージキューそのものの順序性は保証されるはずです(優先順位を付けなければ)。 (2) デキューするのはBひとつだけで、BがデキューしたメッセージをB-1、B-2に 分配するのでしょうか? それとも、B-1、B-2...が皆同じように口を開けて待っていて、キューイング されたら早い者勝ちでデキューするのでしょうか? (3) Bが処理した結果がキューイングされた順番と同じになるよう、順序性をここで 保証するのであれば、同期や排他などの処理で順序性が保たれるように作りこむ が必要となります。 パラメータに関しては、メッセージの大きさとメッセージ数の上限がやろうと している事に対して十分な値であれば良いと思います。

quoth
質問者

補足

回答ありがとうございます。 (2)については 「B-1、B-2...が皆同じように口を開けて待っていて、キューイングされたら早い者勝ちでデキューする」 を想定しています。 これをすることで、プロセスBの負荷分散(ある特定のプロセスB(たとえばB-1だけ)に処理が集中することがないようすること)が目的です。 プロセスB-1からプロセスB-nまでに、それなりに平均的に分散させる形で処理をさせたいということです。 プロセスBは受け取ったメッセージによって処理時間がまちまちですので、Bの「処理結果」の順序性の保証は不要です。

関連するQ&A

  • メッセージキューイングとは?

    すみません。 メッセージキューイングとは、どのように使用するものでしょうか? まだ、開発経験が浅い為、このような質問方法でいいかもよく分かっていないのですが、どなたか分かりやすく回答頂けないでしょうか? 例えば、同サーバー(Win2003サーバー)内で、AとBのプロセスがあった場合にAからメッセージを発行し、Bはそのメッセージを受け取って処理を開始するみたいに使用出来るのでしょうか?

  • POSIX メッセージキュー作成時の払い出しディスクリプタ

    現在、Linux(Fedora 7)の環境でPOSIXのメッセージキューを用いたプロセス間通信のプログラムを作成しています。 mq_openでメッセージキューをオープンしているのですが、 異なるプロセスですでに開かれているキューをオープンした時に、 最初にオープンしたキューと異なる値のディスクリプタが払い出されてしまいます。(その際のディスクリプタの値は他のキューの値になっていたりもします。) 例) <プロセスA(プロセスBより先に実行)> mqd = mq_open(   "/sample001", O_RDWR|O_CREAT, S_IRWXU, &mqattr); printf("Process A mqd = %d", mqd); <プロセスB> mqd = mq_open("/sample001", O_RDWR); printf("Process B mqd = %d", mqd); <実行結果> Process A mqd = 10 Process B mqd = 14 何か心当たりはありませんでしょうか?

  • 異なるプロセスですでに開かれているキューのオープンができません

    現在、Linux(Suse10.3)の環境でPOSIXのメッセージキューを用いたプロセス間通信のプログラムを作成しています。 mq_openでメッセージキューをオープンしているのですが、 異なるプロセスですでに開かれているキューのオープンができません。 最初にオープンしたキューは受信専用、異なるプロセスでオープンするキューは送信専用です。 errnoを調べましたが、 EACCES("\nキューは存在するが、呼び出し元が指定されたモードでそのキ>ューをオープンする許可を持たない。")となっています。 プロセスAの第3引数についてはmode_t S_IRWXU=0x777;としていますが、この辺りの設定方法がよくわかりません。 例) <プロセスA(プロセスBより先に実行)> msqid = mq_open(   "/sample001", O_RDONLY | O_CREAT, S_IRWXU, &mqattr); cout << "msqid:" << msqid << enld; msqid:3 <プロセスB> mqd = mq_open("/sample001", O_WRONLY); cout << "msqid:" << msqid << enld; msqid:-1 ///////////////////////////////////////////////////////////// //errnoは下記の通りです。 ///////////////////////////////////////////////////////////// EACCES(キューは存在するが、呼び出し元が指定されたモードでそのキ>ューをオープ>ンする許可を持たない。) 何か心当たりはありませんでしょうか?

  • プロセス間でのメッセージキュー送信

    Linux初心者です。 あるプロセスが生成したメッセージキューへ、別のプロセスからメッセージキュー送信する場合、キューIDを指定する必要があります。 しかし、Linuxでは仮想メモリを使用しているため、共有メモリにアクセスできないはずで、異なるプロセス間でキューIDを共有する方法がわかりません。。 メッセージキューについて以下のサイトでサンプルプログラムが紹介されていますが、2つのプロセスが親子関係であるため、キューIDを共有できています。 http://linuxmag.sourceforge.jp/Japanese/March2003/article287.shtml そもそも、親子関係がないとプロセス間通信ができないのでしょうか? ご存知の方、よろしくお願いします。

  • キューについて

    インターネットの記事でjava.util.Queueの使い方に関する記事を読んでいてふと思ったのですが このQueueというものを使用する場面が想像できなかったので質問させてください。 キューを使用することで先入れ先出しで処理されると思うのですがそもそもプログラムってそういう ものなんじゃないの?(早い者勝ちで処理される)と思ってしまいました。 例えばAさんとBさんが同じ処理を行うボタンを押したとして、Aさんのリクエストが早ければAさんの 処理、Bさんのリクエストが早ければBさんの処理が先に行われる。 そう考えるとキューというクラス(インターフェース)自体必要なの? って思って使い道が想像がつかなかったのですがどうなのでしょうか。 ※例のような動きを実現させるために必要なのであろうとは思うのですが業務アプリを作る上では 必要性について想像がつかなかったのですが使用する場面はあるのでしょうか。

    • ベストアンサー
    • Java
  • スレッドとメッセージキューに関して

    現在、下記のようなプログラムを作成しています。 内容は、メッセージキューを受信するスレッドを生成するというイメージです。 処理内容は下記のようになります。  (1)メッセージキューの生成  (2)スレッド生成(メッセージキュー受信側)  (3)スレッド停止  (4)メッセージキューの削除 しかし、(3)のスレッド停止を実施しても、(4)のメッセージキューの削除以降にて、msgrcvのエラーが出力されてしまいます。 スレッド停止を行ったことから、TestThreadは動作しなくなり、(4)のメッセージキューの削除にて、エラーともならずに終了することを望んでりますが、上手くいきません。 下記に作成しているプログラムを記載いたします。 正常終了をするには何がいけないのでしょうか? ご教授宜しくお願い致します。 [test.cc] ---------------------------------------------------------------- #include <time.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <ctype.h> #include <stdlib.h> #include <pthread.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> // メソッドポインタ定義 typedef void (*testT); // スレッドID pthread_t threadId; // メッセージキュー識別子 int msqId; // 送受信するメッセージ struct msgbuf{ long int type; char data[BUFSIZ]; }; // テストスレッド void TestThread() { // メッセージ struct msgbuf message; while( 1 ) { printf("### TEST ###\n"); printf("msq start\n"); // 受信 if( msgrcv( msqId, &message, BUFSIZ, 0, 0 ) == -1) { printf("ERR! msgrcv errno[%d]\n", errno); continue; } printf("msq ed\n"); sleep(1); } return; } // メイン int main(int argc, char *argv[]) { // メッセージキュー識別子退避変数 int testMsqid; // スレッド操作リターン値 int status; // スレッドa用のパラメータ pthread_t thread_test; printf("### TEST START ###\n"); // メッセージキューの作成 if( (testMsqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1 ) { printf("ERR! CREATE bkMsqId[%d]\n", testMsqid); return 1; } // メッセージキュー識別子を共通変数に設定 msqId = testMsqid; printf("msgget OK\n"); sleep(5); // スレッドを生成 status = pthread_create(&thread_test, NULL, (void*(*)(void*))TestThread, (void*)NULL); if(status!=0) { printf("pthread_create ng\n"); return 1; } printf("pthread_create OK\n"); sleep(5); // スレッド停止 status = pthread_cancel(thread_test); // スレッド停止結果 if ( status != 0 ) { printf("pthread_cancel ng\n"); return 1; } printf("pthread_cancel OK\n"); sleep(5); // メッセージキューの削除 if ( msgctl( msqId, IPC_RMID, NULL) == -1 ) { printf("msqId[%d] errno[%d]\n", msqId, errno); return 1; } printf("msgctl OK\n"); sleep(5); printf("### TEST E N D ###\n"); return 0; } ----------------------------------------------------------------

  • キューとスタックの問題です、宜しくお願いします

     (多分基本情報処理に関する問題だと思うのですが)データ構造に関する問題です、いくら考えても分かりません、宜しくお願いします。 【問】空の状態のキューとスタックの二つのデータ構造がある。 次の手続きを順に実行した場合、変数xに代入されるデータはどれか。 ここで、 ・データyをスタックに挿入することをpush(y) ・スタックからデータを取り出すことをpop( ) ・データyをキューに挿入することをenq(y) ・キューからデータを取り出すことをdeq( ) と表す。 (1)push(a) (2)push (b) (3)enq(pop( )) (4)enq(c) (5)push(d) (6)push(dep( )) (7)pop( ) → x 以上の答えとして(6)にはbがスタックにpushされるので、後入れ先出し を考えると当然「xにはb」が入るはずなのですが、どうも答えは「d」となっています。 「d」は「b」より前にスタックされてますので、最新で取出される情報は「b」しかないと思うのですが、誰か誤りを指摘してください、宜しくお願いします。

  • POSIXメッセージとは?

    こんにちわ。 私はSolaris8のC++でプログラミングをしている中級者です。 プロセス間通信の方法として、メッセージキューを使っています。 具体的には、キュー作成(msgget)、送信(msgsnd)、受信(msgrcv)、削除(msgctl)等の関数を使っているのですが、これ以外に「POSIXメッセージ」とかいうメッセージがあると聞きました。 SUNのドキュメントで調べてみたのですが、POSIXとは"Potal Operating System Interface for UNIX"で、まあUNIXベースのOSならみんな使えるような関数と解釈しました。この解釈は正しいでしょうか? そして、私が使用しているmsgXXX関数とどのように違って、どのような利点があるのでしょうか? 具体的には、上記のmsgXXXを実現するために、mq_open(), mq_close, mq_send, mq_receiveを使えば良いというだけのことなのでしょうか? POSIXメッセージとは、何か?また、こうやって使うんだよというような参考になるURLをご存じの方がいらっしゃいましたら、教えてくださいませ。

  • sendmailのキュー

    古いメールサーバを廃棄します。 その前にキューにたまったメールの処理をしたいと思います。 キューの消し方は、mailqコマンドでメッセージIDを調べ、 【手順1】 $ rm /var/spool/mqueue/dfJAA00**** $ rm /var/spool/mqueue/qfJAA00**** などとすればよいと聞きました。→d***とq***を消す。 しかし、/var/spool/mqueueをみると、頭文字がdやqのメッセージ ばかりではなく、頭文字が大文字のQや大文字のT、小文字のt、 小文字のxなどのファイルがあります。 これらのファイルは、どのような性質のファイルなのでしょうか? 【手順1】を実行すれば、自動的に消えてくれるようなファイル なのでしょうか? mailqコマンドで、メールキューがなくなった後も、これらのファイルが残っていた場合の対処方法などもご教授いただければ幸いです。 よろしくお願いいたします。

  • メッセージループについて

    確認したいのですが、AとBのプロセスがあるとしたら、 AとB while(GetMessage(&msg,NULL,0,0,PM_REMODE)) { TranslateMessage(&msg); DispatchMessage(&msg); } でAを実行中のときはBのプロセスはGetMessageによって処理を行わず待機、Bに移った場合、AはGetMessageによって待機というのでいいのでしょうか?