linux进程通信—消息队列
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向其中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。
(1)创建消息队列
使用下面的函数来创建消息队列:
– 参数“key”:消息队列关联的标识符
– 参数“msgflg”:消息队列的建立标志和存取权限。IPC_CREAT 如果内核
中没有此队列则创建它;IPC_EXCL 当和IPC_CREAT 一起使用时,如果
队列已经存在,则失败
– 返回值:执行成功则返回消息队列的标识符,否则返回-1
(2)操作消息队列
消息队列的操作可由下列函数来实现:
在msgrcv 和 msgsnd 中
–参数msqid:消息队列的标识码
– 参数*msgp:指向消息缓冲区的指针
– 参数msgsz:消息的长短
– 参数msgflg:标志位
– 返回值:成功返回数据长度,错误返回-1
1、第四个参数mtype指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将之返回。如果mtype 的值是零,函数将不做类型检查而自动返回队列中的最旧的消息。
2、第五个参数msgflg标志位如果取0,则表示忽略标志位,当然还有其他取值,这里不再展开介绍,如果需要用到其他取值可以使用man 2 msgrcv 来进行查看。
3、这里再介绍一下结构体msgp,是一个标准的通用结构
struct msgstru
{
long mtype; //必须大于0
char mtext[nbyte];
}
(3)代码展示
发送部分函数:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>
#define MAXSIZE 512
struct msgbuf
{
long int mtype;
char mtext[MAXSIZE];
};
int main()
{
key_t key = 1234;
struct msgbuf data;
int msgfd;
int flag = 1;
char buffer[BUFSIZ];//BUFSIZ的大小为8192
//创建消息队列获取标识码
msgfd = msgget(key,0666|IPC_CREAT);
if(msgfd == -1)
{
fprintf(stderr,"create messege failed:%d\n",errno);
exit(EXIT_FAILURE);
}
while(flag == 1)
{
printf("please input some messege:\n");
//将键盘上输入的数据读入缓冲区,stdin是标准输入
fgets(buffer,BUFSIZ,stdin);
data.mtype = 1;
strcpy(data.mtext,buffer);//将buffer中的数据复制到data.mtext
//发送数据
if((msgsnd(msgfd,(void*)&data,MAXSIZE,0) == -1))
{
fprintf(stderr,"messege send failed!\n");
exit(EXIT_FAILURE);
}
if((strncmp(buffer,"end",3)) == 0)
flag = 0;
sleep(1);
}
exit(EXIT_SUCCESS);
}
接受部分函数:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>
#define MAXSIZE 512
struct msgbuf
{
long int mtype;
char mtext[MAXSIZE];
};
int main()
{
struct msgbuf data;
int msgfd;
int flag = 1;
long int msgtyp = 0;
int ret;
key_t key = 1234;
//创建消息队列
msgfd = msgget(key,0666|IPC_CREAT);
if(msgfd == -1)
{
fprintf(stderr,"create messege failed:%d\n",errno);
exit(EXIT_FAILURE);
}
while(flag)
{
//读取消息队列中的数据
if((msgrcv(msgfd,(void*)&data,BUFSIZ,msgtyp,0)) == -1)
{
fprintf(stderr,"msgrcv failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("you have wrote:%s",data.mtext);
//判断输入结束程序
if((strncmp(data.mtext,"end",3)) == 0)
flag = 0;
}
//关闭消息队列
ret = msgctl(msgfd,IPC_RMID,0);
if(ret == -1)
{
fprintf(stderr,"msgctl failed:%d\n",errno);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}