プロセスがメッセージを送受信できるようにするには、msgget(2) 関数によって待ち行列を初期化しなければなりません。待ち行列の所有者または作成者は、msgctl(2) を使用して、その所有権またはアクセス権を変更できます。また、そうするためのアクセス権を持つプロセスは、制御操作のために msgctl(2) を使用することもできます。
IPC メッセージを使用すると、プロセスはメッセージを送受信し、メッセージを任意の順序で処理待ち行列に入れることができます。パイプで使用されるファイルバイトストリームのモデルによるデータフローとは異なり、IPC メッセージでは長さが明示されます。
メッセージには特定のタイプを割り当てることができます。このため、サーバプロセスは、クライアント PID をメッセージタイプとして使用して、その待ち行列上のクライアント間にメッセージトラフィックを振り向けることができます。単一メッセージトランザクションでは、複数のサーバプロセスは、共用メッセージ待ち行列に送られるトランザクション群に対して、並行して働くことができます。
メッセージの送受信操作は、それぞれ msgsnd(2) 関数と msgrcv(2) 関数によって実行されます。メッセージが送信されると、そのテキストがメッセージ待ち行列にコピーされます。msgsnd(2) 関数と msgrcv(2) 関数は、ブロッキング操作としても非ブロッキング操作としても実行できます。ブロッキングされたメッセージ操作は、次の条件のどれかが生じるまで中断されます。
呼び出しが成功した
プロセスがシグナルを受信した
待ち行列が削除された
msgget(2) 関数は、新しいメッセージ待ち行列を初期化します。また、key 引数に対応する待ち行列のメッセージ待ち行列 ID (msgid) を戻します。msgflg 引数として渡される値は、待ち行列アクセス権と制御フラグを設定する 8 進数の整数でなければなりません。
MSGMNI カーネル構成オプションは、カーネルがサポートする固有のメッセージ待ち行列の最大数を指定します。この制限を越えると、msgget(2) 関数は失敗します。次に、msgget(2) 関数の使用例を示します。
#include <sys/ipc.h>
#include <sys/msg.h>
...
key_t key; /* msgget() に渡す key */
int msgflg, /* msgget() に渡す msgflg */
msqid; /* msgget() からの戻り値 */ ...
key = ...
msgflg = ...
if ((msqid = msgget(key, msgflg)) == -1)
{
perror("msgget: msgget failed");
exit(1);
} else
(void) fprintf(stderr, "msgget succeeded");
...
|
msgctl(2) 関数は、メッセージ待ち行列のアクセス権やその他の特性を変更します。msgid 引数は、既存のメッセージ待ち行列の ID でなければなりません。cmd 引数は、次のいずれか 1 つです。
次に、msgctl(2) に各種のフラグをすべて付けて使用する例を示します。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
...
if (msgctl(msqid, IPC_STAT, &buf) == -1) {
perror("msgctl: msgctl failed");
exit(1);
}
...
if (msgctl(msqid, IPC_SET, &buf) == -1) {
perror("msgctl: msgctl failed");
exit(1);
}
...
|
msgsnd(2) と msgrcv(2) 関数は、それぞれメッセージを送受信します。msgid 引数は、既存のメッセージ待ち行列の ID でなければなりません。msgp 引数は、メッセージのタイプとテキストを含んでいる構造体へのポインタです。msgsz 引数は、メッセージの長さをバイト数で指定します。msgflg 引数には、様々な制御フラグを渡すことができます。
次に、msgsnd(2) と msgrcv(2) の使用例を示します。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
...
int msgflg; /* 操作用のメッセージフラグ */
struct msgbuf *msgp; /* メッセージバッファへのポインタ */
size_t msgsz; /* メッセージの長さ */
size_t maxmsgsize;
long msgtyp; /* 希望するメッセージタイプ */
int msqid /* 使用するメッセージ待ち行列の ID */
...
msgp = malloc(sizeof(struct msgbuf) - sizeof (msgp->mtext)
+ maxmsgsz);
if (msgp == NULL) {
(void) fprintf(stderr, "msgop: %s %ld byte messages.¥n",
"could not allocate message buffer for", maxmsgsz);
exit(1);
...
msgsz = ...
msgflg = ...
if (msgsnd(msqid, msgp, msgsz, msgflg) == -1)
perror("msgop: msgsnd failed");
...
msgsz = ...
msgtyp = first_on_queue;
msgflg = ...
if (rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) == -1)
perror("msgop: msgrcv failed");
...
|