sys V 进程间通信之消息队列
note
msgget获取内核消息队列实例
msgctl可以删除内核消息队列实例
msgsnd\msgrcv函数注意struct msgbuf字段的填充
code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <getopt.h>struct msgbuf {long mtype;char mtext[80];
};static void usage(char *prog_name, char *msg)
{if (msg != NULL)fputs(msg, stderr);fprintf(stderr, "Usage: %s [options]\n", prog_name);fprintf(stderr, "Options are:\n");fprintf(stderr, "-s send message using msgsnd()\n");fprintf(stderr, "-r read message using msgrcv()\n");fprintf(stderr, "-t message type (default is 1)\n");fprintf(stderr, "-k message queue key (default is 1234)\n");fprintf(stderr, "-R remove msg queue\n");exit(EXIT_FAILURE);
}static void send_msg(int qid, int msgtype)
{struct msgbuf msg;time_t t;msg.mtype = msgtype;time(&t);snprintf(msg.mtext, sizeof(msg.mtext), "a message at %s", ctime(&t));if (msgsnd(qid, (void *) &msg, sizeof(msg.mtext), IPC_NOWAIT) == -1) {perror("msgsnd error");exit(EXIT_FAILURE);}printf("sent: %s\n", msg.mtext);
}static void get_msg(int qid, int msgtype)
{struct msgbuf msg;if (msgrcv(qid, (void *)&msg, sizeof(msg.mtext), msgtype, MSG_NOERROR | IPC_NOWAIT) == -1) {if (errno != ENOMSG) {perror("msgrcv");exit(EXIT_FAILURE);}printf("No message available for msgrcv()\n");} elseprintf("message received: %s\n", msg.mtext);
}static void remove_msg_queue(int qid) {int ret = -1;ret = msgctl(qid, IPC_RMID, NULL);if (ret == -1) {perror("msgctl");exit(EXIT_FAILURE);}
}int main(int argc, char *argv[])
{int qid, opt;int mode = 0; /* 1 = send, 2 = receive */int msgtype = 1; /* default msg type:1 */int msgkey = 1234; /* default sysV ipc key:1234 */int need_remove = 0;while ((opt = getopt(argc, argv, "srt:k:R")) != -1) {switch (opt) {case 's':mode = 1;break;case 'r':mode = 2;break;case 't':msgtype = atoi(optarg);if (msgtype <= 0)usage(argv[0], "-t option must be greater than 0\n");break;case 'k':msgkey = atoi(optarg);break;case 'R':need_remove = 1;break;default:usage(argv[0], "Unrecognized option\n");}}if (mode == 0 && need_remove == 0)usage(argv[0], "must use -s or -r or -R option\n");qid = msgget(msgkey, IPC_CREAT | 0666);if (qid == -1) {perror("msgget");exit(EXIT_FAILURE);}if (mode == 2)get_msg(qid, msgtype);else if (mode == 1)send_msg(qid, msgtype);if (need_remove == 1) {remove_msg_queue(qid);}exit(EXIT_SUCCESS);
}
test