消息队列是消息的链表,存储在内核中,由消息队列标识出标识。
msgget用于创建一个新队列或打开一个现有队列
#include<sys/msg.h>
int msgget(key_t key,int flag)
返回值:若成功,返回消息队列ID;若出错,返回-1。
msgsnd将新消息添加到队列尾端,每个消息包含一个正的长整型类型的字段,一个非负的长度以及实际数据字节数,所有这些都在讲消息添加到队列时,传送给msgsnd。
#include<sys/msg.h>
int msgsnd(int msgid,const void* ptr,size_t nbytes,int flag)
返回值:若成功,返回0;若出错,返回-1。
ptr参数指向一个长整型数,它包含了正的整形消息类型,其后紧接着的是消息数据。若发送的最长消息是512字节,则可定义下列结构
struct mymsg
{
long mtype;
char mtext[512];
};
ptr就是一个指向mymsg结构的指针。
msgrcv从队列中取用消息
#include<sys/msg.h>
ssize_t msgrcv(int msgid,void* ptr,size_t nbytes,long type,int flag);
返回值:若成功,返回消息数据部分长度;若出错,返回-1;
和msgsnd一样,ptr指向一个长整形数,其后紧跟着的是存储在实际消息数据的缓存区,nbytes指定数据缓存区的长度。若返回的消息长度大于nbytes,而且在flag中设置了MSG_NOERROR位,则该消息会被截断。如果没有设置这一标志,而消息又太长,则出错返回E2BIG(消息仍留在队列中)。
参数type可以指定想要哪一种消息
type==0 返回消息队列中的第一个消息
type>0 返回消息队列中消息类型为type的第一个消息
type<0 返回消息队列中消息类型小于等于type绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
msgctl函数对队列执行多种操作
#include<sys/msg.h>
int msgctl(int msgid,int cmd,struct msgid_ds* buf);
返回值:若成功,返回0;若出错,返回-1;
cmd 参数指定msgid指定的队列要执行的命令
IPC_STAT 取次队列的msgid_ds结构,并将它存放在buf指向的结构中
IPC_SET 将字段msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes从buf指向的结构复制到与这个消息队列相关的msgid_ds结构中。
IPC_RMID 从系统中删除该消息队列以及仍在该队列中的所有数据。
下面是利用消息队列进行进程间通信的例子
//msgsend.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/msg.h>
#include<errno.h>
#define MAXLEN 1024
struct mymsg
{
long mtype;
char mtext[MAXLEN];
};
int main()
{
int msgid;
char buf[MAXLEN];
int n;
int len;
struct mymsg data;;
if((msgid=msgget((key_t)1234,0666|IPC_CREAT))<0) //创建消息队列
{
fprintf(stderr,"msgset error:[%s]\n",strerror(errno));
exit(1);
}
while((fgets(buf,MAXLEN,stdin))!=NULL) //从标准输入读取数据
{
data.mtype=1;
len=strlen(buf);
strncpy(data.mtext,buf,len);
if((n=msgsnd(msgid,(void*)&data,len,0))<0) //发送到消息队列
{
fprintf(stderr,"msgsnd error:[%s]\n",strerror(errno));
exit(1);
}
}
}
//msgrcv.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<sys/msg.h>
#define MAXLEN 1024
struct mymsg
{
long mtype;
char mtext[MAXLEN];
};
int main()
{
char buf[MAXLEN];
int n;
int msgid;
struct mymsg data;
int type=1;
if((msgid=msgget((key_t)1234,0666|IPC_CREAT))<0) //打开一个消息队列
{
fprintf(stderr,"msgget error:[%s]\n",strerror(errno));
exit(1);
}
while((n=msgrcv(msgid,(void*)&data,MAXLEN,type,0))>0) //从消息队列接收数据
{
strncpy(buf,data.mtext,n);
write(STDOUT_FILENO,buf,n);
}
if(msgctl(msgid,IPC_RMID,0)<0) //关闭消息队列
{
fprintf(stderr,"msgctl(IPC_RMID) error:[%s]\n",strerror(errno));
exit(1);
}
exit(0);
}