没想到第一个博客是关于操作系统的
直接上代码
#include<stdio.h>
#include<unistd.h>
#include<sys/msg.h>
#include<string.h>
struct message
{
int type;//消息类型,或者说消息编号,不计算在消息大小中
char name[20];//消息内容,可以定义多个变量
}msg1,msg2;//用来发送和接收消息的结构体变量
int mid1,mid2;//用来记录消息队列标识
int main()
{
int id=0,snd,rcv;
mid1=msgget(75,IPC_CREAT|0777);//用关键字 75 创建一个消息队列,权限为0777
mid2=msgget(80,IPC_CREAT|0777);//同上
while((id=fork())== -1);//尝试创建第一个子进程直到成功
if(id==0)//对第一个子进程的操作
{
msgget(75,IPC_CREAT|0777);//获取关键字为75的消息队列
printf("mid1=%d\n",mid1);//通过返回值判断消息队列是否创建成功
scanf("%d",&msg1.type);//输入发送消息的类型
scanf("%s",&msg1.name);//发送的消息
snd=msgsnd(mid1,&msg1,20,0);//发送消息msg1到消息队列标识为mid1的消息队列上,消息大小为20字节,忽略标志位
rcv=msgrcv(mid2,&msg1,20,msg2.type,0);//从消息队列标识为mid2上,接收消息类型为msg2.type,或者说编号为这个数值的消息到msg1这个结构中,忽略标志位
printf("rcv result form p2 %d\n",rcv);//如果结果非负证明接收成功
printf("rcv from p2 %s\n",msg1.name);//输出接收到的消息
exit(0);
}
else
{
while((id=fork())== -1);//创建第二个子进程
if(id==0)//对第二个子进程的操作
{
msgget(80,IPC_CREAT|0777);//同上
printf("mid2=%d\n",mid2);//同上
scanf("%d",&msg2.type);//同上
scanf("%s",&msg2.name);//同上
snd=msgsnd(mid2,&msg2,20,0);//同上
rcv=msgrcv(mid1,&msg2,20,msg1.type,0);//同上
printf("rcv result from p1 %d\n",rcv);//同上
printf("rcv from p1 %s\n",msg2.name);//同上
exit(0);
}
}
wait(0);//此处两个wait是为了保证在两个子进程通信完成后再删除消息队列
wait(0);
msgctl(mid1,IPC_RMID,0);//删除标识为mid1的消息队列
msgctl(mid2,IPC_RMID,0);//删除标识为mid2的消息队列
return 0;
}
注意
- 这个程序使用两个消息队列的原因是为了便于区分是否真正进行了两个进程的消息收发,以免从代码角度难以解释,并且可以避免在同一个消息队列上使用同一消息类型取到的消息是自己刚刚发送的那一个。
- 如果不使用wait和exit的组合会因为进程的无序执行而出现未知的问题,如scanf无效等等
建议
- 使用两个程序写进程通信会更加明了
- 可以使用sleep函数控制子进程的执行顺序