プロセスがメッセージを送受信できるようにするには、msgget(2) を使用して待ち行列を初期化する必要があります。待ち行列の所有者または作成者は msgctl(2) を使用して、所有権またはアクセス権を変更できます。アクセス権を持つプロセスは msgctl(2) を使用して、操作を制御できます。
IPC メッセージを使用すると、プロセスはメッセージを送受信し、メッセージを任意の順序で処理待ち行列に入れることができます。パイプで使用されるファイルバイトストリームのモデルによるデータフローとは異なり、IPC メッセージでは長さが明示されます。
メッセージには特定のタイプを割り当てることができます。このため、サーバープロセスはクライアントプロセス ID をメッセージタイプとして使用することによって、その待ち行列上のクライアント間にメッセージトラフィックを振り向けることができます。単一メッセージトランザクションでは、複数のサーバープロセスは、共有メッセージ待ち行列に送られるトランザクション群に対して、並行して働くことができます。
メッセージを送受信する操作は、それぞれ msgsnd(2) と msgrcv(2) によって実行されます。メッセージが送信されると、そのテキストがメッセージ待ち行列にコピーされます。msgsnd(2) と msgrcv(2) は、ブロック操作としても非ブロック操作としても実行できます。ブロックされたメッセージ操作は、次の条件のどれかが生じるまで中断されます。
呼び出しが成功した。
プロセスがシグナルを受信した。
待ち行列が削除された。
msgget(2) は、新しいメッセージ待ち行列を初期化します。また、キー引数に対応する待ち行列のメッセージ待ち行列 ID (msqid) を返すこともできます。msgflg 引数として渡される値は、待ち行列アクセス権と制御フラグを設定する 8 進数の整数である必要があります。
MSGMNI カーネル構成オプションは、カーネルがサポートする固有のメッセージ待ち行列の最大数を指定します。この制限を超えると、msgget(2) 関数は失敗します。
次のコードに、msgget(2) の使用例を示します。
#include <sys/ipc.h>
#include <sys/msg.h>
...
key_t key; /* key to be passed to msgget() */
int msgflg, /* msgflg to be passed to msgget() */
msqid; /* return value from 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 つです。
待ち行列の状態の情報を buf が指すデータ構造体に入れます。この呼び出しを行うには、プロセスが読み取り権を持つ必要があります。
所有者のユーザー ID とグループ ID、アクセス権、およびメッセージ待ち行列の大きさ (バイト数) を設定します。この呼び出しを行うには、プロセスが所有者、作成者、またはスーパーユーザーの有効なユーザー ID を持つ必要があります。
次のコードに、さまざまなフラグをすべて指定した 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; /* message flags for the operation */
struct msgbuf *msgp; /* pointer to the message buffer */
size_t msgsz; /* message size */
size_t maxmsgsize; /* maximum message size */
long msgtyp; /* desired message type */
int msqid /* message queue ID to be used */
...
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");
...