(3)如果这辆车的方向和单行道的方向相反,那么这辆车会被阻塞在自己条件上的信号量上,并且设置一个标志位,表示当前有反向的车等待进入单行道。
(4)每一辆车离开单行道时必须唤醒等待的车辆。
(5)定义Arrive(),Cross(),Leave()三个函数
(6)通过mutex->down();Count=buff_ptr[*put_ptr+1];mutex->up();判断是否为第一辆车,然后如果是第一辆车要说要设定单行道的方向currentDirec=direc;mutex->down();buff_ptr[*put_ptr+4]=direc设置单行道的方向,buff_ptr[*put_ptr+1]=++count修改目前单行道上的车辆数;
(7)在每一个相应的函数里,实现相应的功能,Arrive()函数中判断车辆数,方向,修改单行道方向;在cross()函数中判断几辆车通过单行道,方向如何,从哪个方向进入单行道从哪个方向通过单行道;Leave()函数,判断车辆从哪个方向离开,并且唤醒等待的进程。
运行结果:
在第一行参数设定一共有几辆车,单行道的maxNum,通过的速度
online@online-Lenovo:
~/dxb/test6$./Transport731
5216号车从西方向等待单行道
online@online-Lenovo:
~/dxb/test6$5217号车从东方向等待单行道
downerror:
Invalidargument
5218号车从西方向等待单行道
5222号车从东方向等待单行道
downerror:
Invalidargument
5221号车从西方向等待单行道
5220号车从西方向等待单行道
5219号车从东方向等待单行道
5216号车从西方向进入单行道
downerror:
Invalidargument
5216号车从西方向通过单行道,道上车数:
1
5218号车从西方向进入单行道
5218号车从西方向通过单行道,道上车数:
2
5221号车从西方向进入单行道
5221号车从西方向通过单行道,道上车数:
3
5216号车从西方向离开单行道
5218号车从西方向离开单行道
5221号车从西方向离开单行道
结论分析与体会:
通过这次试验,我了解到了如何利用管程变量来反映进程间的死锁,饥饿。
通过设置信号量来保证每一个进程都有机会来执行,并且运用最基本的goto语句来不断的创建车辆进程,达到要求。
代码:
Transport.h:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
typedefunionsemuns{
intval;
}Sem_uns;
enumState{waiting,running};
//哲学家管程中使用的信号量
classSema{
public:
Sema(intid);
~Sema();
intdown();//信号量加1
intup();//信号量减1
private:
intsem_id;//信号量标识符
};
//哲学家管程中使用的锁
classLock{
public:
Lock(Sema*lock);
~Lock();
voidclose_lock();
voidopen_lock();
private:
Sema*sema;//锁使用的信号量
};
//哲学家管程中使用的条件变量
classCondition{
public:
Condition(Sema*sema1,Sema*sema2);
~Condition();
voidWait(Lock*conditionLock,intdirec);//过路条件不足时阻塞
voidSignal(intdirec);//唤醒相反方向阻塞车辆
private:
Sema*sema[2];//一个方向阻塞队列
//Sema*queue2;//另一方向阻塞队列
Lock*lock;//进入管程时获取的锁
};
//哲学家管程的定义
classdp{
public:
dp(intrate,intmax);
~dp();
voidArrive(intdirec);//车辆准备上单行道,direc为行车方向
voidCross(intdirec);//车辆正在单行道上
voidLeave(intdirec);//车辆通过了单行道
intgetNum();
voidaddNum();
voiddecNum();
//建立或获取ipc信号量的一组函数的原型说明
intget_ipc_id(char*proc_file,key_tkey);
intset_sem(key_tsem_key,intsem_val,intsem_flag);
//创建共享内存,放哲学家状态
char*set_shm(key_tshm_key,intshm_num,intshm_flag);
private:
intrate;//车速
intmaxCars;//最大同向车数
intnumCars;//当前正在通过的车辆数
intcurrentDirec;//当前通过的车辆的方向
Condition*con;//通过单行道的条件变量
Lock*lock;//单行道管程锁
int*buff_ptr;
int*put_ptr;
Sema*mutex;
};
Transport.cc:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
typedefunionsemuns{
intval;
}Sem_uns;
enumState{waiting,running};
//管程中使用的信号量
classSema{
public:
Sema(intid);
~Sema();
intdown();//信号量加一
intup();//信号量减一
private:
intsem_id;//信号量标识符
};
//单行道管程中使用的锁
classLock{
public:
Lock(Sema*lock);
~Lock();
voidclose_lock();
voidopen_lock();
private:
Sema*sema;//锁使用的信号量
};
//单行通道管程中使用的条件变量
classCondition{
public:
Condition(Sema*semal,Sema*sema2);
~Condition();
voidWait(Lock*conditionLock,intdirec);//过路条件不足时阻塞
voidSignal(intdirec);//唤醒相反方向阻塞的车辆
private:
Sema*sema[2];//一个方向阻塞队列
Lock*lock;//进入管程时获取的锁
};
//单行道管程的定义
classdp{
public:
dp(intrate,intmax);
~dp();
voidArrive(intdirec);//车辆准备上单行道,direc为单行方向
voidCross(intdirec);//车俩正在单行道上
voidLeave(intdirec);//车辆通过了单行道
intgetNum();
voidaddNum();
voiddecNum();
//建立或获取ipc信号量的一组函数的原型说明
intget_ipc_id(char*proc_file,key_tkey);
intset_sem(key_tsem_key,intsem_val,intsem_flag);
//创建共享内存,方单行道状态
char*set_shm(key_tshm_key,intshm_num,intshm_flag);
private:
intrate;//车速
intmaxCars;//最大同向车辆
intnumCars;//当前通过的车辆的数量
intcurrentDirec;//当前通过的车辆的方向
Condition*con;//通过单行道的条件变量
Lock*lock;//单行道管程锁
int*buff_ptr;
int*put_ptr;
Sema*mutex;
};
Sema:
:
Sema(intid){
sem_id=id;
}
Sema:
:
~Sema(){}
intSema:
:
down()
{
structsembufbuf;
buf.sem_op=-1;
buf.sem_num=0;
buf.sem_flg=SEM_UNDO;
if((semop(sem_id,&buf,1))<0)
{
perror("downerror");
exit(EXIT_FAILURE);
}
returnEXIT_SUCCESS;
}
intSema:
:
up()
{
Sem_unsarg;
structsembufbuf;
buf.sem_op=1;
buf.sem_num=0;
buf.sem_flg=SEM_UNDO;
if((semop(sem_id,&buf,1))<0){
perror("uperror");
exit(EXIT_FAILURE);
}
returnEXIT_SUCCESS;
}
Lock:
:
Lock(Sema*s)
{
sema=s;
}
Lock:
:
~Lock(){}
//上锁
voidLock:
:
close_lock()
{
sema->down();
}
//开锁
voidLock:
:
open_lock()
{
sema->up();
}
//用于单行道问题的条件变量
Condition:
:
Condition(Sema*s0,Sema*s1)
{
sema[0]=s0;
sema[1]=s1;
}
voidCondition:
:
Wait(Lock*lock,intdir)
{
lock->open_lock();
sema[dir]->down();
lock->close_lock();
}
voidCondition:
:
Signal(intdir)
{
sema[dir]->up();
}
intdp:
:
get_ipc_id(char*proc_file,key_tkey)
{
#defineBUFSZ256
FILE*pf;
inti,j;
charline[BUFSZ],colum[BUFSZ];
if((pf=fopen(proc_file,"r"))==NULL)
{
perror("procfilenotopen");
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);
returni;
}
fclose(pf);
return-1;
}
intdp:
:
set_sem(key_tsem_key,intsem_val,intsem_flg)
{
intsem_id;
Sem_unssem_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("semaphorecreateerror");
exit(EXIT_FAILURE);
}
}
//设置信号量初值
sem_arg.val=sem_val;
if(semctl(sem_id,0,SETVAL,sem_arg)<0)
{
perror("semaphoreseterror");
exit(EXIT_FAILURE);
}
returnsem_id;
}
char*dp:
:
set_shm(key_tshm_key,intshm_num,intshm_flg)
{
inti,shm_id;
char*shm_buf;
//测试由shm_key标识的内存区是否已经建立
if((shm_id=get_ipc_id("/proc/sysvipc/shm",shm_key))<0)
{
//shmget新建立一个长度为shm_num字节的共享内存
if((shm_id=shmget(shm_key,shm_num,shm_flg))<0)
{
perror("shareMemoryseterror");
exit(EXIT_FAILURE);
}
//shmat将由shm_id标识的共享内存附加给指针shm_buf
if((shm_buf=(char*)shmat(shm_id,0,0))<(char*)0)
{
perror("getshareMemoryerror");
exit(EXIT_FAILURE);
}
for(i=0;i}
//共享内存区已经建立,将由shm_id标识的共享内存附加给指针shm_buf
if((shm_buf=(char*)shmat(shm_id,0,0))<(char*)0)
{
perror("getshareMemoryerror");
exit(EXIT_FAILURE);
}
returnshm_buf;
}
//单行道行驶问题管程构造函数
dp:
:
dp(intr,intmax)
{
intipc_flg=IPC_CREAT|0644;
intshm_key=220;
intshm_num=5;
intsem_key=120;
intsem_val=0;
intshm_flg=IPC_CREAT|0644;
intsem_id;
Sema*sema;
Sema*sema1;
Sema*sema2;
rate=r;
maxCars=max;
numCars=0;
//共享内存保存当前车辆数
buff_ptr=(int*)set_shm(shm_key++,shm_num,shm_flg);
put_ptr=(int*)set_shm(shm_key,1,shm_flg);
buff_ptr[*put_ptr]=0;//车辆数
buff_ptr[*put_ptr+1]=0;//记录是否为第一辆车
buff_ptr[*put_ptr+2]=0;//当前方向超出最大车辆数
buff_ptr[*put_ptr+3]=0;//反方向车辆数
buff_ptr[*put_ptr+4]=0;//记录当前方向
//sum个中同时可以有max个在就餐,建立一个初值为max的用于锁的信号灯
if((sem_id=set_sem(sem_key++,1,ipc_flg))<0)
{
perror("Semaphorcreateerror");
exit(EXIT_FAILURE);
}
sema=newSema(sem_id);
lock=newLock(sema);
//为每一个单行道建立初值为0的用于条件变量的信号灯
if((sem_id=set_sem(sem_key++,sem_val,ipc_flg))<0)
{
perror("Semaphorcreateerror");
exit(EXIT_FAILURE);
}
sema=newSema(sem_id);
if((sem_id=set_sem(sem_key++,sem_val,ipc_flg))<0)
{
perror("Semaphorcreateerror");
exit(EXIT_FAILURE);
}
sema2=newSema(sem_id);
con=newCondition(sema1,sema2);
//共享内存互斥信号量
sem_id=set_sem(sem_key++,1,ipc_flg);
mutex=newSema(sem_id);
}
//车辆在单行道路口进行判定,是否可以进入
voiddp:
:
Arrive(intdirec)
{
intcount;
lock->close_lock();
mutex->down();
count=buff_ptr[*put_ptr+1];
mutex->up();
if(count==0)
{
currentDirec=direc;
mutex->down();
buff_ptr[*put_ptr+4]=direc;
buff_ptr[*put_ptr+1]=++count;
mutex->up();
}
stringstr;
if(direc==0)str="东";
elsestr="西";
cout<mutex->down();
currentDirec=buff_ptr[*put_ptr+4];
mutex->up();
if(currentDirec!
=direc)
{
mutex->down();
count=buff_ptr[*put_ptr+3];
buff_ptr[*put_ptr+3]=++count;
mutex->up();
con->Wait(lock,direc);
}
sleep
(1);
lock->open_lock();
}
//车辆在单行道阻塞
voiddp:
:
Cross(intdirec)
{
intcount,i;
lock->close_lock();
for(i=0;i<30;i++)
{
numCars=getNum();
if(numCars>=maxCars)
{
mutex->down();
count=buff_ptr[*put_ptr+2];
buff_ptr[*put_ptr+2]=++count;
mutex->up();
con->Wait(lock,direc);
}
}
addNum();
stringstr;
if(direc==0)str="东";
elsestr="西";
cout<sleep
(1);
numCars=getNum();
if(direc==0)str="东";
elsestr="西";
cout<"<sleep(rate);
lock->open_lock();
}
//车辆离开单行道唤醒
voiddp:
:
Leave(intdirec)
{
intcount,num;
lock->close_lock();
stringstr;
if(direc==0)str="东";
elsestr="西";
cout<decNum();
sleep
(1);
numCars=getNum();
mutex->down();
count=bu