实验六 信号量实现进程同步

信号量实现进程同步

【实验目的】

进程同步是操作系统多进程/多线程并发执行的关键之一,进程 同步是并发进程为了完成共同任务采用某个条件来协调他们的活 动,这是进程之间发生的一种直接制约关系。本次试验是利用信号量进行进程同步。

【实验软硬件环境】

Linux,gcc

【实验内容】

生产者进程生产产品,消费者进程消费产品。当生产者进程生产产品时,如果没有空缓冲区可用,那么生产者进程必须等待消费者进程释放出一个缓冲区。当消费者进程消费产品时,如果缓冲区中没有产品,那么消费 者进程将被阻塞,直到新的产品被生产出来。

【实验程序及分析】
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#define MAXSEM 5
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int fullid, emptyid,mutxid; //f 已有产品量 e 空余量
int main(){
struct sembuf P,V;
union semun arg;
//声明共享主存array, sum, get, set
int *array;
int *sum;
int *get;
int *set;
//将array,sum,set,get映射到共享主存
array =(int *)mmap(NULL,sizeof(int)*MAXSEM,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
sum=(int *)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
set=(int *)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
get=(int *)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
//创建信号量fullid, emptyid,mutxid
fullid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);
emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);
mutxid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);
//初始化信号量
arg.val=0;
if(semctl(fullid,0,SETVAL,arg)==-1)perror("semctl setval error");
arg.val=MAXSEM;
if(semctl(emptyid,0,SETVAL,arg)==-1)perror("semctl setval error");
arg.val=1;
if(semctl(mutxid,0,SETVAL,arg)==-1)perror("semctl setval error");
//初始化P,V操作
V.sem_num=0;
V.sem_op=1;
V.sem_flg=SEM_UNDO;
P.sem_num=0;
P.sem_op=-1;
P.sem_flg=SEM_UNDO;
//创建生产者进程
pid_t fpid1=fork();
if(fpid1==0){
int i=0;
while(i<100){
//对emptyid ,mutxid执行P操作
semop(emptyid,&P,1);
semop(mutxid,&P,1);
array[*(set)%MAXSEM] = i+1; //生产产品
(*set)++;
printf("produce %d\n",i+1);
//对emptyid, mutxid执行V操作
semop(mutxid,&V,1);
semop(fullid,&V,1);
i++;
}
//休眠一段时间
sleep(1);
//打印生产者结束
printf("producer is over\n");
exit(0);
}else{
//创建消费者进程
pid_t fpid2=fork();
if(fpid2==0){
//消费者进程A
while(1){
//对fuild, mutxid执行P操作
semop(fullid,&P,1);
semop(mutxid,&P,1);
if(*get == 100)
break;
*sum += array[(*get)%MAXSEM];
printf("the comsumer A get number %d\n", array[(*get)%MAXSEM]);
(*get) ++;
if(*get == 100)
{printf("the sum is %d\n", *sum);
break;
}
//对emptyid, mutxid执行V操作
semop(mutxid,&V,1);
semop(emptyid,&V,1);
sleep(0.5);
}
printf("consumer A is over\n");
exit(0);
}else{
//消费者进程B
while(1){
//对fuild, mutxid执行P操作
semop(fullid,&P,1);
semop(mutxid,&P,1);
if(*get == 100)
break;
*sum += array[(*get)%MAXSEM];
printf("the comsumer B get number %d\n", array[(*get)%MAXSEM]);
(*get) ++;
if(*get == 100)
{printf("the sum is %d\n", *sum);
break;
}
//对emptyid, mutxid执行V操作
semop(mutxid,&V,1);
semop(emptyid,&V,1);
sleep(0.5);
}
printf("consumer B is over\n");
exit(0);
}

}

}

【程序分析】:

本次实验创建了一个生产者进程和两个消费者进程,主要是通过共享内存机制通过进行PV操作完成,设置了信号量fullid, emptyid,mutxid来实现对生产者,消费者的操作。生产者总共需要生产100个产品,消费者取出产品并进行输出产品编号。