实现AB进程对话 (消息队列加多进程实现)
代码A
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
//定义消息包类型
struct msgbuf
{
long mtype; //消息类型,必须 > 0
char mtext[128]; //消息内容
};
//回收僵尸进程
void handler(int sig)
{
while (waitpid(-1,NULL,WNOHANG) > 0); //此处WNOHANG不能填0
}
int main(int argc, char const *argv[])
{
//捕获17号信号
__sighandler_t s = signal(SIGCHLD,handler);
if(SIG_ERR == s)
{
perror("signal");
return -1;
}
//
//计算Key
key_t key = ftok("/home/ubuntu/",1);
if (key < 0)
{
perror("ftok");
return -1;
}
printf("key = %#x\n",key);
//消息队列创建
int msqid = msgget(key,IPC_CREAT|0664);
if (msqid < 0)
{
perror("msgget");
return -1;
}
printf("msqid = %d\n",msqid);
system("ipcs -q");
//创建两个进程,一个进程往消息队列中发送数据,一个进程从队列中写数据
pid_t cpid = fork();
if(cpid > 0)
{
//子进程从msgtype为51的进程中读取数据
struct msgbuf rcv;
while (1)
{
memset(&rcv,0,sizeof(rcv));
rcv.mtype = 51; //消息类型
//从消息队列中读取数据
//阻塞的方式,读取消息队列中的第一条消息
if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),51,0) < 0)
{
perror("msgrcv");
return -1;
}
printf("A==读取到的消息内容:%s\n",rcv.mtext);
if (strcasecmp(rcv.mtext,"quit")==0)
{
//父进程推出前杀死子进程
kill(cpid,9);
break;
}
}
} else if(0==cpid)
{
struct msgbuf snd;
//父进程向msgtype为50的进程中发送数据
while (1)
{
memset(&snd,0,sizeof(snd));
snd.mtype = 50; //消息类型
//从终端获取消息内容
//printf("A==清输入消息内容>>>");
fgets(snd.mtext,sizeof(snd.mtext),stdin);
snd.mtext[strlen(snd.mtext)-1] = 0;
//向消息队列中发送数据
if( msgsnd(msqid,&snd,sizeof(snd.mtext),0) < 0)
{
perror("msgsnd");
return -1;
}
if (strcasecmp(snd.mtext,"quit")==0)
{
break;
}
}
} else {
perror("fork");
return -1;
}
return 0;
}
代码B
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
//定义消息包类型
struct msgbuf
{
long mtype; //消息类型,必须 > 0
char mtext[128]; //消息内容
};
//回收僵尸进程
void handler(int sig)
{
while (waitpid(-1,NULL,WNOHANG) > 0); //此处WNOHANG不能填0
}
int main(int argc, char const *argv[])
{
//捕获17号信号
__sighandler_t s = signal(SIGCHLD,handler);
if(SIG_ERR == s)
{
perror("signal");
return -1;
}
//计算Key
key_t key = ftok("/home/ubuntu/",1);
if (key < 0)
{
perror("ftok");
return -1;
}
printf("key = %#x\n",key);
//消息队列创建
int msqid = msgget(key,IPC_CREAT|0664);
if (msqid < 0)
{
perror("msgget");
return -1;
}
printf("msqid = %d\n",msqid);
system("ipcs -q");
//创建两个进程,一个进程往消息队列中发送数据,一个进程从队列中写数据
pid_t cpid = fork();
if(cpid > 0)
{
//子进程向从msgtype为50的进程中读取数据
struct msgbuf rcv;
while (1)
{
memset(&rcv,0,sizeof(rcv));
rcv.mtype = 50; //消息类型
//从消息队列中读取数据
//阻塞的方式,读取消息队列中的第一条消息
if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),50,0) < 0)
{
perror("msgrcv");
return -1;
}
printf("B==读取到的消息内容:%s\n",rcv.mtext);
if (strcasecmp(rcv.mtext,"quit")==0)
{
kill(cpid,9);
break;
}
}
} else if(0==cpid)
{
//父进程向msgtype为51的消息队列发送数据
struct msgbuf snd;
//父进程向msgtype为50的进程中发送数据
while (1)
{
memset(&snd,0,sizeof(snd));
snd.mtype = 51; //消息类型
//从终端获取消息内容
//printf("B==清输入消息内容>>>");
fgets(snd.mtext,sizeof(snd.mtext),stdin);
snd.mtext[strlen(snd.mtext)-1] = 0;
//向消息队列中发送数据
if( msgsnd(msqid,&snd,sizeof(snd.mtext),0) < 0)
{
perror("msgsnd");
return -1;
}
if (strcasecmp(snd.mtext,"quit")==0)
{
break;
}
}
} else {
perror("fork");
return -1;
}
return 0;
}
结果为
