消息队列是由链表实现的,它是基于system V标准。
特点:
- 双向通信;
- 基于消息(数据块);
- 不遵循“先入先出”的原则;
- 生命周期随内核;
创建新的消息队列或取得已存在的消息队列
int msgget(key_t key,int msgflg);
key:可认为是端口号,由ftok()函数生成;
msgflg:IPC_CREAT:如果IPC不存在,生成新的IPC资源,否则打开旧的资源,单独使用IPC_CREAT,msgget()返回的是新建共享内存的标识符或已有共享内存的操作符;
IPC_EXCL:只有在共享内存不存在时,再建立新的共享内存。它本身没有意义,和IPC_CREAT一起使用保证消息队列是新建的,而不是打开已有的资源。
向队列中读写数据
读数据:
size_t msgrcv(int msgid,void* msgp,size_t msgsz,long msgtyp,int msgflg)
msgid:消息队列标识码;
msgp:指向消息缓冲区的指针,用来暂存接收和发送消息;
msgsz:消息大小;
msgtyp:从消息队列读取消息的形态,为0时,所有消息将被读取;
msgflg:指示核心程序在队列为空时的行动。如果和IPC_NOWAIT合用时,表示读(空时)或写(满时)不会等待,立即返回-1,并设定错 误码为ENOMSG,当msgflg为零时,则会出现阻塞等待的处理模式。
设定消息队列属性:
int msgctl(int msgqid,int cmd,struct msgid_ds* buf);
参数:msgctl系统调用对msgqid标识的消息队列执行cmd操作,系统定义了3种cmd操作:
IPC_STAT:该命令用来获取消息队列对应的msgqid_ds数据结构,并将其保存到buf指向的地址空间
IPC_SET:用来设置消息队列的属性,要设置的属性保存在buf中
IPC_RMID:从内核中删除msgqid标识的消息队列
相关指令:
ipcs -q :查看系统中消息队列
ipcrm -q + msgid :删除消息队列
//client
#include<stdio.h>
#include<stdlib.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<string.h>
#define MSGKEY 1024
struct msgstru
{
long msgtype;
char msgtext[2048];
};
int main()
{
struct msgstru msgs;
int msg_type;
char str[256];
int ret_value;
int msgid;
msgid = msgget(MSGKEY,IPC_EXCL);
if(msgid < 0)
{
msgid = msgget(MSGKEY,IPC_CREAT|0666);
if(msgid < 0)
{
printf("failed to creat msgqueue!!!\n");
exit(-1);
}
}
while(1)
{
printf("input message type:");
scanf("%d",&msg_type);
printf("%d\n",msg_type);
if(msg_type == 0)
{
break;
}
printf("input message to be sent:");
scanf("%s",str);
msgs.msgtype = msg_type;
strcpy(msgs.msgtext,str);
//send
ret_value = msgsnd(msgid,&msgs,sizeof(struct msgstru),IPC_NOWAIT);
if(ret_value < 0)
{
printf("msgsnd() write msg failed");
exit(-1);
}
}
msgctl(msgid,IPC_RMID,0);//del
return 0;
}
//server
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#define MSGKEY 1024
struct msgstru
{
long msgtype;
char msgtext[2048];
};
void childproc()
{
struct msgstru msgs;
int msgid,ret_value;
char str[512];
while(1)
{
msgid = msgget(MSGKEY,IPC_EXCL);
if(msgid < 0)
{
printf("msg not existed!!!\n");
sleep(3);
break;
}
ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),0,0);
printf("text = [%s] pid = [%d]\n",msgs.msgtext,getpid());
}
return;
}
int main()
{
int i,cpid;
for(i=0;i<5;i++)
{
cpid = fork();
if(cpid < 0)
{
printf("fork failed\n");
}
else if(cpid == 0)
childproc();
}
return 0;
}