65,210
社区成员
发帖
与我相关
我的任务
分享
//信号量与PV操作的一个例子,模拟借书还书操作,共4个用户,每用户最多借15本书,书库共40本书,在书库没书时,该用户处于睡眠等待状态,直到有其他用户还书,若所有用户均处于等待状态,则产生了死锁
int Semget(key_t semkey,int nsems,int semflgs);
bool P(int sid,int semnum,int n);
bool V(int sid,int semnum,int n);
void sig_usr1(int);
static int pid[4];
int main(int argc,char **argv)
{
int semid;
if((semid=Semget(4446,1,IPC_CREAT|IPC_EXCL|0666))==-1)exit(-1);
if(semctl(semid,0,SETVAL,40)==-1)perr_exit("semctl"); //书的总量
int book,sleeptime;
int borrow;
for(int i=0;i<4;i++){ //4个用户
pid[i]=fork();
if(pid[i]<0){perror("Fork");i--;}
else if(pid[i]==0){
srand(time(NULL)+i);
book=0;
while(1){
sleeptime=rand()%7;
borrow=sleeptime-3; //每次最多借还3本
if(borrow>0&&borrow+book<=15) //每人最多借15本
{
if(!P(semid,0,borrow))
continue;
book+=borrow;
cout<<"User "<<i<<" borrow "<<borrow<<" books from libary,"
<<"now it remains ";
cout<<semctl(semid,0,GETVAL,0)<<" books\n";
sleep(sleeptime);
}
else if(borrow<0&&borrow+book>=0)
{
if(!V(semid,0,-borrow))continue;
book+=borrow;
cout<<"User "<<i<<" gives "<<-borrow<<" books back to libary,"
<<"now it remains "; //由于V与GETVAL并不是原子操作,此处可能打印错误
//有可能在归还与取值之间,书被借出
cout<<semctl(semid,0,GETVAL,0)<<" books\n";
sleep(sleeptime);
}
}
return 0;
}
}
signal(SIGUSR1,sig_usr1);
while(1)usleep(1000);
return 0;
}
int Semget(key_t semkey,int nsems,int semflgs)
{
int semid;
if ((semid = semget(semkey, 0, 0)) == -1) { /* Semaphore does not exist - Create. */
if ((semid = semget(semkey,nsems,semflgs)) != -1)
return semid;
else if (errno == EEXIST) {
if((semid = semget(semkey, 0, 0)) == -1) {
perror("IPC error 1: semget"); return -1;
}
}
else {
perror("IPC error 2: semget"); return -1;
}
}
return semid;
}
void sig_usr1(int sig)
{
for(int i=0;i<4;i++)
kill(pid[i],SIGQUIT);
kill(getpid(),SIGQUIT);
}
bool Semset(int sid,int semnum,int n)
{
struct sembuf sm;
sm.sem_num=semnum;
sm.sem_op=n;
sm.sem_flg=SEM_UNDO;
if(semop(sid,&sm,1)==-1){
perror ("semop");
return false;
}
return true;
}
bool P(int sid,int semnum,int n)
{
return Semset(sid,semnum,-n);
}
bool V(int sid,int semnum,int n)
{
return Semset(sid,semnum,n);
}