消息队列是一种消息的链表,用户可以对消息队列写入信息,读取信息。与无名管道类似,可以实现不相关进程之间的通信,但不同的是消息队列可以实现对消息的查询读取。
消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列这四种操作。实现消息队列的四种操作的函数
int msgget(key_t key, int msgflg);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
prt:指向消息结构的指针。该消息结构 msgbuf 为:
struct msgbuf{
long mtype;//消息类型
char mtext[1];//消息正文}
size_t msgsz 为消息字节数
flag:IPC_NOWAIT 若消息并没有立即发送而调用进程会立即返回函数传入值
0:msgsnd 调用阻塞直到条件满足为止
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgp:消息缓冲区
msgsz:消息字节数
msgtyp :消息类型
0:接收消息队列中第一个消息
大于 0:接收消息队列中第一个类型为 msgtyp 的消息Msgtype:
小于 0:接收消息队列中第一个类型值不小于 msgtyp 绝对值且类型
值又最小的消息
flag:MSG_NOERROR 若返回的消息比 size 字节多,则消息就会截短到size 字节,且不通知消息发送进程
IPC_NOWAIT 若消息并没有立即发送而调用进程会立即返回函数传入值
0:msgsnd 调用阻塞直到条件满足为止
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd命令
IPC_STAT:读取消息队列的数据结构 msqid_ds,并将其存储在
buf 指定的地址中
IPC_SET:设置消息队列的数据结构 msqid_ds 中的 ipc_perm 元
素的值。这个值取自 buf 参数
IPC_RMID:从系统内核中移走消息队列
buf:消息缓冲区
应用实例:使用消息队列实现两个进程之间的通信,发送端接收终端输入字符串,接收端将接收到的字符显示到终端,以end结束输入。
接收端实例
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
/************************************
int msgget(key_t key, int msgflg);
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);
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
*************************************/
#define MAX_SIZE 512
struct msgbuf_struct
{
long mtype; /* message type, must be > 0 */
char mtext[MAX_SIZE]; /* message data */
};
int main()
{
struct msgbuf_struct data;
char buffer[BUFSIZ];
int msgid=-1;
int run_flag=1;
long int msgtyp=0;
msgid=msgget((key_t)1234,IPC_CREAT|0666);
if(msgid==-1)
{
printf("Creat message Queue failed!!\n");
exit(EXIT_FAILURE);
}
while(run_flag)
{
if(msgrcv(msgid, (void *)&data, BUFSIZ, msgtyp, 0)==-1)
{
printf("recived message failed!\n");
exit(EXIT_FAILURE);
}
printf("You write data is %s",data.mtext);
if(strncmp(data.mtext,"end",3)==0)//字符串比较函数
{
run_flag=0;
}
sleep(1);
}
if(msgctl(msgid,IPC_RMID, 0)==-1)
{
printf("close msgqueue failed!!\n");
}
return 0;
}
发送端实例
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
/************************************
int msgget(key_t key, int msgflg);
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);
*************************************/
#define MAX_SIZE 512
struct msgbuf_struct
{
long mtype; /* message type, must be > 0 */
char mtext[MAX_SIZE]; /* message data */
};
int main()
{
struct msgbuf_struct data;
char buffer[BUFSIZ];
int msgid=-1;
int run_flag=1;
msgid=msgget((key_t)1234,IPC_CREAT|0666);
if(msgid==-1)
{
printf("Creat message Queue failed!!\n");
exit(EXIT_FAILURE);
}
while(run_flag)
{
printf("Enter some data:");
fgets(buffer,BUFSIZ,stdin);
strcpy(data.mtext,buffer);
data.mtype=1; //制定为发送操作
if((msgsnd(msgid,(void*)&data,MAX_SIZE,0))==-1) //标志位给定为0
{
printf("send message failed!!\n");
exit(EXIT_FAILURE);
}
if(strncmp(buffer,"end",3)==0)//字符串比较函数
{
run_flag=0;
}
sleep(1);
}
return 0;
}