System V 消息队列
一、System V 消息队列
有一个队列,队列存放各种消息。每个进程可以把数据封存在消息中,再放入队列。每个进程都可以拿到消息队列,再从中取出/放入消息。
消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。
二、msgget函数
. msgget函数原型:用于创建一个新的消息队列或访问一个已存在的消息队列
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
注意:
msgid = msgget(1234, 0); //按照原有权限打开该消息队列
1. 测试代码:
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int msgid;
msgid = msgget(1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("msgget succ\n");
printf("msgget = %d\n", msgid);
return 0;
}
输出结果:
2. 测试代码:
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int msgid;
msgid = msgget(IPC_PRIVATE, 0666);
if (msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("msgget succ\n");
printf("msgget = %d\n", msgid);
return 0;
}
输出结果:
3. 测试代码:
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int msgid;
msgid = msgget(1234, 0400 | IPC_CREAT);
if (msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("msgget succ\n");
printf("msgget = %d\n", msgid);
msgid = msgget(1234, 0600 | IPC_CREAT);
if (msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
return 0;
}
输出结果:
三、msgsnd函数
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
int main(int argc, const char *argv[])
{
int msgid;
msgid = msgget(1234, 0);
if (msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("msggget succ\n");
printf("msgid = %d\n", msgget);
struct msqid_ds buf;
msgctl(msgid, IPC_STAT, &buf);
printf("mode = %o\n", buf.msg_perm.mode);
printf("bytes = %ld\n", buf.__msg_cbytes);
printf("msg_qnum = %d\n", (int)buf.msg_qnum);
printf("msg_qbytes = %d\n", (int)buf.msg_qbytes);
return 0;
}
输出结果:
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
int main(int argc, const char *argv[])
{
int msgid;
msgid = msgget(1234, 0);
if (msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("msggget succ\n");
printf("msgid = %d\n", msgget);
struct msqid_ds buf;
sscanf("666", "%o", (unsigned int *)&buf.msg_perm.mode);
msgctl(msgid, IPC_SET, &buf);
return 0;
}
输出结果:
四、msgsnd函数
msgsnd函数原型:把一条消息添加到消息队列中
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
- msgid:有msgget函数返回的消息队列标识码
- msgp:是一个指针,指针指向准备发送的消息
- msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
- msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
1. 测试代码:
程序1:
//msg_stat.c
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
int main(int argc, const char *argv[])
{
int msgid;
msgid = msgget(1234, 0);
if (msgid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("msggget succ\n");
printf("msgid = %d\n", msgget);
struct msqid_ds buf;
msgctl(msgid, IPC_STAT, &buf);
printf("mode = %o\n", buf.msg_perm.mode);
printf("bytes = %ld\n", buf.__msg_cbytes);
printf("msg_qnum = %d\n", (int)buf.msg_qnum);
printf("msg_qbytes = %d\n", (int)buf.msg_qbytes);
return 0;
}
程序2:
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage:%s<bytes> <type>\n", argv[0], argv[1]);
exit(EXIT_FAILURE);
}
int len = atoi(argv[1]);
int type = atoi(argv[2]);
int msgid;
msgid = msgget(1234, 0);
if (msgid == -1)
{
perrro("msgget");
exit(EXIT_FAILURE);
}
struct msgbuf *ptr;
ptr(struct msgbuf*) malloc(sizeof(long) + len);
ptr->mtype = type;
if (msgsnd(msgid, ptr, len, 0) < 0) //阻塞方式
{
perrro("msgsnd");
exit(EXIT_FAILURE);
}
return 0;
}
输出结果: