消息队列
管道和共享内存:字节流数据 消息:数据报(类型+数据) 队列:优先级队列 可以指定类型来读取,在相同类型下,按照先进先出的顺序 消息队列的操作:
1.创建和访问一个消息队列 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
int msgget(key_t key, int msgflag);
key :某个消息队列的名字,给一个整型值即可msgflag :有两个选项IPC_CREAT和IPC_EXCL,单独使用IPC_CREAT,如果消息队列不存在则创建之,如果存在则打开返回;单独使用IPC_EXCL是没有意义的;两个同时使用,如果消息队列不存在则创建之,如果存在则出错返回。返回值 :成功返回一个非负整数,即消息队列的标识码,失败返回-1 2.把一条消息添加到消息队列中
int msgsnd(int msqid, const void *msqp, size_t msqsz, int msqflg);
msgid :由msgget函数返回的消息队列标识码msqp :指针指向准备发送的消息msqsz :消息结构中数据部分的大小,不包括类型大小msgflg :默认为0返回值 :成功返回0,失败返回-1
消息结构一方面必须小于系统规定的上限,另一方面必须以一个long int长整型开始,接受者以此来确定消息的类型
struct msgbuf
{
long mtye;
char mtext[1];
};
3.从一个消息队列接受消息
ssize_t msgrcv(int msqid, void *msqp, size_t msqsz, long msqtyp, int msqflg);
参数:与msgsnd相同 返回值:成功返回实际放到接收缓冲区里去的字符个数,失败返回-1 如果指定的空间不能将消息的数据完全存储下来,则本次读取不成功
4.消息队列的控制函数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msqid :由msgget函数返回的消息队列标识码cmd :有三个可选的值
IPC_STAT 把msqid_ds结构中的数据设置为消息队列的当前关联值 IPC_SET 在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值 IPC_RMID 删除消息队列
和之前一样,我们写两个程序,a向消息队列中写入数据,b从消息队列中读取数据。
完成下面的操作:
先连续发送三条消息: 然后,连续接收两个消息后发现消息队列中还剩下最后一条消息: 一旦消息队列中的消息被读完或者,读取不存在的消息,比如2号类型消息,那么终端显示就是阻塞状态
注意 :在接收消息的时候,如果将消息类型改为0,不代表接收0号消息,而是不区分消息类型,直接接收,最后靠接受者自己使用
msg.h
#program once
typedef struct msgbuf
{
long mtype;
char mtext[128];
}MsgBuf;
发送
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include"msg.h"
int main(int argc,char *argv[])
{
if(argc < 3)
{
printf("Please input type and data\n");
exit(0);
}
MsgBuf mess;
memset(&mess,0,sizeof(mess));
sscanf(argv[1],"%d",&mss.mtype);
strcpy(msss.mtext,argv[2]);
int msgid = msgget((key_t)1234,IPC_CREAT | 0664);
assert(msgid != -1);
msgsnd(msgid,&mess,strlen(mess,mtext),0);
exit(0);
}
接收(注意读取问题)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include"msg.h"
int main(int argc,char *argv[])
{
if(argc < 2)
{
printf("please input type\n");
exit(0);
}
MsgBuf mess;
memset(&mess,0,sizeof(mess));
long type = 0;
sscanf(argv[1],"%d",&type);
int msgid = msgget((key_t)1234,IPC_CREAT | 0664);
assert(msgid != -1);
msgrcv(msgid,&mess,127,type,0);
printf("type:%d,data :%s\n",mess.mtype,mess.mtext);
exit(0);
}
简单总结:
|