操作系统实验之一,要求"参照生产者和消费者的程序,编写猴子过桥的模拟程序,要求避免死锁和饥饿"。
L:左边有猴子过桥
R:右边有猴子过桥
#include
#include
#include
#include
#include
#include
#include
#include "shmpc.h"
/*
********************************************************************************
* Name: main
* Description: entry point
********************************************************************************
*/
//var used to shared memory
int shmid;
void *myshm;
struct myshm_st *buf;
//var used to semaphore
int Lmutex,Rmutex,concur;
struct sembuf actionC;
struct sembuf actionA;
struct sembuf actionB;
//common var
int i,n;
void processA()
{
//printf ( "Create a Producer Process Success,%d\n",getpid());
printf ( "Create a LEFT monkey passing bridge Process Success,%d\n",getpid());
//用来获取当前进程的进程识别码
//attach share memory
myshm=shmat(shmid,NULL,0);
if(myshm==(void *)-1)
{
perror("shmat");
exit(-1);
}
buf=(struct myshm_st *)myshm;
//P concur ----------------------------
// struct sembuf actionC;
actionC.sem_num=0;
actionC.sem_op=-1;
actionC.sem_flg=SEM_UNDO;
if(semop(concur,&actionC,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
//P Lmutex(A) ----------------------------
actionA.sem_num=0;
actionA.sem_op=-1;
actionA.sem_flg=SEM_UNDO;
if(semop(Lmutex,&actionA,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
buf->m_rcount++;
if(buf->m_rcount==1)
{
//P Rmutex(B) ----------------------------
actionB.sem_num=0;
actionB.sem_op=-1;
actionB.sem_flg=SEM_UNDO;
if(semop(Rmutex,&actionB,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
}
//V Lmutex(A)---------------------------------------
actionA.sem_op=1;
if(semop(Lmutex,&actionA,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
//V concur---------------------------------------
actionC.sem_op=1;
if(semop(concur,&actionC,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
for(n=0; n<10; n++)
{
if(n==0)
{
while(buf->m_buf[0]=='L')
sleep(1);
buf->m_buf[0]='L';
}
sleep(1);
bool flag=0;
for(int j=0; j<10; j++)
if(buf->m_buf[j]!='0')
flag=1;
if(flag)
{
bool ce=1;
for(int j=0; j<10; j++)
{
if( buf->m_buf[j]=='R')
ce=0;
}
if(ce==0)break;
printf("[%d/L/%d]:",getpid(),n);
for(i=0; i<10; i++)
{
if(buf->m_buf[i]!='0')
printf("|%c",buf->m_buf[i]);
else
printf("| ");
}
printf("|\n");
// if(buf->m_buf[9]!='R')
for(int j=9; j>=0; j--)
{
buf->m_buf[j+1]=buf->m_buf[j];
buf->m_buf[j]='0';
}
}
else break;
}
//P Lmutex(A) ----------------------------
// struct sembuf actionA;
actionA.sem_num=0;
actionA.sem_op=-1;
actionA.sem_flg=SEM_UNDO;
if(semop(Lmutex,&actionA,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
buf->m_rcount--;
if( buf->m_rcount==0)
{
//V Rmutex---------------------------------------
actionB.sem_op=1;
if(semop(Rmutex,&actionB,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
}
//V Lmutex(A)---------------------------------------
actionA.sem_op=1;
if(semop(Lmutex,&actionA,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
if(shmdt(myshm)==-1)
perror("shmdt");
exit(0);
}
void processB()
{
printf ( "Create a RIGHT monkey passing bridge Process Success,%d\n",getpid());
//attach share memory
myshm=shmat(shmid,NULL,0);
if(myshm==(void *)-1)
{
perror("shmat");
exit(-1);
}
buf=(struct myshm_st *)myshm;
//P concur ----------------------------
// struct sembuf actionC;
actionC.sem_num=0;
actionC.sem_op=-1;
actionC.sem_flg=SEM_UNDO;
if(semop(concur,&actionC,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
//P Rmutex(B) ----------------------------
// struct sembuf actionB;
actionB.sem_num=0;
actionB.sem_op=-1;
actionB.sem_flg=SEM_UNDO;
if(semop(Rmutex,&actionB,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
buf->m_lcount++;
// struct sembuf actionA;
if(buf->m_lcount==1)
{
//P Lmutex(A) ----------------------------
actionA.sem_num=0;
actionA.sem_op=-1;
actionA.sem_flg=SEM_UNDO;
if(semop(Lmutex,&actionA,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
}
//V Rmutex---------------------------------------
actionB.sem_op=1;
if(semop(Rmutex,&actionB,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
//V concur---------------------------------------
actionC.sem_op=1;
if(semop(concur,&actionC,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
for(n=0; n<10; n++)
{
bool sf=0;
while(sf==0)
{
sf=1;
for(int j=0; j<10; j++)
if(buf->m_buf[j]=='L')
{
sf=0;
}
if(sf==0)sleep(1);
}
if(n==0)
{
while(buf->m_buf[9]=='R')
sleep(1);
buf->m_buf[9]='R';
}
sleep(1);
bool flag=0;
for(int j=0; j<10; j++)
if(buf->m_buf[j]!='0')
flag=1;
if(flag)
{
bool ce=1;
for(int j=0; j<10; j++)
{
if( buf->m_buf[j]=='L')
ce=0;
}
if(ce==0)break;
printf("[%d/R/%d]:",getpid(),n);
for(i=0; i<10; i++)
{
if(buf->m_buf[i]!='0')
printf("|%c",buf->m_buf[i]);
else
printf("| ");
}
printf("|\n");
if(buf->m_buf[0]!='L')
for(int j=1; j<10; j++)
{
buf->m_buf[j-1]=buf->m_buf[j];
buf->m_buf[j]='0';
}
}
else break;
// buf->m_rcount--;
}
//P Rmutex(B) ----------------------------
// struct sembuf actionB;
actionB.sem_num=0;
actionB.sem_op=-1;
actionB.sem_flg=SEM_UNDO;
if(semop(Rmutex,&actionB,1)==-1)
{
perror("semop");
exit(0);
}
//-------------------------------------
buf->m_lcount--;
if(buf->m_lcount==0)
{
//V Lmutex(A)---------------------------------------
actionA.sem_op=1;
if(semop(Lmutex,&actionA,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
}
//V Rmutex---------------------------------------
actionB.sem_op=1;
if(semop(Rmutex,&actionB,1)==-1)
{
perror("semop");
exit(0);
}
//--------------------------------
if(shmdt(myshm)==-1)
perror("shmdt");
exit(0);
}
int main()
{
char t;
int ppid,cpid;
//create a shared memery
printf("Begin...\n");
shmid=shmget(MYKEY,sizeof(struct myshm_st),IPC_CREAT|0770);
//第一个参数是为共享内存段命名的,shmget()函数成功时返回一个与key相关的共享内存标识符
//第三个参数是权限标志
if( shmid==-1 )//如果调用失败,shmget调用失败返回-1
{
perror("shmget");//perror ( )用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到 标 准 设备
exit(-1);
}
//attach shared memory
myshm=shmat(shmid,NULL,0);
//第一个参数是函数返回的共享内存的标志
if(myshm==(void *)-1)
{
perror("shmat");
exit(-1);
}
//init shared memory
buf=(struct myshm_st *)myshm;
buf->m_lcount=0;
buf->m_rcount=0;
for(int i=0; i<10; i++)
buf->m_buf[i]='0';
//create a semaphore信号量
Lmutex=semget(MYKEY,1,IPC_CREAT|IPC_EXCL|0770);
Rmutex=semget(MYKEYY,1,IPC_CREAT|IPC_EXCL|0770);
concur=semget(MYKEYYY,1,IPC_CREAT|IPC_EXCL|0770);
if( Lmutex==-1 )
{
perror("semget");
exit(0);
}
if( Rmutex==-1 )
{
perror("semget");
exit(0);
}
if(concur==-1 )
{
perror("semget");
exit(0);
}
union semun init_val;
init_val.val=1;
if( semctl(Lmutex,0,SETVAL,init_val )==-1)//该函数用来直接控制信号量信息
{
perror("semctl");
exit(0);
}
if( semctl(Rmutex,0,SETVAL,init_val )==-1)//该函数用来直接控制信号量信息
{
perror("semctl");
exit(0);
}
if( semctl(concur,0,SETVAL,init_val )==-1)//该函数用来直接控制信号量信息
{
perror("semctl");
exit(0);
}
for(;;)
{
scanf("%c",&t);
char x=getchar();
switch ( t )
{
case 'L' :
//create a producer process
ppid=fork();
if( ppid==0 )
{
processA();
}
break;
case 'R':
cpid=fork();
if( cpid==0 )
{
processB();
}
break;
case 'q':
if(shmdt(myshm)==-1)
perror("shmdt");
if(shmctl(shmid,IPC_RMID,0)==-1)
perror("shmctl");
if(semctl(Lmutex,1,IPC_RMID,NULL)==-1)
perror("semctl");
if(semctl(Rmutex,1,IPC_RMID,NULL)==-1)
perror("semctl");
if(semctl(concur,1,IPC_RMID,NULL)==-1)
perror("semctl");
exit(0);
break;
}
}
return 0;
}