操作系统实验三题目四

题目四

题目内容-共享内存通信

  • 编写程序 sender,它创建一个共享内存,然后随机产生一个100以内的计算表达式(例如12+34),并将这串表达式字符串通过共享内存发送给 receiver;最后,receiver完成表达式运算后,将计算结果(36)写到共享内存 ,sender收到应答消息后,将接收到的计算结果显示在终端屏幕上。上述计算重复10次后,sender向receiver发送”end”,等待receiver发送”over”信息后,删除共享内存,结束程序的运行。
  • 编写程序receiver, 它通过共享内存接收来自 sender 产生的信息,如果该信息是计算表达式,则将表达式显示在终端屏幕上,然后计算表达式的结果,再通过该共享内存向sender 发送计算结果,等待接收下一个消息;如果该信息是”end”,则向 sender 发送一个应答消息”over”,并结束程序的运行。选择合适的信号量机制实现两个进程对共享内存的互斥及同步使用。

C代码

sender.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<semaphore.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/shm.h>

void input(char* msg);

int main(){
char msg[256];//用来存放消息

int shmid=shmget(8084,256,IPC_CREAT | 0666);
// shmeget() 函数申请一块共享内存,
// 第一个参数是共享内存标识符,第二个参数是共享内存的大小,第三个参数是给予创建和读写权限
// 函数申请成功返回共享内存的ID号,失败返回-1
if(shmid <0){
printf("failed\n");
exit(0);
// 失败退出程序
}

char* shmptr=shmat(shmid,0,0);
// 将共享内存映射到该进程地址,返回起始指针

sem_t* share_memory =sem_open("shm",O_CREAT,0666,1);
// sem_open() 用来创建互斥量,
//第一个参数是该互斥量标识符,第二个参数代表若没有则创建,第三个参数赋予读写权限,第四个参数是初始值
// 创建共享内存的互斥量并赋予初始值1,代表共享内存并未被使用,0代表共享内存在被占用

sem_t* s_send=sem_open("s_send",O_CREAT,0666,0);
// 创建发送者的互斥量,用来标明谁发送了消息,0代表sender未发送消息,1代表sender发送了一条消息
sem_t* r_send=sem_open("r_send",O_CREAT,0666,0);
// 创建接收者的互斥量,0代表receiver未发送消息,1代表receiver发送了一条消息
// s_send 和 r_send 用于实现两个进程的同步

int i;
for(i=1;i<=11;i++){

if(i<11)
input(msg); //input函数用来随机生成算数表达式
else
strcpy(msg,"end\n"); //最后一条消息发送end
sem_wait(share_memory); // P操作,申请共享内存互斥量
strcpy(shmptr,msg); // 将消息拷贝到共享内存中
sem_post(share_memory); // V操作, 释放共享内存互斥量
sem_post(s_send); //V操作,释放s_send,代表sender已经发送了一条消息
printf("\nsender to receiver %s \n",msg); //打印该消息

sem_wait(r_send); // P操作,等待receiver回应
sem_wait(share_memory); // P操作,申请共享内存互斥量
strcpy(msg,shmptr); // 取出消息放到msg中
sem_post(share_memory); // V操作, 释放共享内存互斥量
printf("send has received %s\n",msg); // 打印该消息
}

shmdt(shmptr); // 将该映射地址删除
shmctl(shmid,IPC_RMID,0); // 获得共享内存的控制权,释放共享内存
sem_close(share_memory); // 关闭互斥量
sem_close(s_send); // 关闭互斥量
sem_close(r_send); // 关闭互斥量
return 0;
}

void input(char* msg){

int a=rand()%100;
int b=rand()%100;
sprintf(msg,"%d+%d\n",a,b); // 打印到msg中

}

receiver.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<semaphore.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/shm.h>


int main(){
char msg[256];
int shmid=shmget(8084,256,IPC_CREAT |0666);

if(shmid <0){
printf("failed\n");
exit(0);
}

char* shmptr=shmat(shmid,0,0);
sem_t* share_memory =sem_open("shm",O_CREAT,0666,1);
sem_t* s_send=sem_open("s_send",O_CREAT,0666,0);
sem_t* r_send=sem_open("r_send",O_CREAT,0666,0);

// 前面代码与serder.c相同不再赘述
int i;
for(i=1;i<=11;i++){

sem_wait(s_send); // P操作,等待sender发送消息
sem_wait(share_memory); // P操作,申请共享内存互斥量
strcpy(msg,shmptr); // 将消息取出,放到msg中
printf("\nreceiver has received %s\n",msg); // 打印该消息

if(i<11){
int a,b;
sscanf(msg,"%d+%d",&a,&b); // 取出两个整数a,b
sprintf(msg,"%d\n",a+b); // 计算结果,放到msg中
}
else
strcpy(msg,"over\n"); // 最后一条消息发送over

strcpy(shmptr,msg); // 发送消息到共享内存中
printf("receiver to sender %s\n",msg); // 打印该消息
sem_post(share_memory); // 释放共享内存互斥量
sem_post(r_send); // 释放r_send,表明receiver已经回应了一条消息
}
shmdt(shmptr); // 删除映射地址

return 0;
}

编译

Makefile文件

1
2
3
4
5
6
7
8
9
10
all : sender receiver
.PHONY : clean
sender : sender.o
cc -pthread -o sender sender.o
receiver : receiver.o
cc -pthread -o receiver receiver.o
clean :
rm receiver
rm sender
rm *.o

全部完成后输入命令

  • make(重新编译输入make即可)
  • ./receiver
  • ./sender(另起一个终端)

实验结果

author: YaoGuangMing 2022-HDU

转载请标明出处!