System V メッセージキュー

System V メッセージキューは、メッセージキュー識別子で識別される。カーネルはシステム内のすべてのメッセージキューに対して、その情報をで定義される struct msqid_dsを用いて保持する。

struct msqid_ds {
    struct ipc_perm msg_perm; /* 読み書き許可ビット */
    struct msg *msg_first; /* キュー上の先頭のメッセージへのポインタ */
    struct msg msg_last; /* キュー上の最後のメッセージへのポインタ */
    msglen_t msg_cbytes; /* キュー上のバイト数 */
    msgqnum_t msg_qnum; /* キュー上のメッセージ数 */
    msglen_t msg_qbytes; /* 最大バイト数 */
    pid_t msg_lspid; /* 最後のmsgsnd()を行ったプロセスのID */
    pid_t msg_lrpid; /* 最後のmsgrcv()を行ったプロセスのID */
    time_t msg_stime; /* 最後のmsgsnd()の時刻 */
    time_t msg_ctime; /* 最後のmsgctl()の時刻 */
};



msgget関数

#include <sys/msg.h>

int msgget(key_t key, int oflag);

戻り値:成功なら非負の識別子、エラーなら-1

引数keyには、ftokが返した値か、IPC_PRIVATE定数を指定できる。
oflagは、読み書き許可ビット。IPC_CREATか、IPC_CREAT | IPC_EXCL。
新しいメッセージキューが加算されると、mqqid_ds構造体のメンバ

初期化されるメンバ初期化される値
msg_perm.uid実効ユーザID
msg_perm.cuid実効ユーザID
msg_perm.gid実効グループID
msg_perm.cgid実効グループID
msg_perm.modeoflag中の読み書きビット
msg_qnumゼロ
msg_lspidゼロ
msg_lrpidゼロ
msg_stimeゼロ
msg_rtimeゼロ
msg_ctime初期化の時刻
msg_qbytesシステムの限界値

msgsnd関数

msggetでオープンしたメッセージキューには、msgsndを用いてメッセージを置くことができる。

#include <sys/msg.h>

int msgsnd(int msqid, const void *ptr, size_t length, int flag);

戻り値:成功なら0、エラーなら-1

msqidは、msggetが返した識別子。ptrは、で定義されているstruct msgbuf構造体へのポインタ。

struct msgbuf {
    long mtype; /* メッセージタイプ (ゼロ以上) */
    char mtext[1]; /* メッセージデータ */
};

しかし、1バイトのメッセージを用いることは適切ではないため、このmsgbuf構造体を通常用いない。
大半のアプリケーションでは、独自のメッセージ構造体を定義している。

flag引数は、ゼロまたはIPC_NOWAIT。このフラグは、msgsndの呼び出しを非ブロッキングにする。


msgrcv関数

#include <sys/msg.h>

ssize_t msgrcv(int msqid, 
               void *ptr, 
               size_t length, 
               long type, 
               int flag);

戻り値:成功ならバッファに読み込まれたバイト数、エラーなら-1

typeは、キュー上のどのメッセージを取り出すかを指定する。

  • 1.type == 0

  • キューの先頭(キューの最も古い)のメッセージが返される。

  • 2.type > 0

  • そのtypeを持つ先頭のメッセージが返される。

  • 3.type < 0

  • typeの絶対値と等しいかまたは小さなタイプを持つメッセージの中で、最も小さなタイプを持つ最初のメッセージが返される。


    flag引数は、指定したメッセージがキュー上にない場合の動作を指定する。

  • IPC_NOWAITビットが設定され、かつメッセージが存在しない場合、msgrcv関数は即座にENOMSGエラーを返す。

  • そうでない場合は

    1.供給したタイプのメッセージが置かれた場合

    2.msqidで識別されるメッセージキューが、システムから削除された場合(この場合は、EIDRMエラーが返される。)

    3.呼び出したスレッドが、捕捉したシグナルによって割り込まれた場合(この場合はEINTRエラーが返される。)


  • flag引数で、MSG_NOERRORビットを指定すると、受信したメッセージのデータ部の大きさがlength引数よりも大きくても、エラーを返さずにデータを切り捨てることを指示する。MSG_NOERRORを指定していない場合は、メッセージの全長がlengthを越えるならばE2BIGエラーが返される。


    msgctl関数

    msgctlを用いて、メッセージキューに対して種々の操作を施すことが出来る。

    #include <sys/msg.h>
    
    int msgctl(int msqid, int cmd, struct msqid_ds *buff);
    
    戻り値:成功なら0、エラーなら-1




    cmdに与えるコマンド

    IPC_RMIDmsqidで指定されるメッセージキューを、システムから削除する。
    IPC_SETmsqid_ds構造体のmsg_perm.uid, msg_perm.gid, msg_perm.mode, msg_qbytesメンバを、buff引数が指す構造体の対応するメンバの値に設定する
    IPC_STAT指定されたメッセージキューのmsqid_ds構造体を、buff引数を通して呼び出し側に返す






    参考:UNIXネットワークプログラミング Vol.2 スティーヴンズ