基本概念
消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值。
消息队列与管道同样有缺陷,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。
IPC数据结构
struct msqid_ds { struct ipc_perm msg_perm; /* Ownership and permissions */ time_t msg_stime; /* Time of last msgsnd(2) */ time_t msg_rtime; /* Time of last msgrcv(2) */ time_t msg_ctime; /* Time of last change */ unsigned long __msg_cbytes; /* Current number of bytes in queue (nonstandard) */ msgqnum_t msg_qnum; /* Current number of messages in queue */ msglen_t msg_qbytes; /* Maximum number of bytes allowed in queue */ pid_t msg_lspid; /* PID of last msgsnd(2) */ pid_t msg_lrpid; /* PID of last msgrcv(2) */ };
struct ipc_perm { key_t __key; /* Key supplied to msgget(2) */ uid_t uid; /* Effective UID of owner */ gid_t gid; /* Effective GID of owner */ uid_t cuid; /* Effective UID of creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions */ unsigned short __seq; /* Sequence number */ };
消息队列函数
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflg);
key: 某个消息队列的名字
msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf);
关于cmd
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgid: 由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备发送的消息,
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
消息结构
struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */ };
消息接收
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/msg.h> #define MsgMax 1024*10 struct msgbuf { long type; char text[MsgMax]; }; int main(int argc, char *argv[]) { int msgid; int ret = 0; int flag = 0; int type = 0; if (argc == 1) { fprintf(stderr, "Usage: %s <消息类型 type 0 1 2 3 .. -1 -2 -3> <n 阻塞 > \n", argv[0]); exit(EXIT_FAILURE); } if (argc == 2) { type = atoi(argv[1]); flag = 0; } if (argc == 3) { type = atoi(argv[1]); flag = flag | IPC_NOWAIT; } msgid = msgget(0x1234, IPC_CREAT|0666); if (msgid == -1) { if (errno == ENOENT) { printf("我们自己检查,,,,消息队列不存在\n"); } if (errno == EEXIST) { printf("我们自己检查,,,,消息队已经存在\n"); } perror("msgget err"); return -1; } printf("msgid:%d \n", msgid); struct msgbuf buf; memset(&buf, 0, sizeof(struct msgbuf)); ret = msgrcv(msgid, &buf, MsgMax, type, flag); if (ret < 0) { perror("msgsnd err"); return -1; } buf.text[ret] = '\0'; printf("mtext:%s \n", buf.text); return 0; }
消息发送
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/msg.h> struct msgbuf { long type; char text[1024]; }; int main() { int msgid; msgid=msgget(0x1234,IPC_CREAT|0666); if(msgid==-1) { if(errno==EEXIST) { printf("消息队列不存在\n"); } else if(errno==ENOENT) { printf("消息队列存在\n"); } else if(errno==EIDRM) { printf("队列标志为删除\n"); } else if(errno==ENOMEM) { printf("创建队列时内存不够\n"); } else if(errno==ENOSPC) { printf("超出最大队列限制\n"); } printf("error\n"); exit(0); } printf("msgid is %d\n",msgid); struct msgbuf buf; memset(&buf,0,sizeof(buf)); buf.type=2; strcpy(buf.text,"11111222223333344444"); int ret=msgsnd(msgid,&buf,10,IPC_NOWAIT); if(ret==-1) { printf("msgsnd error!\n"); exit(0); } return 0; }
消息状态查看
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/msg.h> int main() { int msgid; msgid=msgget(0x1234,IPC_CREAT|0666); if(msgid==-1) { if(errno==EEXIST) { printf("消息队列不存在\n"); } if(errno==ENOENT) { printf("消息队列存在\n"); } printf("error!\n"); exit(0); } printf("msgid is %d,消息队列创建成功!\n",msgid); struct msqid_ds buf; memset(&buf,0,sizeof(buf)); int ret=msgctl(msgid,IPC_STAT,&buf); if(ret==-1) { printf("获取消息队列状态失败!\n"); exit(0); } printf("权限信息 %o \n", buf.msg_perm.mode); printf("当前消息队列中有多少字节 %ld \n", buf.__msg_cbytes); printf("当前消息队列的个数 %d \n", buf.msg_qnum); return 0; }