mq_notify - ライブラリコールの説明 - Linux コマンド集 一覧表
- 名前
- 書式
- 説明
- 返り値
- エラー
- 準拠
- 例
- 関連項目
名前
mq_notify - メッセージ到着時に通知を行うよう登録する
書式
#include <mqueue.h>
mqd_t mq_notify(mqd_t mqdes, const struct sigevent *notification);
説明
mq_notify
()を使うと、ディスクリプタ
mqdes
で参照される空のメッセージキューに新しくメッセージが到着した時に
非同期の通知 (notification) の配送の登録/解除を行うことができる。
notification
引き数は
sigevent
構造体へのポインタである。
sigevent
構造体は以下のような感じで定義されている:
union sigval { /* Data passed with notification */
int sival_int; /* Integer value */
void *sival_ptr; /* Pointer value */
};
struct sigevent {
int sigev_notify; /* Notification method */
int sigev_signo; /* Notification signal */
union sigval sigev_value; /* Data passed with notification */
void (*sigev_notify_function) (union sigval);
/* Function for thread notification */
void *sigev_notify_attributes;
/* Thread function attributes */
};
notification
が NULL でないポインタであれば、
mq_notify
()はメッセージ通知を受け取るように呼び出し元のプロセスを登録する。
notification
が指す
sigevent
の
sigev_notify
フィールドは、どのような通知を行うのかを指定する。
このフィールドは以下の値のいずれかを持つ。
-
SIGEV_NONE
-
「空の (null)」の通知: 呼び出し元のプロセスを通知の宛先として登録するが、
実際にはメッセージが到着した時に通知は送られない。
-
SIGEV_SIGNAL
-
sigev_signo
で指定されたシグナルを送って、プロセスに通知する。
sigaction
(2) の
SA_SIGINFO
フラグで登録されたシグナルハンドラでそのシグナルが捕捉された場合、
シグナルハンドラの第二引き数として渡される
siginfo_t
構造体の各フィールドは以下のように設定される。
si_code
には
SI_MESGQ
が設定される。
si_signo
にはシグナル番号が設定される。
si_value
には
notification->sigev_value
で指定した値が設定される。
si_pid
にはメッセージを送信したプロセスの PID が、
si_uid
には送信プロセスの実ユーザ ID が設定される。
sigwaitinfo
(2) を使ってシグナルを受信する場合も、同じ情報が得られる。
-
SIGEV_THREAD
-
新しいスレッドの開始関数として
notification->sigev_thread_function
を起動することで通知を行う。
起動時の関数の引き数としては
notification->sigev_value
だけが渡される。
notification->sigev_notify_attributes
は、NULL 以外の場合、
そのスレッドの属性を定義する
pthread_attr_t
構造体へのポインタとなっている必要がある。
一つのメッセージキューから通知を受信するように登録できるプロセスは
一つだけである。
notification
が NULL で、かつ呼び出し元のプロセスがこのメッセージキューからの
通知を受信するに現在登録している場合、登録を削除する。
これ以降、別のプロセスがこのメッセージキューから通知を受信するように
登録できるようになる。
メッセージ通知は、それまで空のキューに新しいメッセージが到着した
場合にのみ行われる。
mq_notify
()が呼び出された時にそのキューが空でない場合、
そのキューが空になり、その後新しいメッセージが到着した時に
初めて通知が行われることになる。
別のプロセスやスレッドが
mq_receive
()を使って、空のキューからメッセージの読み出しを待っている場合、
メッセージ通知の登録は全て無視される。
メッセージは
mq_receive
()を呼び出しているプロセスやスレッドに配送され、
メッセージ通知の登録は効力を持ったままとなる。
通知は一度だけ行われる。通知が送られた後は、通知要求の登録は削除され、
別のプロセスがメッセージ通知を受信するように登録できるようになる。
通知を受けたプロセスが次の通知も受信したい場合は、
mq_notify
()を使ってその後の通知も受けるように要求することができる。
mq_notify
()を再度呼び出すのは、読み出していないメッセージを全部読み出して
キューが空になる前にすべきである
(キューからのメッセージ読み出しをキューが空になった時に
停止 (block) せずに行うには、キューを非停止モード (non-blocking mode)
に設定しておくとよい)。
返り値
成功すると、
mq_notify
()は 0 を返す。エラーの場合、-1 を返し、
errno
をエラーを示す値に設定する。
エラー
-
EBADF
-
mqdes
に指定されたディスクリプタが不正である。
-
EBUSY
-
別のプロセスがすでに
このメッセージキューに対する通知を受信するように登録している。
-
EINVAL
-
notification->sigev_notify
が許可された値のいずれでもない。もしくは
notification->sigev_notify
が
SIGEV_SIGNAL
だが
notification->sigev_signo
が有効なシグナル番号ではない。
-
ENOMEM
-
必要なメモリがなかった。
準拠
例
以下のプログラムは、
コマンドライン引き数で指定された名前のメッセージキューへの
通知要求を登録し、通知はスレッドの作成で行われる。
そのスレッドは、そのキューからメッセージを一つ読み出してから、
プロセスを終了する関数を実行する。
#include <pthread.h>
#include <mqueue.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define die(msg) { perror(msg); exit(EXIT_FAILURE); }
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) die("mq_getattr");
buf = malloc(attr.mq_msgsize);
if (buf == NULL) die("malloc");
nr = mq_receive(mqdes, buf, attr.mq_msgsize, NULL);
if (nr == -1) die("mq_receive");
printf("Read %ld bytes from MQ", (long) nr);
free(buf);
exit(EXIT_SUCCESS); /* プロセスを終了する */
}
int
main(int argc, char *argv[])
{
mqd_t mqdes;
struct sigevent not;
assert(argc == 2);
mqdes = mq_open(argv[1], O_RDONLY);
if (mqdes == (mqd_t) -1) die("mq_open");
not.sigev_notify = SIGEV_THREAD;
not.sigev_notify_function = tfunc;
not.sigev_notify_attributes = NULL;
not.sigev_value.sival_ptr = &mqdes; /* スレッド関数に渡す引き数 */
if (mq_notify(mqdes, ¬) == -1) die("mq_notify");
pause(); /* プロセスはスレッド関数により終了される */
}
関連項目
- Linux Tips 関連記事
- Linux Tips(目次)
- Linux ディストリビューション一覧
- rpm のファイル名にあるi386とかi686とは
- 自分のマシンの情報を調べる
- cron の設定
- ssh の root ログインを禁止する
- ssh を、ユーザ、IPでアクセス制限
- 鍵交換方式によるssh接続
- 鍵交換方式によるssh接続( windowsから )
- 複数ファイル内の文字列を置換して上書き保存する
- あるグループをイニシャルグループとするユーザー一覧出力
- 複数ファイルのファイル名を一括変換する
- 連番ファイルをコマンド一発で作成する
- 中身がランダムなファイルを任意のサイズで作成する
- Linux ユーザーアカウントをロック・アンロックする