Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_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 を生成するような実装を行っても「よい」ことに
       なっている。

属性

       この節で使用されている用語の説明については、 attributes(7) を参照。

       ┌─────────────────┬───────────────┬─────────┐
       │インターフェース属性      │
       ├─────────────────┼───────────────┼─────────┤
       │mq_notify()      │ Thread safety │ MT-Safe │
       └─────────────────┴───────────────┴─────────┘

準拠

       POSIX.1-2001.

注意

   C ライブラリとカーネルの違い
       In the glibc implementation, the mq_notify()  library function is implemented  on  top  of
       the  system  call  of  the  same  name.   When  sevp  is NULL, or specifies a notification
       mechanism other than SIGEV_THREAD, the library function directly invokes the system  call.
       For  SIGEV_THREAD,  much of the implementation resides within the library, rather than the
       kernel.  (This is necessarily so, since the thread involved in handling  the  notification
       is  one  that  must  be  managed  by  the  C  library  POSIX threads implementation.)  The
       implementation involves the use of a raw netlink(7) socket and creates a  new  thread  for
       each notification that is delivered to the process.

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

   プログラムのソース
       #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 プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。