吸烟者问题

###一、问题描述

抽烟者问题。假设一个系统中有三个抽烟者进程,每个抽烟者不断地卷烟并抽烟。抽烟者卷起并抽掉一颗烟需要有三种材料:烟草、纸和胶水。一个抽烟者有烟草,一个有纸,另一个有胶水。系统中还有两个供应者进程,它们无限地供应所有三种材料,但每次仅轮流提供三种材料中的两种。得到缺失的两种材料的抽烟者在卷起并抽掉一颗烟后会发信号通知供应者,让它继续提供另外的两种材料。这一过程重复进行。 请用以上介绍的 IPC 同步机制编程,实现该问题要求的功能。

二、问题分析

这个问题主要涉及到操作系统中的进程见的同步与互斥的,是一个非常经典的问题。可以看做是生产者消费者这一类。

三个抽烟者相当于三个不同的消费者,他们每次只会有一个抽烟者可以抽到烟,其余两个则需要等待。而在这里默认空间大小只有一个单元,即供应者每次放下两种材料后都会停下来等待直到有消费者使用了这两种材料,他才会继续放另两种材料。相当于说缓冲区的大小为1。为了方便起见,我们把要放的两种材料捆绑到一起,看成一个单位,分别用A、B、C表示,三个吸烟着分别用1,2,3号表示。

###三、画出大致的操作流程和关键代码

img

设置五个信号量分别为三个抽烟者对应的glue、tobacco、paper和与供应者相应的同步信号量表示缓存区为空的empty信号量。最后还有一个保证临界资源安全访问的互斥信号量mutex。

供应者: 1号抽烟者: 2号抽烟者: 3号抽烟者:

while(1) while(1) while(1) whiel(1)

{ { { {

p(empty); p(glue); p(tobacco); p(paper);

p(mutex); p(mutex); p(mutex); p(mutex);

供应材料。 抽烟 抽烟 抽烟

v(mutex) v(mutex); v(mutex); v(mutex);

if(材料为A) v(empty); v(empty); v(empty);

v(glue) } } }

if(材料为B)

v(tobacco)

if(材料为C)

v(paper)

}

信号量的初始值:

empty=1;mutex=1;glue=0;paper=0;tobacco=0;

四、具体代码

ipc.h:

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
/*
* Filename
: ipc.h
* copyright
: (C) 2006 by zhonghonglie
* Function
: 澹版槑 IPC 鏈哄埗鐨勫嚱鏁板師鍨嬪拰鍏ㄥ眬鍙橀噺
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#define BUFSZ 256
//寤虹珛鎴栬幏鍙?ipc 鐨勪竴缁勫嚱鏁扮殑鍘熷瀷璇存槑
int get_ipc_id(char *proc_file,key_t key);
char *set_shm(key_t shm_key,int shm_num,int shm_flag);
int set_msq(key_t msq_key,int msq_flag);
int set_sem(key_t sem_key,int sem_val,int sem_flag);
int down(int sem_id);
int up(int sem_id);
/*淇″彿鐏帶鍒剁敤鐨勫叡鍚屼綋*/
typedef union semuns {
int val;
} Sem_uns;
/* 娑堟伅缁撴瀯浣?/
typedef struct msgbuf {
long mtype;
char mtext[1];
} Msg_buf;
//鐢熶骇娑堣垂鑰呭叡浜紦鍐插尯鍗冲叾鏈夊叧鐨勫彉閲?
key_t buff_key;
int buff_num;
char *buff_ptr;
//鐢熶骇鑰呮斁浜у搧浣嶇疆鐨勫叡浜寚閽?
key_t pput_key;
int pput_num;
int *pput_ptr;
//娑堣垂鑰呭彇浜у搧浣嶇疆鐨勫叡浜寚閽?
key_t cget_key;
int cget_num;
int *cget_ptr;
//鐢熶骇鑰呮湁鍏崇殑淇″彿閲?
key_t tobacco_key;
key_t glue_key;
key_t paper_key;
int tobacco_sem;
int glue_sem;
int paper_sem;
//娑堣垂鑰呮湁鍏崇殑淇″彿閲?
key_t empty_key;
key_t mutex_key;
int empty_sem;
int mutex_sem;
int sem_val;
int sem_flg;
int shm_flg;

ipc.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
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
绗?41 椤靛疄楠屽洓銆佽繘绋嬪悓姝ュ疄楠?
* Filename
* copyright
* Function
: ipc.c
: (C) 2006 by zhonghonglie
: 涓€缁勫缓绔?IPC 鏈哄埗鐨勫嚱鏁?
*/
#include "ipc.h"
/*
* get_ipc_id() 浠?proc/sysvipc/鏂囦欢绯荤粺涓幏鍙?IPC 鐨?id 鍙?
* pfile: 瀵瑰簲/proc/sysvipc/鐩綍涓殑 IPC 鏂囦欢鍒嗗埆涓?
*
msg-娑堟伅闃熷垪,sem-淇″彿閲?shm-鍏变韩鍐呭瓨
* key: 瀵瑰簲瑕佽幏鍙栫殑 IPC 鐨?id 鍙风殑閿€?
*/
int get_ipc_id(char *proc_file,key_t key)
{
FILE *pf;
int i,j;
char line[BUFSZ],colum[BUFSZ];
if((pf = fopen(proc_file,"r")) == NULL){
perror("Proc file not open");
exit(EXIT_FAILURE);
}
fgets(line, BUFSZ,pf);
while(!feof(pf)){
i = j = 0;
fgets(line, BUFSZ,pf);
while(line[i] == ' ') i++;
while(line[i] !=' ') colum[j++] = line[i++];
colum[j] = '\0';
if(atoi(colum) != key) continue;
j=0;
while(line[i] == ' ') i++;
while(line[i] !=' ') colum[j++] = line[i++];
colum[j] = '\0';
i = atoi(colum);
fclose(pf);
return i;
}
fclose(pf);
return -1;
}
/*
* 淇″彿鐏笂鐨?down/up 鎿嶄綔
* semid:淇″彿鐏暟缁勬爣璇嗙
* semnum:淇″彿鐏暟缁勪笅鏍?
* buf:鎿嶄綔淇″彿鐏殑缁撴瀯
*/
int down(int sem_id)
{
struct sembuf buf;
buf.sem_op = -1;
buf.sem_num = 0;
buf.sem_flg = SEM_UNDO;
if((semop(sem_id,&buf,1)) <0) {
perror("down error ");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
int up(int sem_id)
{
struct sembuf buf;
buf.sem_op = 1;
buf.sem_num = 0;
buf.sem_flg = SEM_UNDO;
if((semop(sem_id,&buf,1)) <0) {
perror("up error ");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
/*
* set_sem 鍑芥暟寤虹珛涓€涓叿鏈?n 涓俊鍙风伅鐨勪俊鍙烽噺
*
濡傛灉寤虹珛鎴愬姛,杩斿洖 涓€涓俊鍙风伅鏁扮粍鐨勬爣璇嗙 sem_id
*
杈撳叆鍙傛暟:
* sem_key 淇″彿鐏暟缁勭殑閿€?
* sem_val 淇″彿鐏暟缁勪腑淇″彿鐏殑涓暟
* sem_flag 淇″彿绛夋暟缁勭殑瀛樺彇鏉冮檺
*/
int set_sem(key_t sem_key,int sem_val,int sem_flg)
{
int sem_id;
Sem_uns sem_arg;
//娴嬭瘯鐢?sem_key 鏍囪瘑鐨勪俊鍙风伅鏁扮粍鏄惁宸茬粡寤虹珛
if((sem_id = get_ipc_id("/proc/sysvipc/sem",sem_key)) < 0 )
{
//semget 鏂板缓涓€涓俊鍙风伅,鍏舵爣鍙疯繑鍥炲埌 sem_id
if((sem_id = semget(sem_key,1,sem_flg)) < 0)
{
perror("semaphore create error");
exit(EXIT_FAILURE);
}
//璁剧疆淇″彿鐏殑鍒濆€?
sem_arg.val = sem_val;
if(semctl(sem_id,0,SETVAL,sem_arg) <0)
{
perror("semaphore set error");
exit(EXIT_FAILURE);
}
}
return sem_id;
}
/*
* set_shm 鍑芥暟寤虹珛涓€涓叿鏈?n 涓瓧鑺?鐨勫叡浜唴瀛樺尯
*
濡傛灉寤虹珛鎴愬姛,杩斿洖 涓€涓寚鍚戣鍐呭瓨鍖洪鍦板潃鐨勬寚閽?shm_buf
*
杈撳叆鍙傛暟:
* shm_key 鍏变韩鍐呭瓨鐨勯敭鍊?
* shm_val 鍏变韩鍐呭瓨瀛楄妭鐨勯暱搴?
* shm_flag 鍏变韩鍐呭瓨鐨勫瓨鍙栨潈闄?
*/
char * set_shm(key_t shm_key,int shm_num,int shm_flg)
{
int i,shm_id;
char * shm_buf;
//娴嬭瘯鐢?shm_key 鏍囪瘑鐨勫叡浜唴瀛樺尯鏄惁宸茬粡寤虹珛
if((shm_id = get_ipc_id("/proc/sysvipc/shm",shm_key)) < 0 )
{
//shmget 鏂板缓 涓€涓暱搴︿负 shm_num 瀛楄妭鐨勫叡浜唴瀛?鍏舵爣鍙疯繑鍥炲埌 shm_id
if((shm_id = shmget(shm_key,shm_num,shm_flg)) <0)
{
perror("shareMemory set error");
exit(EXIT_FAILURE);
}
//shmat 灏嗙敱 shm_id 鏍囪瘑鐨勫叡浜唴瀛橀檮鍔犵粰鎸囬拡 shm_buf
if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0)
{
perror("get shareMemory error");
exit(EXIT_FAILURE);
}
for(i=0; i<shm_num; i++) shm_buf[i] = 0; //鍒濆涓?0
}
//shm_key 鏍囪瘑鐨勫叡浜唴瀛樺尯宸茬粡寤虹珛,灏嗙敱 shm_id 鏍囪瘑鐨勫叡浜唴瀛橀檮鍔犵粰鎸囬拡 shm_buf
if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0)
{
perror("get shareMemory error");
exit(EXIT_FAILURE);
}
return shm_buf;
}
/*
* set_msq 鍑芥暟寤虹珛涓€涓秷鎭槦鍒?
* 濡傛灉寤虹珛鎴愬姛,杩斿洖 涓€涓秷鎭槦鍒楃殑鏍囪瘑绗?msq_id
* 杈撳叆鍙傛暟:
* msq_key 娑堟伅闃熷垪鐨勯敭鍊?
* msq_flag 娑堟伅闃熷垪鐨勫瓨鍙栨潈闄?
*/
int set_msq(key_t msq_key,int msq_flg)
{
int msq_id;
//娴嬭瘯鐢?msq_key 鏍囪瘑鐨勬秷鎭槦鍒楁槸鍚﹀凡缁忓缓绔?
if((msq_id = get_ipc_id("/proc/sysvipc/msg",msq_key)) < 0 )
{
//msgget 鏂板缓涓€涓秷鎭槦鍒?鍏舵爣鍙疯繑鍥炲埌 msq_id
if((msq_id = msgget(msq_key,msq_flg)) < 0)
{
perror("messageQueue set error");
exit(EXIT_FAILURE);
}
}
return msq_id;
}

供应者:

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
/*
* Filename
: producer.c
* copyright
: (C) 2006 by zhonghonglie
* Function
: 寤虹珛骞舵ā鎷熺敓浜ц€呰繘绋?
*/
#include "ipc.h"
int main(int argc,char *argv[])
{
int rate;
//鍙湪鍦ㄥ懡浠よ绗竴鍙傛暟鎸囧畾涓€涓繘绋嬬潯鐪犵鏁?浠ヨ皟瑙h繘绋嬫墽琛岄€熷害
if(argv[1] != NULL) rate = atoi(argv[1]);
else rate = 3; //涓嶆寚瀹氫负 3 绉?
//鍏变韩鍐呭瓨浣跨敤鐨勫彉閲?
buff_key = 101;//缂撳啿鍖轰换缁欑殑閿€?
buff_num = 1;//缂撳啿鍖轰换缁欑殑闀垮害
pput_key = 102;//鐢熶骇鑰呮斁浜у搧鎸囬拡鐨勯敭鍊?
pput_num = 1; //鎸囬拡鏁?
shm_flg = IPC_CREAT | 0644;//鍏变韩鍐呭瓨璇诲啓鏉冮檺
//鑾峰彇缂撳啿鍖轰娇鐢ㄧ殑鍏变韩鍐呭瓨,buff_ptr 鎸囧悜缂撳啿鍖洪鍦板潃
buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg);
//鑾峰彇鐢熶骇鑰呮斁浜у搧浣嶇疆鎸囬拡 pput_ptr
pput_ptr = (int *)set_shm(pput_key,pput_num,shm_flg);
//淇″彿閲忎娇鐢ㄧ殑鍙橀噺
tobacco_key = 201; //鐢熶骇鑰呭悓姝ヤ俊鍙风伅閿€?
glue_key = 202; //鐢熶骇鑰呬簰鏂ヤ俊鍙风伅閿€?
paper_key=203; //鐢熶骇鑰?鐨勫悓姝ヤ俊鍙风伅閿€?
empty_key = 301; //娑堣垂鑰呭悓姝ヤ俊鍙风伅閿€?
mutex_key = 302; //娑堣垂鑰呬簰鏂ヤ俊鍙风伅閿€?
sem_flg = IPC_CREAT | 0644;
//鐢熶骇鑰呭悓姝ヤ俊鍙风伅鍒濆€艰涓虹紦鍐插尯鏈€澶у彲鐢ㄩ噺
sem_val = buff_num;
//鑾峰彇鐢熶骇鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?prod_sem
empty_sem = set_sem(empty_key,sem_val,sem_flg);
//娑堣垂鑰呭垵濮嬫棤浜у搧鍙彇,鍚屾淇″彿鐏垵鍊艰涓?0
sem_val = 0;
//鑾峰彇娑堣垂鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?cons_sem
paper_sem = set_sem(paper_key,sem_val,sem_flg);
glue_sem = set_sem(glue_key,sem_val,sem_flg);
tobacco_sem = set_sem(tobacco_key,sem_val,sem_flg);
//鐢熶骇鑰呬簰鏂ヤ俊鍙风伅鍒濆€间负 1
sem_val = 1;
//鑾峰彇鐢熶骇鑰呬簰鏂ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?pmtx_sem
mutex_sem = set_sem(mutex_key,sem_val,sem_flg);
int i=0;
//寰幆鎵ц妯℃嫙鐢熶骇鑰呬笉鏂斁浜у搧
while(1){
int d;
//濡傛灉缂撳啿鍖烘弧鍒欑敓浜ц€呴樆濉?
down(empty_sem);
//濡傛灉鍙︿竴鐢熶骇鑰呮鍦ㄦ斁浜у搧,鏈敓浜ц€呴樆濉?
down(mutex_sem);
//鐢ㄥ啓涓€瀛楃鐨勫舰寮忔ā鎷熺敓浜ц€呮斁浜у搧,鎶ュ憡鏈繘绋嬪彿鍜屾斁鍏ョ殑瀛楃鍙婂瓨鏀剧殑浣嶇疆
sleep(rate);
d=(i++)%3;
buff_ptr[*pput_ptr] = 'A'+ d;
printf("%d provider put: %c to Buffer[%d]\n",getpid(),buff_ptr[*pput_ptr],*pput_ptr);
//瀛樻斁浣嶇疆寰幆涓嬬Щ
*pput_ptr = (*pput_ptr+1) % buff_num;
//鍞ら啋闃诲鐨勭敓浜ц€?
up(mutex_sem);
//鍞ら啋闃诲鐨勬秷璐硅€?
if(d==0)
up(paper_sem);
if(d==1)
up(glue_sem);
if(d==2)
up(tobacco_sem);
}
return EXIT_SUCCESS;
}

三个抽烟者:

glue.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
/*
Filename
: consumer.c
copyright
: (C) by zhanghonglie
Function
: 寤虹珛骞舵ā鎷熸秷璐硅€呰繘绋?
*/
#include "ipc.h"
int main(int argc,char *argv[])
{
int rate;
//鍙湪鍦ㄥ懡浠よ绗竴鍙傛暟鎸囧畾涓€涓繘绋嬬潯鐪犵鏁?浠ヨ皟瑙h繘绋嬫墽琛岄€熷害
if(argv[1] != NULL) rate = atoi(argv[1]);
else rate = 3; //涓嶆寚瀹氫负 3 绉?
//鍏变韩鍐呭瓨 浣跨敤鐨勫彉閲?
buff_key = 101; //缂撳啿鍖轰换缁欑殑閿€?
buff_num = 1; //缂撳啿鍖轰换缁欑殑闀垮害
cget_key = 103; //娑堣垂鑰呭彇浜у搧鎸囬拡鐨勯敭鍊?
cget_num = 1; //鎸囬拡鏁?
shm_flg = IPC_CREAT | 0644; //鍏变韩鍐呭瓨璇诲啓鏉冮檺
//鑾峰彇缂撳啿鍖轰娇鐢ㄧ殑鍏变韩鍐呭瓨,buff_ptr 鎸囧悜缂撳啿鍖洪鍦板潃
buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg);
//鑾峰彇娑堣垂鑰呭彇浜у搧鎸囬拡,cget_ptr 鎸囧悜绱㈠紩鍦板潃
cget_ptr = (int *)set_shm(cget_key,cget_num,shm_flg);
//淇″彿閲忎娇鐢ㄧ殑鍙橀噺
tobacco_key = 201; //鐢熶骇鑰呭悓姝ヤ俊鍙风伅閿€?
glue_key = 202; //鐢熶骇鑰呬簰鏂ヤ俊鍙风伅閿€?
paper_key=203; //鐢熶骇鑰?鐨勫悓姝ヤ俊鍙风伅閿€?
empty_key = 301; //娑堣垂鑰呭悓姝ヤ俊鍙风伅閿€?
mutex_key = 302; //娑堣垂鑰呬簰鏂ヤ俊鍙风伅閿€?
sem_flg = IPC_CREAT | 0644; //淇″彿鐏搷浣滄潈闄?
//鐢熶骇鑰呭悓姝ヤ俊鍙风伅鍒濆€艰涓虹紦鍐插尯鏈€澶у彲鐢ㄩ噺
sem_val = buff_num;
//鑾峰彇鐢熶骇鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?prod_sem
empty_sem = set_sem(empty_key,sem_val,sem_flg);
//娑堣垂鑰呭垵濮嬫棤浜у搧鍙彇,鍚屾淇″彿鐏垵鍊艰涓?0
sem_val = 0;
//鑾峰彇娑堣垂鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?cons_sem
glue_sem = set_sem(glue_key,sem_val,sem_flg);
sem_val = 1;
//鑾峰彇鐢熶骇鑰呬簰鏂ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?pmtx_sem
mutex_sem = set_sem(mutex_key,sem_val,sem_flg);
while(1){
//濡傛灉鏃犱骇鍝佹秷璐硅€呴樆濉?
down(glue_sem);
down(mutex_sem);
//鐢ㄨ涓€瀛楃鐨勫舰寮忔ā鎷熸秷璐硅€呭彇浜у搧,鎶ュ憡鏈繘绋嬪彿鍜?
sleep(rate);
printf("%d 1鍙峰惛鐑熻€?寰楀埌浜? %c鐑熻崏鍜岀焊 from Buffer[%d]\n",getpid(),buff_ptr[*cget_ptr],*cget_ptr);
//璇诲彇浣嶇疆寰幆涓嬬Щ
*cget_ptr = (*cget_ptr+1) % buff_num;
up(mutex_sem);
//鍞ら啋闃诲鐨勭敓浜ц€?
up(empty_sem);
}
return EXIT_SUCCESS;
}

tobacco.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
/*
Filename
: consumer.c
copyright
: (C) by zhanghonglie
Function
: 寤虹珛骞舵ā鎷熸秷璐硅€呰繘绋?
*/
#include "ipc.h"
int main(int argc,char *argv[])
{
int rate;
//鍙湪鍦ㄥ懡浠よ绗竴鍙傛暟鎸囧畾涓€涓繘绋嬬潯鐪犵鏁?浠ヨ皟瑙h繘绋嬫墽琛岄€熷害
if(argv[1] != NULL) rate = atoi(argv[1]);
else rate = 3; //涓嶆寚瀹氫负 3 绉?
//鍏变韩鍐呭瓨 浣跨敤鐨勫彉閲?
buff_key = 101; //缂撳啿鍖轰换缁欑殑閿€?
buff_num = 1; //缂撳啿鍖轰换缁欑殑闀垮害
cget_key = 103; //娑堣垂鑰呭彇浜у搧鎸囬拡鐨勯敭鍊?
cget_num = 1; //鎸囬拡鏁?
shm_flg = IPC_CREAT | 0644; //鍏变韩鍐呭瓨璇诲啓鏉冮檺
//鑾峰彇缂撳啿鍖轰娇鐢ㄧ殑鍏变韩鍐呭瓨,buff_ptr 鎸囧悜缂撳啿鍖洪鍦板潃
buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg);
//鑾峰彇娑堣垂鑰呭彇浜у搧鎸囬拡,cget_ptr 鎸囧悜绱㈠紩鍦板潃
cget_ptr = (int *)set_shm(cget_key,cget_num,shm_flg);
//淇″彿閲忎娇鐢ㄧ殑鍙橀噺
tobacco_key = 201; //鐢熶骇鑰呭悓姝ヤ俊鍙风伅閿€?
glue_key = 202; //鐢熶骇鑰呬簰鏂ヤ俊鍙风伅閿€?
paper_key=203; //鐢熶骇鑰?鐨勫悓姝ヤ俊鍙风伅閿€?
empty_key = 301; //娑堣垂鑰呭悓姝ヤ俊鍙风伅閿€?
mutex_key = 302; //娑堣垂鑰呬簰鏂ヤ俊鍙风伅閿€?
sem_flg = IPC_CREAT | 0644; //淇″彿鐏搷浣滄潈闄?
//鐢熶骇鑰呭悓姝ヤ俊鍙风伅鍒濆€艰涓虹紦鍐插尯鏈€澶у彲鐢ㄩ噺
sem_val = buff_num;
//鑾峰彇鐢熶骇鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?prod_sem
empty_sem = set_sem(empty_key,sem_val,sem_flg);
//娑堣垂鑰呭垵濮嬫棤浜у搧鍙彇,鍚屾淇″彿鐏垵鍊艰涓?0
sem_val = 0;
//鑾峰彇娑堣垂鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?cons_sem
tobacco_sem = set_sem(tobacco_key,sem_val,sem_flg);
sem_val = 1;
//鑾峰彇鐢熶骇鑰呬簰鏂ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?pmtx_sem
mutex_sem = set_sem(mutex_key,sem_val,sem_flg);
while(1){
//濡傛灉鏃犱骇鍝佹秷璐硅€呴樆濉?
down(tobacco_sem);
down(mutex_sem);
//鐢ㄨ涓€瀛楃鐨勫舰寮忔ā鎷熸秷璐硅€呭彇浜у搧,鎶ュ憡鏈繘绋嬪彿鍜?
sleep(rate);
printf("%d 2鍙峰惛鐑熻€?寰楀埌浜? %c鑳舵按鍜岀焊 from Buffer[%d]\n",getpid(),buff_ptr[*cget_ptr],*cget_ptr);
//璇诲彇浣嶇疆寰幆涓嬬Щ
*cget_ptr = (*cget_ptr+1) % buff_num;
//鍞ら啋闃诲鐨勭敓浜ц€?
up(mutex_sem);
up(empty_sem);
}
return EXIT_SUCCESS;
}

paper.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
/*
Filename
: consumer.c
copyright
: (C) by zhanghonglie
Function
: 寤虹珛骞舵ā鎷熸秷璐硅€呰繘绋?
*/
#include "ipc.h"
int main(int argc,char *argv[])
{
int rate;
//鍙湪鍦ㄥ懡浠よ绗竴鍙傛暟鎸囧畾涓€涓繘绋嬬潯鐪犵鏁?浠ヨ皟瑙h繘绋嬫墽琛岄€熷害
if(argv[1] != NULL) rate = atoi(argv[1]);
else rate = 3; //涓嶆寚瀹氫负 3 绉?
//鍏变韩鍐呭瓨 浣跨敤鐨勫彉閲?
buff_key = 101; //缂撳啿鍖轰换缁欑殑閿€?
buff_num = 1; //缂撳啿鍖轰换缁欑殑闀垮害
cget_key = 103; //娑堣垂鑰呭彇浜у搧鎸囬拡鐨勯敭鍊?
cget_num = 1; //鎸囬拡鏁?
shm_flg = IPC_CREAT | 0644; //鍏变韩鍐呭瓨璇诲啓鏉冮檺
//鑾峰彇缂撳啿鍖轰娇鐢ㄧ殑鍏变韩鍐呭瓨,buff_ptr 鎸囧悜缂撳啿鍖洪鍦板潃
buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg);
//鑾峰彇娑堣垂鑰呭彇浜у搧鎸囬拡,cget_ptr 鎸囧悜绱㈠紩鍦板潃
cget_ptr = (int *)set_shm(cget_key,cget_num,shm_flg);
//淇″彿閲忎娇鐢ㄧ殑鍙橀噺
tobacco_key = 201; //鐢熶骇鑰呭悓姝ヤ俊鍙风伅閿€?
glue_key = 202; //鐢熶骇鑰呬簰鏂ヤ俊鍙风伅閿€?
paper_key=203; //鐢熶骇鑰?鐨勫悓姝ヤ俊鍙风伅閿€?
empty_key = 301; //娑堣垂鑰呭悓姝ヤ俊鍙风伅閿€?
mutex_key = 302; //娑堣垂鑰呬簰鏂ヤ俊鍙风伅閿€?
sem_flg = IPC_CREAT | 0644; //淇″彿鐏搷浣滄潈闄?
//鐢熶骇鑰呭悓姝ヤ俊鍙风伅鍒濆€艰涓虹紦鍐插尯鏈€澶у彲鐢ㄩ噺
sem_val = buff_num;
//鑾峰彇鐢熶骇鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?prod_sem
empty_sem = set_sem(empty_key,sem_val,sem_flg);
//娑堣垂鑰呭垵濮嬫棤浜у搧鍙彇,鍚屾淇″彿鐏垵鍊艰涓?0
sem_val = 0;
//鑾峰彇娑堣垂鑰呭悓姝ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?cons_sem
paper_sem = set_sem(paper_key,sem_val,sem_flg);
sem_val = 1;
//鑾峰彇鐢熶骇鑰呬簰鏂ヤ俊鍙风伅,寮曠敤鏍囪瘑瀛?pmtx_sem
mutex_sem = set_sem(mutex_key,sem_val,sem_flg);
while(1){
//濡傛灉鏃犱骇鍝佹秷璐硅€呴樆濉?
down(paper_sem);
//鐢ㄨ涓€瀛楃鐨勫舰寮忔ā鎷熸秷璐硅€呭彇浜у搧,鎶ュ憡鏈繘绋嬪彿鍜?
down(mutex_sem);
sleep(rate);
printf("%d 0鍙峰惛鐑熻€?寰楀埌浜? %c鐑熻崏鍜岃兌姘?from Buffer[%d]\n",getpid(),buff_ptr[*cget_ptr],*cget_ptr);
//璇诲彇浣嶇疆寰幆涓嬬Щ
*cget_ptr = (*cget_ptr+1) % buff_num;
up(mutex_sem);
//鍞ら啋闃诲鐨勭敓浜ц€?
up(empty_sem);
}
return EXIT_SUCCESS;
}

makefile:

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
hdrs = ipc.h
opts = -g -c
c_src = glue.c ipc.c
c_obj = glue.o ipc.o
d_src = paper.c ipc.c
d_obj = paper.o ipc.o
e_src = tobacco.c ipc.c
e_obj = tobacco.o ipc.o
f_src = provider.c ipc.c
f_obj = provider.o ipc.o
all: glue paper tobacco provider
glue: $(c_obj)
gcc $(c_obj) -o glue
glue.o: $(c_src) $(hdrs)
gcc $(opts) $(c_src)
paper: $(d_obj)
gcc $(d_obj) -o paper
paper.o: $(p_src) $(hdrs)
gcc $(opts) $(d_src)
tobacco: $(e_obj)
gcc $(e_obj) -o tobacco
tobacco.o: $(e_src) $(hdrs)
gcc $(opts) $(e_src)
provider: $(f_obj)
gcc $(f_obj) -o provider
provider.o: $(f_src) $(hdrs)
gcc $(opts) $(f_src)
clean:
rm glue provider paper tobaco *.o