Linux进程间通信之消息队列
一、引言:管道只能在一端读一端写,有一些局限性,而消息队列功能性更强,可以相互发送数据。
二、什么是消息队列:
消息队列是消息的链接表,存储在内核中,由消息队列标识符标识。在本节中,我们把消息队列简称为队列,其标识符简称为队列ID。
消息队列由内核来管理,我们只需要掌握如何创建或打开一个现有的消息队列,如何将新消息添加至指定队列尾端和从队列中获取消息,和控制消息队列(如删除消息队列)。
注:每个消息由3部分组成:一个正的长整型类型的字段、一个非负的长度(nbytes)和实际数据字节数(对应的长度)。消息总时放在队列尾端。
三、特点:
1.消息队列时面向记录的,其中的消息具有特定的格式以及特定的优先级
2.消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
3.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
四、如何创建(打开),添加消息或获取消息队列等操作
消息队列相关API(包含头文件<sys/msg.h>):
NAME
msgget - get a message queue identifier
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
//返回值:成功返回队列ID;失败返回-1
①功能:创建或打开消息队列
②参数:
*key详细请看标识符和键。
*flag:消息队列的建立标志和存取权限(例:msgget(key,IPC_CREAT|0666 )
①如果键的值是IPC_PRIVATE。
②或者键的值不是IPC_PRIVATE,并且键所对应的消息队列不存在,同时标志中指定IPC_CREAT。
五、函数msgsnd和msgrcv
1.msgsnd:
NAME
msgrcv, msgsnd - message operations
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *ptr, size_t size, int flg);
//返回值:若成功,返回0,若失败,返回-1
ssize_t msgrcv(int msqid, void *ptr, size_tsize, long typ,int flg);
//返回值:若成功,成功返回消息数据长度;若失败,返回-1
①功能:添加消息。
②参数:
*msqid:消息队列的ID。
*ptr:该参数指向一个长整型数,它包含了正的整型消息类型,其后紧接着时消息数据(若nbytes是0,则无消息数据)。若发送的最长是512字节的,则可定义下列结构体:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
*size:消息大小。
*flag:若为0,为默认方式:阻塞。
2.函数msgrcv:
①功能:读取消息。
②参数:
*msgid:消息队列的ID。
*ptr:如上文所示。
*size:消息的大小。
*type:消息的类型。
六、函数msgtcl:
NAME
msgctl - message control operations
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
//返回值:成功返回0;失败返回-1。
①功能:控制消息队列。
②参数:
*msqid:消息队列的ID。
*cmd:指定的队列要执行的命令,如 IPC_RMID可以删除该消息队列以及该队
列中所有的数据。
*buf:一般设置为NULL。
实例:
msgget.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
key_t key;
key = ftok(".",3);
printf("key = %x\n",key);
struct msgbuf buf;
struct msgbuf sendbuf = {988,"hi!"};
int msgID;
msgID = msgget(key,IPC_CREAT|0666);
int i = msgrcv(msgID,&buf,sizeof(buf.mtext),888,0);
if(i == -1) {
printf("get message error\n");
}
printf("data:%s\n",buf.mtext);
int j = msgsnd(msgID,&sendbuf,sizeof(sendbuf.mtext),0);
if(j == -1) {
printf("send message error\n");
}
return 0;
}
msgsend.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
int msgID;
key_t key;
key = ftok(".",3);
printf("key = %x\n",key);
struct msgbuf sendbuf = {888,"hallo from sendmsg.c"};
struct msgbuf buf;
msgID = msgget(key,IPC_CREAT|0666);
int j = msgsnd(msgID,&sendbuf,sizeof(sendbuf.mtext),0);
if(j == -1) {
printf("send message error\n");
}
int i = msgrcv(msgID,&buf,sizeof(buf.mtext),988,0);
if(i == -1) {
printf("get message error\n\n");
}
printf("data:%s\n",buf.mtext);
return 0;
}
编译运行getmsg.c,get阻塞。
编译运行sendmsg.c,get继续运行。
运行结果如下: