mmzkyl
操作系统实验三之利用Linux的共享内存通信机制实现两个进程间的通信
09/19
本文最后更新于2021年09月19日,已超过246天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
操作系统实验三之利用Linux的共享内存通信机制实现三个进程间的通信
前言
编写程序创建三个线程:sender1线程、sender2线程和receiver线程,三个线程的功能描述如下:
- sender1线程:运行函数sender1(),它创建一个消息队列,然后等待用户通过终端输入一串字符,并将这串字符通过消息队列发给receiver线程;可循环发送多个消息,直到用户输入“exit”为止,表示它不再发送消息,最后向receiver线程发送消息“end1”,并且等待receiver的应答(老师告知可以省略这步,所以代码没有体现,sender2同),等到应答消息后,将接收到的应答信息显示在终端屏幕上,结束线程的运行。
- sender2线程:运行函数sender2(),共享sender1创建的消息队列,等待用户通过终端输入一串字符,并将这串字符通过消息队列发送给receiver线程;可循环发送多个消息,直到用户输入“exit”为止,表示它不再发送消息,最后向receiver线程发送消息“end2”,并且等待receiver的应答,等到应答消息后,将接收到的应答信息显示在终端屏幕上,结束线程的运行。
- receiver线程:运行函数receive(),它通过消息队列接收来自sender1和sender2两个线程的消息,将消息显示在终端屏幕上,当收到内容为“end1”的消息时,就向sender1发送一个应答消息“over1”;当收到内容为“end2”的消息时,就向sender2发送一个应答消息“over2”;消息接受完成后删除消息队列,结束线程的运行。选择合适的信号量机制实现三个线程之间的同步和互斥。
代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<sys/msg.h>
#include<semaphore.h>
#include<sys/types.h>
#include<sys/ipc.h>
pthread_t s1,s2,r;
//定义线程
sem_t Write;
sem_t Read;
sem_t mutex_0,mutex_1,mutex_2;
//定义信号量
//mutex_0代表receive的操作权
//mutex_1代表send1操作权
//mutex_2代表send2操作权
int flag_temp;
//切换进程判断所需参数
struct msgbuf{
long mtype ;
char mtext[100];
};
void *receive(void *arg){
struct msgbuf buf;
int flag1 = 1,flag2 = 1;
for(;1;)
{
memset(&buf,0,sizeof(buf));
sem_wait(&mutex_0);
sem_wait(&Read);
//receive需要有操作权并且有Read的权利,才能够读取
int ret = msgrcv(*(int *)arg,&buf,sizeof(buf.mtext),2,0);
//接收消息
if (ret == -1){
perror("msgrcv error");
exit(1);
}
else{
printf("receive:%s\n",buf.mtext);
}
if(flag1&&!strncmp(buf.mtext,"end1",4)){
pthread_cancel(s1);
flag1--;
}
else if(flag2&&!strncmp(buf.mtext,"end2",4)){
pthread_cancel(s2);
flag2--;
}
if(flag1 == 0 && flag2 == 0){
printf("再见\n");
exit(0);
}
printf("re,请输入要切换的目标\n");
scanf("%d",&flag_temp);
if(flag_temp == 0)
{
printf("已切换到re\n");
sem_post(&mutex_0);
}
if(flag_temp == 1)
{
printf("已切换到send1\n");
sem_post(&mutex_1);
}
if(flag_temp == 2)
{
printf("已切换到send2\n");
sem_post(&mutex_2);
}
//判断通过输入来判断接下来切换到哪个进程
}
}
void *sender1(void *arg){
struct msgbuf buf;
for(int i=1;i;)
{
memset(&buf,0,sizeof(buf));
sem_wait(&mutex_1);
sem_wait(&Write);
//send1需要有操作权并且有Write的权利,才能够写入
printf("send1,请输入要发送的内容\n");
scanf("%s",buf.mtext);
buf.mtype=2;
if(!strncmp(buf.mtext,"exit",4))
{
strcpy(buf.mtext,"end1");
i=0;
}
else
{
strcat(buf.mtext,"(s1)");
}
int ret = msgsnd(*(int *)arg,&buf,sizeof(buf.mtext),0);
//发送消息
if(ret==-1)
{
perror("msgsnd error");
sem_post(&Write);
exit(1);
}
sem_post(&Read);
sem_post(&Write);
printf("send1,请输入要切换的目标\n");
scanf("%d",&flag_temp);
if(flag_temp == 0)
{
printf("已切换到re\n");
sem_post(&mutex_0);
}
if(flag_temp == 1)
{
printf("已切换到send1\n");
sem_post(&mutex_1);
}
if(flag_temp == 2)
{
printf("已切换到send2\n");
sem_post(&mutex_2);
}
}
}
void *sender2(void *arg){
struct msgbuf buf;
for(int i=1;i;)
{
memset(&buf,0,sizeof(buf));
sem_wait(&mutex_2);
sem_wait(&Write);
//send1需要有操作权并且有Write的权利,才能够写入
printf("send2,请输入要发送的内容\n");
scanf("%s",buf.mtext);
buf.mtype=2;
if(!strncmp(buf.mtext,"exit",4))
{
strcpy(buf.mtext,"end2");
i=0;
}
else
{
strcat(buf.mtext,"(s2)");
}
int ret = msgsnd(*(int *)arg,&buf,sizeof(buf.mtext),0);
if(ret == -1)
{
perror("msgsnd error");
sem_post(&Write);
exit(1);
}
sem_post(&Read);
sem_post(&Write);
printf("send2,请输入要切换的目标\n");
scanf("%d",&flag_temp);
if(flag_temp == 0)
{
printf("已切换到re\n");
sem_post(&mutex_0);
}
if(flag_temp == 1)
{
printf("已切换到send1\n");
sem_post(&mutex_1);
}
if(flag_temp == 2)
{
printf("已切换到send2\n");
sem_post(&mutex_2);
}
}
}
int main(){
int ret,msgid,x;
sem_init(&Write,0,1);
sem_init(&Read,0,0);
sem_init(&mutex_1,0,1);
sem_init(&mutex_2,0,0);
sem_init(&mutex_0,0,0);
//初始使send1具有操作权以及写权限
key_t key = 100;
//key值可随意定义
msgid=msgget(key,IPC_CREAT|0666);
if(msgid==-1)
{
perror("msgid error");
exit(1);
}
ret=pthread_create(&r,NULL,receive,(void *)&msgid);
if (ret!=0)
{
perror("receiver create error");
exit(1);
}
ret=pthread_create(&s1,NULL,sender1,(void *)&msgid);
if (ret!=0)
{
perror("sender1 create error");
exit(1);
}
ret=pthread_create(&s2,NULL,sender2,(void *)&msgid);
if (ret!=0)
{
perror("sender2 create error");
exit(1);
}
pthread_join(r,NULL);
pthread_join(s1,NULL);
pthread_join(s2,NULL);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}