IPC-消息队列
父子进程之间
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>
struct msgbuf
{
long mtype;
char mdata[1024];
};
int main(void)
{
int msgid = msgget(IPC_PRIVATE, 0666|IPC_CREAT);
if(-1 == msgid)
{
perror("msgget");
exit(EXIT_FAILURE);
}
struct msgbuf msg;
memset(&msg, 0, sizeof(struct msgbuf));
if(fork() > 0)
{
msg.mtype = 1;
strcpy(msg.mdata, "Hello world");
if(-1 == msgsnd(msgid, &msg, sizeof(struct msgbuf), 0))
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
wait(NULL);
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
sleep(1);
if(-1 == msgrcv(msgid, &msg, sizeof(struct msgbuf), 1, 0)) // 在消息队列中接收类型为1的消息
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
printf("child process receive: %s\n", msg.mdata);
return 0;
}
非亲缘关系进程之间
process.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
struct msgbuf
{
long mtype;
char data[1024];
};
int main(void)
{
key_t key = ftok("process.c", 'a');
if(-1 == key)
{
perror("ftok");
exit(EXIT_FAILURE);
}
int msgid = msgget(key, 0666|IPC_CREAT);
if(-1 == msgid)
{
perror("msgget");
exit(EXIT_FAILURE);
}
struct msgbuf msg;
memset(&msg, 0, sizeof(struct msgbuf));
msg.mtype = 1;
strcpy(msg.data, "Hello world");
if(-1 == msgsnd(msgid, &msg, sizeof(struct msgbuf), 0))
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
memset(&msg, 0, sizeof(struct msgbuf));
if(-1 == msgrcv(msgid, &msg, sizeof(struct msgbuf), 2, 0))
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
printf("Receive from 2 : %s\n", msg.data);
sleep(1); // 等待process2读取消息队列,再删除消息队列
if(-1 == msgctl(msgid, IPC_RMID, NULL))
{
perror("msgctl");
exit(EXIT_FAILURE);
}
return 0;
}
process2.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
struct msgbuf
{
long mtype;
char data[1024];
};
int main(void)
{
key_t key = ftok("process.c", 'a');
if(-1 == key)
{
perror("ftok");
exit(EXIT_FAILURE);
}
int msgid = msgget(key, 0666|IPC_CREAT);
if(-1 == msgid)
{
perror("msgget");
exit(EXIT_FAILURE);
}
struct msgbuf msg;
memset(&msg, 0, sizeof(struct msgbuf));
msg.mtype = 2;
strcpy(msg.data, "How are you");
if(-1 == msgsnd(msgid, &msg, sizeof(struct msgbuf), 0))
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
memset(&msg, 0, sizeof(struct msgbuf));
if(-1 == msgrcv(msgid, &msg, sizeof(struct msgbuf), 1, 0))
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
printf("Receive from 1 : %s\n", msg.data);
return 0;
}
管道消息队列的比较
相同之处:
通过与命名管道一样,消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接收的方式来传递数据的。在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。与命名管道相比,消息队列的优势在于:
1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。
2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。
3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。