Provided by: manpages-ja-dev_0.5.0.0.20140515+dfsg-2_all bug

名前

       mq_notify - メッセージ到着時に通知を行うよう登録する

書式

       #include <mqueue.h>

       int mq_notify(mqd_t mqdes, const struct sigevent *notification);

       -lrt でリンクする。

説明

       mq_notify()   を使うと、ディスクリプタ  mqdes で参照される空のメッセージキューに新しくメッ
       セージが到着した時に 非同期の通知 (notification) の配送が行われるように登録したり、 その解
       除を行ったりできる。

       sevp 引き数は sigevent 構造体へのポインタである。 この構造体の定義と一般的な詳細については
       sigevent(7) を参照。

       sevp が NULL でないポインタであれば、 mq_notify()   はメッセージ通知を受け取るように呼び出
       し元のプロセスを登録する。 sevp が指す sigevent 構造体の sigev_notify フィールドは、どのよ
       うな通知を行うのかを指定する。 このフィールドは以下の値のいずれかを持つ。

       SIGEV_NONE
              「空の (null)」の通知: 呼び出し元のプロセスを通知の宛先として登録するが、  実際には
              メッセージが到着した時に通知は送られない。

       SIGEV_SIGNAL
              sigev_signo で指定されたシグナルを送って、プロセスに通知する。 一般的な詳細について
              は sigevent(7)  を参照。 siginfo_t 構造体の si_code フィールドには SI_MESGQ  が設定
              される。  さらに、 si_pid にはメッセージを送信したプロセスの PID が、 si_uid には送
              信プロセスの実ユーザ ID が設定される。

       SIGEV_THREAD
              メッセージの配送時には、 sigev_notify_function があたかも新しいスレッドの開始関数で
              あるかのように起動される。 詳細は sigevent(7)  を参照。

       一つのメッセージキューから通知を受信するように登録できるプロセスは 一つだけである。

       sevp が NULL で、かつ呼び出し元のプロセスがこのメッセージキューからの 通知を受信するに現在
       登録している場合、登録を削除する。  これ以降、別のプロセスがこのメッセージキューから通知を
       受信するように 登録できるようになる。

       メッセージ通知は、それまで空のキューに新しいメッセージが到着した      場合にのみ行われる。
       mq_notify() が呼び出された時にそのキューが空でない場合、  そのキューが空になり、その後新し
       いメッセージが到着した時に 初めて通知が行われることになる。

       別のプロセスやスレッドが mq_receive(3)  を使って、空のキューからメッセージの読み出しを待っ
       ている場合、 メッセージ通知の登録は全て無視される。 メッセージは mq_receive(3)  を呼び出し
       ているプロセスやスレッドに配送され、 メッセージ通知の登録は効力を持ったままとなる。

       通知は一度だけ行われる。通知が送られた後は、通知要求の登録は削除され、  別のプロセスがメッ
       セージ通知を受信するように登録できるようになる。  通知を受けたプロセスが次の通知も受信した
       い場合は、      mq_notify()       を使ってその後の通知も受けるように要求することができる。
       mq_notify()  を再度呼び出すのは、読み出していないメッセージを全部読み出して キューが空にな
       る前にすべきである (キューからのメッセージ読み出しをキューが空になった時に 停止 (block) せ
       ずに行うには、キューを非停止モード (non-blocking mode)  に設定しておくとよい)。

返り値

       成功すると、 mq_notify()  は 0 を返す。エラーの場合、-1 を返し、 errno  をエラーを示す値に
       設定する。

エラー

       EBADF  mqdes に指定されたディスクリプタが不正である。

       EBUSY  別のプロセスがすでに このメッセージキューに対する通知を受信するように登録している。

       EINVAL sevp->sigev_notify  が許可された値のいずれでもない。もしくは  sevp->sigev_notifySIGEV_SIGNAL だが sevp->sigev_signo が有効なシグナル番号ではない。

       ENOMEM 十分なメモリがない。

       POSIX.1-2008 では、 sevp が NULL で、呼び出し元のプロセスがキュー mqdes に関する通知を受信
       するように登録されていない場合、エラー EINVAL を生成するような実装を行っても「よい」ことに
       なっている。

準拠

       POSIX.1-2001.

       以下のプログラムは、 コマンドライン引き数で指定された名前のメッセージキューへの 通知要求を
       登録し、通知はスレッドの作成によって行われる。  そのスレッドは、そのキューからメッセージを
       一つ読み出してから、 プロセスを終了する関数を実行する。

   プログラムのソース
       #include <pthread.h>
       #include <mqueue.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       static void                     /* スレッド開始関数 */
       tfunc(union sigval sv)
       {
           struct mq_attr attr;
           ssize_t nr;
           void *buf;
           mqd_t mqdes = *((mqd_t *) sv.sival_ptr);

           /* 最大メッセージサイズを決定し、
              メッセージ受信用のバッファを確保する */

           if (mq_getattr(mqdes, &attr) == -1)
               handle_error("mq_getattr");
           buf = malloc(attr.mq_msgsize);
           if (buf == NULL)
               handle_error("malloc");

           nr = mq_receive(mqdes, buf, attr.mq_msgsize, NULL);
           if (nr == -1)
               handle_error("mq_receive");

           printf("Read %zd bytes from MQ\n", nr);
           free(buf);
           exit(EXIT_SUCCESS);         /* プロセスを終了する */
       }

       int
       main(int argc, char *argv[])
       {
           mqd_t mqdes;
           struct sigevent sev;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <mq-name>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           mqdes = mq_open(argv[1], O_RDONLY);
           if (mqdes == (mqd_t) -1)
               handle_error("mq_open");

           sev.sigev_notify = SIGEV_THREAD;
           sev.sigev_notify_function = tfunc;
           sev.sigev_notify_attributes = NULL;
           sev.sigev_value.sival_ptr = &mqdes;   /* スレッド関数に渡す引き数 */
           if (mq_notify(mqdes, &sev) == -1)
               handle_error("mq_notify");

           pause();    /* プロセスはスレッド関数により終了される */
       }

関連項目

       mq_close(3),   mq_getattr(3),   mq_open(3),   mq_receive(3),   mq_send(3),   mq_unlink(3),
       mq_overview(7), sigevent(7)

この文書について

       この  man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクト
       の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。