山東大學操作系統實驗四

一.實驗內容:

抽菸者問題。假設一個系統中有三個抽菸者進程,每個抽菸者不斷地捲菸並抽菸。抽菸者捲起並抽掉一顆煙需要有三種材料:菸草、紙和膠水。一個抽菸者有菸草,一個有紙,另一個有膠水。系統中還有兩個供應者進程,它們無限地供應所有三種材料,但每次僅輪流提供三種材料中的兩種。得到缺失的兩種材料的抽菸者在捲起並抽掉一顆煙後會發信號通知供應者,讓它繼續提供另外的兩種材料。這一過程重複進行。 請用以上介紹的IPC同步機制編程,實現該問題要求的功能。

二.實驗思路:
1.生產者要能提供三種組合的原料:菸草,紙(SP),菸草,膠水(SG),或是紙和膠水(PG),這就需要一個隨機數,來決定提供哪種組合的原料。因爲需要兩個供應者,所以要兩個生產者,兩個生產者生產的內容一樣,決定通過父子進程來實現。因爲父子進程同時向一個臨界區裏寫東西,所以加上互斥。並且生產者能發送三種信號來喚醒不同的消費者。
2.需要三個消費者分別消費不同的內容,通過父進程創建兩個子進程來實現,父進程和兩個子進程分別執行不同的內容,這個和實驗一的內容很相似。三個進程在取東西對臨界區進行修改的時候要互斥。
3.因爲開始時沒有資源,所以將喚醒消費者的三個信號的信號量初始值都設爲0,因爲生產者一次僅供應一個消費者,所以將消費者喚醒生產者的那個信號量初始值設爲1。控制互斥的兩個信號量pmtx和cmtx都設爲1。

代碼如下:

ipc.h:

#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
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;
//producer semaphore
key_t prod_key;
key_t pmtx_key;
int prod_sem;
int pmtx_sem;
//consumer semaphore
key_t c_PG_key;
key_t c_SG_key;
key_t c_SP_key;
key_t cmtx_key;
int c_PG_sem;
int c_SG_sem;
int c_SP_sem;
int cmtx_sem;
int sem_val;
int sem_flg;
int shm_flg;

ipc.c:
#include "ipc.h"
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;
}
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;
}
int set_sem(key_t sem_key,int sem_val,int sem_flg){
	int sem_id;
	Sem_uns sem_arg;
if((sem_id=get_ipc_id("/proc/sysvipc/sem",sem_key))<0)
{
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;
}
char*set_shm(key_t shm_key,int shm_num,int shm_flg)
{
int i,shm_id;
char*shm_buf;
if((shm_id=get_ipc_id("/proc/sysvipc/shm",shm_key))<0)
{
if((shm_id=shmget(shm_key,shm_num,shm_flg))<0)
{
perror("shareMemory set error");
exit(EXIT_FAILURE);
}
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;
}
if((shm_buf=(char*)shmat(shm_id,0,0))<(char*)0)
{
perror("get shareMemory error");
exit(EXIT_FAILURE);
}
return shm_buf;
}
int set_msq(key_t msq_key,int msq_flg)
{
int msq_id;
if((msq_id=get_ipc_id("/proc/sysvipc/msg",msq_key))<0){
if((msq_id=msgget(msq_key,msq_flg))<0)
{
perror("messageQueue set error");
exit(EXIT_FAILURE);
}
}
return msq_id;
}
producer.c:

#include"ipc.h"
int main(int argc,char*argv[]){
int rate;
if(argv[1]!=NULL) rate=atoi(argv[1]);
else rate=3;
buff_key=101;
buff_num=8;
pput_key=102;
pput_num=1;
shm_flg=IPC_CREAT|0644;
buff_ptr=(char*)set_shm(buff_key,buff_num,shm_flg);
pput_ptr=(int*)set_shm(pput_key,pput_num,shm_flg);
prod_key=201;
pmtx_key=202;
c_PG_key=301;
c_SP_key=302;
c_SG_key=303;
sem_flg=IPC_CREAT|0644;
sem_val=1;
prod_sem=set_sem(prod_key,sem_val,sem_flg);
sem_val=0;
c_PG_sem=set_sem(c_PG_key,sem_val,sem_flg);
c_SG_sem=set_sem(c_SG_key,sem_val,sem_flg);
c_SP_sem=set_sem(c_SP_key,sem_val,sem_flg);
sem_val=1;
pmtx_sem=set_sem(pmtx_key,sem_val,sem_flg);
int pid;
pid=fork();
if(pid==0){
while(1){
int r=rand()%3;
if(r==0){
down(prod_sem);
down(pmtx_sem);
buff_ptr[*pput_ptr+1]='P';
buff_ptr[*pput_ptr+2]='G';
sleep(rate);
printf("%d渚涘簲鍟嗘彁渚涳細綰?c,鑳舵按%c\n",getpid(),buff_ptr[*pput_ptr+1],buff_ptr[*pput_ptr]+2);
up(pmtx_sem);
up(c_PG_sem);}
else if(r==1){
down(prod_sem);
down(pmtx_sem);
buff_ptr[*pput_ptr]='S';
buff_ptr[*pput_ptr+2]='G';
sleep(rate);
printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,鑳舵按%c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+2);
up(pmtx_sem);
up(c_SG_sem);
}
else if(r==2){
down(prod_sem);
down(pmtx_sem);
buff_ptr[*pput_ptr]='S';
buff_ptr[*pput_ptr+1]='P';
sleep(rate);
printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,綰?c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+1);
up(pmtx_sem);
up(c_SP_sem);}}
}else{
while(1){
int r=rand()%3;
if(r==0){
down(prod_sem);
down(pmtx_sem);
buff_ptr[*pput_ptr+1]='P';
buff_ptr[*pput_ptr+2]='G';
sleep(rate);
printf("%d渚涘簲鍟嗘彁渚涳細綰?c,鑳舵按%c\n",getpid(),buff_ptr[*pput_ptr+1],buff_ptr[*pput_ptr]+2);
up(pmtx_sem);
up(c_PG_sem);}
else if(r==1){
down(prod_sem);
down(pmtx_sem);
buff_ptr[*pput_ptr]='S';
buff_ptr[*pput_ptr+2]='G';
sleep(rate);
printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,鑳舵按%c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+2);
up(pmtx_sem);
up(c_SG_sem);
}
else if(r==2){
down(prod_sem);
down(pmtx_sem);
buff_ptr[*pput_ptr]='S';
buff_ptr[*pput_ptr+1]='P';
sleep(rate);
printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,綰?c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+1);
up(pmtx_sem);
up(c_SP_sem);}}
}
return EXIT_SUCCESS;
}
<pre name="code" class="objc">consumer.c:
#include"ipc.h"
int main(int argc,char*argv[]){
int rate;
if(argv[1]!=NULL) rate=atoi(argv[1]);
else rate=3;
buff_key=101;
buff_num=3;
cget_key=103;
cget_num=1;
shm_flg=IPC_CREAT|0644;
buff_ptr=(char*)set_shm(buff_key,buff_num,shm_flg);
cget_ptr=(int*)set_shm(cget_key,cget_num,shm_flg);
prod_key=201;
pmtx_key=202;
c_PG_key=301;
c_SP_key=302;
c_SG_key=303;
sem_flg=IPC_CREAT|0644;
sem_val=1;
prod_sem=set_sem(prod_key,sem_val,sem_flg);
sem_val=0;
c_PG_sem=set_sem(c_PG_key,sem_val,sem_flg);
c_SG_sem=set_sem(c_SG_key,sem_val,sem_flg);
c_SP_sem=set_sem(c_SP_key,sem_val,sem_flg);
sem_val=1;
cmtx_sem=set_sem(cmtx_key,sem_val,sem_flg);
int pid1,pid2;
if((pid1=fork())==0){
while(1){
down(c_PG_sem);
down(cmtx_sem);
sleep(rate);
printf("%d鏈夌儫鑽夌殑鍚哥儫鑰呬粠渚涘簲鍟嗗緱鍒扮焊%c,鑳舵按%c寮€濮嬪惛鐑焅n",getpid(),buff_ptr[*cget_ptr+1],buff_ptr[*cget_ptr]+2);
up(cmtx_sem);
up(prod_sem);}}
else if((pid2=fork())==0){
while(1){
down(c_SG_sem);
down(cmtx_sem);
sleep(rate);
printf("%d鏈夌焊鐨勫惛鐑熻€呬粠渚涘簲鍟嗗緱鍒扮儫%c,鑳舵按%c寮€濮嬪惛鐑焅n",getpid(),buff_ptr[*cget_ptr],buff_ptr[*cget_ptr]+2);
up(cmtx_sem);
up(prod_sem);}}
else{
while(1){
down(c_SP_sem);
down(cmtx_sem);
sleep(rate);
printf("%d鏈夎兌姘寸殑鍚哥儫鑰呬粠渚涘簲鍟嗗緱鍒扮儫%c,綰?c寮€濮嬪惛鐑焅n",getpid(),buff_ptr[*cget_ptr],buff_ptr[*cget_ptr]+1);
up(cmtx_sem);
up(prod_sem);}}
return EXIT_SUCCESS;
}

在linux系統中寫的中文拿到windows系統上是亂碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章