プログラミングインタフェース

System V メッセージ

プロセスがメッセージを送受信できるようにするには、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 つです。

IPC_STAT

待ち行列の状態の情報を buf が指すデータ構造体に入れます。この呼び出しを行うには、プロセスが読み取り権を持つ必要があります。

IPC_SET

所有者のユーザー ID とグループ ID、アクセス権、およびメッセージ待ち行列の大きさ (バイト数) を設定します。この呼び出しを行うには、プロセスが所有者、作成者、またはスーパーユーザーの有効なユーザー ID を持つ必要があります。

IPC_RMID

msqid 引数で指定したメッセージ待ち行列を削除します。

次のコードに、さまざまなフラグをすべて指定した 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");
...