メッセージキューはパイプとより扱いが簡単でちょっと嬉しい.
メッセージキューに関する関数
サンプル
メッセージキューに関する関数
メッセージキューに関する関数として,以下がある.
int msgget(key_t key, int msgflg);
指定したkeyのメッセージキュー識別子を取得.msgflgにはパーミッションやオプションなどを指定する.これにIPC_CREATを指定すると,指定したkeyのメッセージキューがない場合は作成してくれる.
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
メッセージの送信.
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);
メッセージの受信.
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
メッセージキューの制御.メッセージキューを消したりできる.
パターンとしては,以下のようになるだろうか.
msggetでメッセージキューを作成,取得する.
msgsndで送信,msgrcvで受信.
msgctlでメッセージキューを削除する.
サンプル
以上を踏まえてサンプルを示す.まず送信側.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* ��å��������塼�������������å�����
msgsnd,msgrcv��*msgp�ˤϤ��ι�¤�ΤؤΥݥ���� */
struct msgbuf{
/* ��å���������Ƭ�Ϥ��ʤ餺long int���Ǥʤ���Фʤ�ʤ� */
long int type;
char data[BUFSIZ];
};
int main(int argc, char *argv[])
{
/* ��å��������塼��ID */
int msqid;
/* ������ */
struct msgbuf message;
/* �ѥ��������å� */
if(argc != 3){
fprintf(stderr,"Usage: %s type string\n",argv[0]);
exit(EXIT_FAILURE);
}else{
/* message��type�����Ǥʤ���Фʤ�ʤ� */
if((message.type = atol(argv[1])) <= 0){
fprintf(stderr,"type value is invalid\n");
exit(EXIT_FAILURE);
}
strncpy(message.data,argv[2],BUFSIZ);
}
/* ��å��������塼�κ���,���� */
errno = 0;
if((msqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1){
perror("msgget failure");
exit(EXIT_FAILURE);
}
/* ������������ */
errno = 0;
if(msgsnd(msqid, &message, BUFSIZ, 0) == -1){
perror("msgsnd failure");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
そして受信側.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* ��å��������塼�������������å�����
msgsnd,msgrcv��*msgp�ˤϤ��ι�¤�ΤؤΥݥ���� */
struct msgbuf{
/* ��å���������Ƭ�Ϥ��ʤ餺long int���Ǥʤ���Фʤ�ʤ� */
long int type;
char data[BUFSIZ];
};
int main(int argc, char *argv[])
{
/* ��å��������塼��ID */
int msqid;
/* ������ */
struct msgbuf message;
long int read_type;
/* �ѥ��������å� */
if(argc != 2){
fprintf(stderr,"Usage: %s type\n",argv[0]);
exit(EXIT_FAILURE);
}else{
/* ���������פ����� */
read_type = atol(argv[1]);
}
/* ��å��������塼�κ���,���� */
errno = 0;
if((msqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1){
perror("msgget failure");
exit(EXIT_FAILURE);
}
while(1){
/* ��å������μ��� */
errno = 0;
if(msgrcv(msqid, &message, BUFSIZ, read_type, 0) == -1){
perror("msgrcv failure");
break;
}else{
fprintf(stdout,"received message:\t%s\n",message.data);
}
/* "exit"���������Ƚ�λ���� */
if(strcmp(message.data, "exit") == 0){
break;
}
}
/* ��å��������塼�κ�� */
errno = 0;
if(msgctl(msqid, IPC_RMID, NULL) == -1){
perror("msgctl failure");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
メッセージは構造体を介して送受信する.この構造体はサンプルのmsgbufのように最初のフィールドをlong int型にしてメッセージタイプ(正の整数)を指定する.サンプルの送信側mq-sndでは引数にこのメッセージタイプとメッセージ文字列を引数に渡す.
$ ./mq-snd 2 type2
$ ./mq-snd 3 type3
$ ./mq-snd 1 type1
メッセージキューが一杯だと,メッセージキューに空きがでるまで待たされる.ノンブロッキンブモードにするには,msgsndのmsgflgにIPC_NOWAITを指定する.サンプルの受信側mq-rcvでは,受信するメッセージタイプを引数に渡す.
$ ./mq-rcv -2
received message: type2
received message: type1
あらかじめ先のmq-sndを実行していた場合の結果である.上の様に負の数を渡すと,そのタイプの値以下のメッセージをキューから取り出す.取り出されなかったメッセージはキューに残っている.
$ ./mq-rcv 0
received message: type3
この様にtypeに0を指定するとすべてのtypeがマッチする(注:mq-sndで文字列exitを送信してmq-rcvを終了すると,mq-rcv内でメッセージキューを削除するので,上の結果にはならない).