• 締切済み

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 何か心当たりはありませんでしょうか?

みんなの回答

  • chie65535
  • ベストアンサー率43% (8516/19358)
回答No.1

><実行結果> >Process A mqd = 10 >Process B mqd = 14 こうなって当たり前。 「2つの別々のプロセスで、同じファイルをopenした場合、同じファイル識別子は返って来ない」のは判りますか? 同様に「2つの別々のプロセスで、同じキューをmq_openした場合、同じキュー識別子は返って来ない」のは判りますか? 「プロセスAにとって、"/sample001"と言う名前のキューは10番である」 「プロセスBにとって、"/sample001"と言う名前のキューは14番である」 と言うように「別々の番号が返される」事によって、それぞれのプロセスがお互いを混同する事無く、キューにアクセス出来るのです。 もし、同じ番号が返って来たら、どうなると思いますか? プロセスAでもBでも、どっちも「10」を返してきて、片方のプロセス、例えばプロセスAがmq_close(10)とかって感じでキューをクローズしちゃったら? 「もう、10番のキューは閉じちゃって使えない」のですよ。プロセスBは「ありゃりゃ。開いてた筈の10番のキューが全部エラーになる。なんで?」って事になってしまいます。 このように「もし同じディスクリプタが返される」としたら「誰がオープンして、誰がクローズしたんだか、混同して訳が判らなくなる」でしょう。 これを、キューじゃなく「普通のファイル」で考えてみて下さい。 「2つの別々のプロセスで、同じファイルをopenした場合、同じファイル識別子が返って来る」としたら? 当然「誰か一人がファイルを閉じた瞬間、全員が、そのファイルに(そのファイル識別子に、そのファイルディスクリプタに)アクセス出来なくなる」って事を意味します。 ファイルもキューも、それは同じです。 4つのプロセスが全員で1個のキューをオープンすると、4つとも、mq_openですべて異なるディスクリプタを返される事になります。

関連するQ&A

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

    現在、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(キューは存在するが、呼び出し元が指定されたモードでそのキ>ューをオープ>ンする許可を持たない。) 何か心当たりはありませんでしょうか?

  • 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をご存じの方がいらっしゃいましたら、教えてくださいませ。

  • メッセージキューの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のパラメータの設定が必要か、必要ならどれを設定すればいいか。 よろしくお願いします。

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

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

  • スレッドとメッセージキューに関して

    現在、下記のようなプログラムを作成しています。 内容は、メッセージキューを受信するスレッドを生成するというイメージです。 処理内容は下記のようになります。  (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; } ----------------------------------------------------------------

  • ソケットディスクリプタを別プロセスで使いたい

    プロセスAで作成したディスクリプタをプロセスBで使いたいのですが 別プロセスへディスクリプタを関連付けたりって出来るのでしょうか? Aで作成->Bで使えるようにする->Aをクローズ->Bで使う このようにしたいです。

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

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

  • O_CREAT、O_TRUNC、O_WRONLYはどうして512、1024、1になる?何進数表示?

    Win2k+cygwinの環境です。 #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> int main(void){ int c,i,t,w; c=O_CREAT,t=O_TRUNC,w=O_WRONLY; i=(O_WRONLY | O_CREAT | O_TRUNC); printf("c=%d,t=%d,w=%d,i=%d\n",c,t,w,i); return 0; } を実行すると $ ./test c=512,t=1024,w=1,i=1537 となりました。 /cygwin/usr/include/bits/fcntl.hには #define O_ACCMODE 0003 #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 /* not fcntl */ #define O_EXCL 0200 /* not fcntl */ #define O_NOCTTY 0400 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */ #define O_APPEND 02000 #define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK #define O_SYNC 010000 #define O_FSYNC O_SYNC #define O_ASYNC 020000 #ifdef __USE_GNU # define O_DIRECT 040000 /* Direct disk access. */ # define O_DIRECTORY 0200000 /* Must be a directory. */ # define O_NOFOLLOW 0400000 /* Do not follow links. */ となっていまして、どうして c=512,t=1024,w=1,i=1537 になるのか分かりません。8進数表になっているのかと推測して #define O_CREAT 0100 よりこれは Ox0100 (8進数表示での0100)の意味なので10進数表示に変換してみましたら 64 となって辻褄が合いません。 #define O_TRUNC 01000 に於いても Ox01000→512 #define O_WRONLY 01 に於いては Ox01→1 でこれだけは実行結果と一致しています。 どうして c=512,t=1024,w=1,i=1537 となるのでしょうか?

  • プロセスの生成

    #include<stdio.h> #include <unistd.h> main(){ int i; printf("\t(%s)プロセスID.....%d\n","元",getpid()); printf("\t(%s)親プロセスID...%d\n","元",getppid()); if((i=fork())==0) { //子プロセスで実行する部分 printf("\t子プロセスでのfork()の値 : %d\n",i); printf("\t(%s)プロセスID.............%d\n","子",getpid()); printf("\t(%s)親プロセスID...........%d\n","子",getppid()); printf("子プロセスを終了します\n"); } else{//親プロセスで実行する部分 printf("\t親プロセスでのfork()の値 : %d\n",i); printf("\t(%s)プロセスID.............%d\n","親",getpid()); printf("\t(%s)親プロセスID...........%d\n","親",getppid()); printf("親プロセスを終了します\n"); } } fork関数の振る舞いについてです。 上記のプログラムをgccでコンパイルして実行した場合出力結果が /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ (元)プロセスID.....375 (元)親プロセスID...246 親プロセスでのfork()の値 : 376 子プロセスでのfork()の値 : 0 (子)プロセスID.............376 (子)親プロセスID...........375 子プロセスを終了します (親)プロセスID.............375 (親)親プロセスID...........246 親プロセスを終了します _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ という感じで出力されました。 fork関数がプロセスの複製を行っていることと、戻り値が0と376の2つであることはわかりました。 また子プロセスには0を親プロセスには376を返すこともわかりました。 感覚的にはif文の真である子プロセス側の記述文と偽である親プロセス側 の記述文が同時に実行されているのではないかと考えましたが 同時に実行されているのに printf("\t子プロセスでのfork()の値 : %d\n",i); printf("\t親プロセスでのfork()の値 : %d\n",i); で表示される値が違うのはなぜでしょうか。 i=fork()によって代入されているのはわかるのですが、 同時に実行されつつ何故2つの違う値をiは出力できるのかがわかりません。 また出力結果が _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ (元)プロセスID.....377 (元)親プロセスID...246 親プロセスでのfork()の値 : 378 (親)プロセスID.............377 (親)親プロセスID...........246 親プロセスを終了します 子プロセスでのfork()の値 : 0 (子)プロセスID.............378 (子)親プロセスID...........1 子プロセスを終了します _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 子プロセスから見たときの親プロセスが1となっているのは何故でしょうか? 本来ならば377ではないでしょうか? わかりにくい説明ですいません。 よろしくお願いします。

  • unlinkしたファイルを元に戻す方法?

    UNIX系OSでは(Windowsとかでもできるのでしょうか?) プログラム中で使う一時ファイルを、 プログラムが途中で異常終了したりした場合でも 確実に消えてなくなるように、 int fd = open( "temp.dat", O_RDWR|O_CREAT ) ; unlink( "temp.dat" ) ; というように、一時ファイルを作った直後にunlink、という手段が よく使われますが・・・ この、unlinkしてしまって、ファイルディスクリプタだけになったファイルを、 別のファイルに自力で書き写す以外に、 再びファイルとして残すことってできないのでしょうか? 要するに・・・ プログラムが途中で異常終了したりしたときは、 確実に消えてほしいけれど、 必要な場合は残したい、でも、残す処理が途中で中断したりして、 半端なファイルが残ってほしくない、 ・・・というような要件なのですが。。

専門家に質問してみよう