一 消息队列
消息队列就是一些消息的列表,用户可以在消息队列中添加消息和读取消息灯。消息队列具有一定的FIFO特性,但是它可以实现消息的随机查询,比FIFO更具有优势。同时,这些消息又是存在于内核中的,由“队列ID”来标识。
二 函数学习
三 实例
在该实例当中,发送端发送的消息类型设置为该进程的进程号(也可以取其他值),因此接受端根据消息类型来确定消息发送者的进程号。
messagesend.c
//使用消息队列发送信息
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define BUFF_SIZE 512
struct message{
long msg_type;
char msg_text[BUFF_SIZE];
};
void main()
{
key_t key=0;
int qid;
struct message msg;
if( (key=ftok(".",'a')) == -1)
{
//创建键值失败
printf("creat key error\n");
exit(0);
}
//创建消息队列
/*****************************
函数原型:int msgget(key_t key,int msgflg)
函数参数:key 消息队列的键值,多个进程通过它访问一个消息
队列
msgflg 权限标志位
返回值:成功 返回消息队列的ID
失败 返回-1
*****************************/
if((qid=msgget(key,IPC_CREAT|0666))==-1)
{
printf("msgget\n",-1);
exit(0);
}
//打印消息队列的ID
printf("open queue %d\n",qid);
while(1)
{
printf("Enter some message to the queue:\n");
if((fgets(msg.msg_text,BUFF_SIZE,stdin))==NULL)
{
printf("no message\n");
exit(1);
}
msg.msg_type=getpid();
/*****************************
函数原型:int msgsnd(int msqid,
const void *msqp,
size_t msgsz,
int msgflg)
函数参数: msqid 消息队列的id
msqp 指向消息结构的指针,该消息结构msgbuf通常如下
struct msgbuf
{
long mtype; //消息类型,该结构必须从这个域开始
char mtext[];//消息正文
}
msgsz 消息正文的字节数(不包括消息类型指针变量)
msgflg IPC_NOWAIT:若消息无法立即发送,函数会立刻返回
0 msgsnd:调用阻塞直到发送成功为止
返回值: 成功 0
失败 -1
*****************************/
if(msgsnd(qid,&msg,strlen(msg.msg_text),0)==-1)
{
printf("msgsnd error\n");
exit(0);
}
if(strncmp(msg.msg_text,"quit",4)==0)
{
break;
}
}
exit(0);
}
messagereceive.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define BUFF_SIZE 512
struct message{
long msg_type;
char msg_text[BUFF_SIZE];
};
void main()
{
int qid;
key_t key;
struct message msg;
if( (key=ftok(".",'a')) == -1)
{
//创建键值失败
printf("creat key error\n");
exit(0);
}
if((qid=msgget(key,IPC_CREAT|0666))==-1)
{
printf("msgget\n",-1);
exit(0);
}
//打印消息队列的ID
printf("open queue %d\n",qid);
do
{
/************************
函数原型:void *memset(void *s, int ch, size_t n);
函数描述:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s
************************/
memset(msg.msg_text,0,BUFF_SIZE);
/*读取消息队列*/
/********************
函数原型:ssize_t msgrcv(int msqid,
void *msgp,
size_t msgsz,
long msgtyp,
int msgflg)
函数参数:msqid 消息队列的ID
msgp 消息缓冲区,通msgsnd()函数的msgp
msgsz 消息正文的字节数 (不包括消息类型指针变量)
msgtyp 0 接受消息队列中的第一个消息
大于0 接受消息队列中第一个类型为msgtyp的消息
小于0 接受消息队列中第一个类型值不小于msgtyp绝对值且类型值最小的消息
msgflg 0 msgsnd()调用阻塞直到接受一条相应类型的消息为止
函数返回值:成功 0
失败 -1
********************/
if(msgrcv(qid,(void *)&msg,BUFF_SIZE,0,0)<0)
{
printf("msgrcv\n");
exit(0);
}
printf("the message from %d:%s",msg.msg_type,msg.msg_text);
}while(strncmp(msg.msg_text,"quit",4));
//删除消息队列
/*
函数原型:int msgctl(int msgqid,int cmd,struct msgqid_ds *buf)
函数参数:msgqid 消息队列的队列id
cmd IPC_STAT 读取消息队列的数据结构msqid_ds,并将其存储在buf指定的地址中
IPC_SET 设置消息队列的数据结构msqid_ds中的ipc_perm域值,这个值取自buf参数
IPC_RMID 从内核中删除消息队列
buf 描述消息队列的msqid_ds结构类型变量
返回值:
*/
if(msgctl(qid,IPC_RMID,NULL)<0)
{
printf("msgctl\n");
exit(0);
}
}
运行结果: