消息队列的使用:
创建打开消息队列msgget()
读数据从队列msgrcv()
写数据到队列msgsnd()
控制消息队列msgctl()
目前主要有两种类型的消息队列:
POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用
消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值
函数ftok
函数功能:返回文件名对应的键值
函数原型:key_t ftok (char*pathname, char proj)
函数参数:pathname: 文件名
proj:项目名(不为0即可)
头文件 :
#include <sys/types.h>
#include <sys/ipc.h>
返回值 :文件名对应的键值
函数msgget
函数功能:创建,打开消息队列
函数原型:int msgget(key_t key, int msgflg);
函数参数:key:键值,由ftok获得
msgflg:标志位
头文件 :
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
返回值 :与健值key相对应的消息队列描述字
创建一个新的消息队列:
1、如果没有与健值key相对应的消息队列,并且 msgflg中包含了IPC_CREAT标志位。
2、key参数为IPC_PRIVATE
函数msgsnd
函数功能:向消息队列中发送一条消息
函数原型:
int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg);
函数参数:Msqid:已打开的消息队列id
Msgp:存放消息的结构
Msgsz:消息数据长度
Msgflg:发送标志,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待
头文件 :
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
返回值 :成功:0出错:-1
消息结构:
struct msgbuf
{
long mtype;/*消息类型*/
char mtext[1]; /*消息数据的首地址*/
}
函数msgrcv
函数功能:从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中。在成功地读取了一条消息以后,队列中的这条消息将被删除
函数原型:int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
函数参数:msgtyp :消息的类型号
头文件 :
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
返回值 :
Msg_rd.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msg_st
{
long int my_msg_type;
char some_text[BUFSIZ];
};
int main(void)
{
int running=1;
int msgid;
struct my_msg_st some_data;
long int msg_to_receive=0;
/*创建消息队列*/
msgid=msgget((key_t)1234,0666 | IPC_CREAT);
if(msgid==-1)
{
fprintf(stderr,"msgget failed with error: %d\n",errno);
exit(EXIT_FAILURE);
}
/*循环从消息队列中接收消息*/
while(running)
{
/*读取消息*/
if(msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)==-1)
{
fprintf(stderr,"msgrcv failed with error: %d\n",errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s",some_data.some_text);
/*接收到的消息为“end”时结束循环*/
if(strncmp(some_data.some_text,"end",3)==0)
{
running=0;
}
}
/*从系统内核中移走消息队列*/
if(msgctl(msgid,IPC_RMID,0)==-1)
{
fprintf(stderr,"msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
Msg_wr.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT 512
struct my_msg_st
{
long int my_msg_type;
char some_text[MAX_TEXT];
};
int main(void)
{
int running=1;
struct my_msg_st some_data;
int msgid;
char buffer[BUFSIZ];
/*创建消息队列*/
msgid=msgget((key_t)1234,0666 | IPC_CREAT);
if(msgid==-1)
{
fprintf(stderr,"msgget failed with error:%d\n",errno);
exit(EXIT_FAILURE);
}
/*循环向消息队列中添加消息*/
while(running)
{
printf("Enter some text:");
fgets(buffer,BUFSIZ,stdin);
some_data.my_msg_type=1;
strcpy(some_data.some_text,buffer);
/*添加消息*/
if(msgsnd(msgid,(void *)&some_data,MAX_TEXT,0)==-1)
{
fprintf(stderr,"msgsed failed\n");
exit(EXIT_FAILURE);
}
/*用户输入的为“end”时结束循环*/
if(strncmp(buffer,"end",3)==0)
{
running=0;
}
}
exit(EXIT_SUCCESS);
}
Msg_rd.c 和 Msg_wr.c 编译后要在Linux下的两个终端里面运行,能实现一个终端循环输入,另一个终端循环输出