消息队列概述
消息队列是存在Linux内核中,以链表形式来存消息
一个消息队列由一个标识符(即队列ID)来标识。
用户进程可以向消息队列添加消息,也可以向消息队列读取消息。
特点
消息队列是面向记录的,其中的消息具有特定的格式(结构体保存)
消息队列独立于发送与接收进程,哪怕进程退出后消息还会保存
消息队列中的消息是可以任意读取的,可以按照类型来读取
一般形式如下:
// 创建或打开消息队列:成功返回队列ID,失败返回-1
int msgget(key_t key, int flag);
// 添加消息:成功返回0,失败返回-1
int msgsnd(int msqid, const void *ptr, size_t size, int flag);
// 读取消息:成功返回消息数据的长度,失败返回-1
int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
// 控制消息队列:成功返回0,失败返回-1
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
消息队列发送端
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};//消息队列所用结构体
int main()
{
struct msgbuf sendbuf = {111,"this is send program!!!"};//消息类型与发送内容
key_t key;
key = ftok(".",'30');//获取IPC键值
if(key<0){
printf("creat key number fail!\n");
}//
printf("%x\n",key);
int msgid = msgget(key, IPC_CREAT|0777);//创建消息队列
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
printf("%d\n",msgid);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);//发送消息
msgctl(msgid, IPC_RMID,NULL);//删除队列
return 0;
}
我们将“this is send programm!!!”
发送到消息队列中
消息队列接收端
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf readbuf;
key_t key;
key = ftok(".",'1');
int msgid = msgget(key, IPC_CREAT|0777);
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),111,0);//一样的键值和类型
printf("%s\n",readbuf.mtext);
printf("get success\n");
}
效果如下:
当同时运行两个程序时,消息就能接收
补充key值作用
进程间通信(IPC)
有两个东西可以标识一个IPC结构:标识符(ID)和键(key)。
键值(ID)
ID是IPC结构的内部名,用来确保使用同一个通讯通道(比如说这个通讯通道就是消息队列)。内部即在进程内部使用,这样的标识方法是不能支持进程间通信的。
标识符(key)
key就是IPC结构的外部名。当多个进程,针对同一个key调用get函数(msgget等),这些进程得到的ID其实是标识了同一个IPC结构。多个进程间就可以通过这个IPC结构通信。
消息队列互相发送接收
我们分为夫妻两个进程
互相发送消息
夫进程如下:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf readbuf;
struct msgbuf sendbuf = {520,"form husband:you are my wife!love you so much"};
key_t key;
key = ftok(".",30);
if(key<0){
printf("creat key number fail!\n");
}
printf("%x\n",key);
int msgid = msgget(key, IPC_CREAT|0777);
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
printf("%d\n",msgid);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),1314,0);
printf("%s\n",readbuf.mtext);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
妻进程
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf readbuf;
struct msgbuf sendbuf = {1314,"form wife:you are my husband!love you so much"};
key_t key;
key = ftok(".",30);
if(key<0){
printf("creat key number fail!\n");
}
printf("%x\n",key);
int msgid = msgget(key, IPC_CREAT|0777);
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
printf("%d\n",msgid);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),520,0);
printf("%s\n",readbuf.mtext);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
两个进程通信可以使用相同的key值但接收和发送通道的类型要不同!