消息队列与管道都是队列,读完之后就删除了,因此第二次读会阻塞,读不到东西。
不同点在于管道是顺序队列,消息队列是链式队列,因此,消息类型可以不一样。而且没有消息的时候,读进程是阻塞的,等着有消息,不像共享内存需要pause手动阻塞,还需要由信号signal唤醒。
可以用消息队列来实现两个无亲缘关系进程的同时收发,但是对于某个进程,收发数据类型要不同。在以下代码中一个类型是100一个是200,通过父子进程实现同时收发。
server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <string.h>
//消息队列为链式结构,每个数据类型可以不一样
struct msgbuf //第一个必须是long的类型
{
long type;
char voltage[124];
char ID[4];
};
int main()
{
int msgid;
int readret;
struct msgbuf sendbuf;
struct msgbuf recvbuf;
int key;
int pid;
key = ftok("./a.c",'b');
if (key < 0)
{
printf("Create key failed\n");
return -1;
}
printf("key = %x", key);
msgid = msgget(key,IPC_CREAT | 0777);
if (msgid < 0)
{
printf("Error msg\n");
}
printf("msgid: %d\n", msgid);
system("ipcs -q");
pid = fork();
if(pid > 0)//paraent write 100
{
sendbuf.type = 100;
while (1)
{
//init sendbuf
memset(sendbuf.voltage, 0, 124);
printf("please enter message\n");
fgets(sendbuf.voltage, 124, stdin);
msgsnd(msgid,(void *)&sendbuf, strlen(sendbuf.voltage), 0);
}
}
if (pid ==0) //read 200
{
while(1)
{
memset(recvbuf.voltage, 0,124);
msgrcv(msgid, (void *)&recvbuf, 124, 200, 0);
printf("read message : %s", recvbuf.voltage);
}
}
//delete message
msgctl(msgid, IPC_RMID, NULL);
system("ipcs -q");
return 0;
}
client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <string.h>
//消息队列为链式结构,每个数据类型可以不一样
struct msgbuf
{
long type;
char voltage[124];
char ID[4];
};
int main()
{
int msgid;
int readret;
struct msgbuf sendbuf;
struct msgbuf recvbuf;
int key;
int pid;
key = ftok("./a.c",'b');
if (key < 0)
{
printf("Create key failed\n");
return -1;
}
printf("key = %x", key);
msgid = msgget(key,IPC_CREAT | 0777);
if (msgid < 0)
{
printf("Error msg\n");
}
printf("msgid: %d\n", msgid);
system("ipcs -q");
pid = fork();
if(pid == 0)//child write 200
{
sendbuf.type = 200;
while (1)
{
//init sendbuf
memset(sendbuf.voltage, 0, 124);
printf("please enter message\n");
fgets(sendbuf.voltage, 124, stdin);
msgsnd(msgid,(void *)&sendbuf, strlen(sendbuf.voltage), 0);
}
}
if (pid > 0) // parant read 100
{
while(1)
{
memset(recvbuf.voltage, 0,124);
msgrcv(msgid, (void *)&recvbuf, 124, 100, 0);
printf("read message : %s", recvbuf.voltage);
}
}
//delete message
msgctl(msgid, IPC_RMID, NULL);
system("ipcs -q");
return 0;
}