理发师问题的实现说明书.docx
《理发师问题的实现说明书.docx》由会员分享,可在线阅读,更多相关《理发师问题的实现说明书.docx(17页珍藏版)》请在冰豆网上搜索。
![理发师问题的实现说明书.docx](https://file1.bdocx.com/fileroot1/2023-4/24/89f6ab56-f2a2-4b03-905b-f037c4b84147/89f6ab56-f2a2-4b03-905b-f037c4b841471.gif)
理发师问题的实现说明书
*******************
实践教学
*******************
兰州理工大学
计算机与通信学院
2012年秋季学期
操作系统原理课程设计
题目:
理发师问题的实现
专业班级:
计算机科学与技术4班
姓名:
曹文波
学号:
10240406
指导教师:
王燕
成绩:
目录
目录··························································2
摘要··························································3
关键字··························································3
设计思想··························································4
正文··························································4
一、数据结构····················································5
1、信号量··················································5
2、全局变量················································5
3、函数····················································5
二、程序模块····················································6
1、理发师模块流程图········································6
2、顾客模块流程图··········································7
3、主程序流程图············································8
4、PV操作伪代码···········································9
三、运行结果····················································10
1、代码编辑·················································10
2、编译运行·················································12
3、运行结果·················································10
设计总结···························································13参考文献···························································14
致谢·······························································15
附录:
源代码·······················································16
摘要
理发师问题是一个利用信号量进行PV操作的经典问题。
设计程序实现此问题,要使得理发师的活动与顾客的活动得到各自真实的模拟。
所执行的程序应体现:
理发师在没有顾客的时候去睡觉,有顾客则工作;顾客在理发师工作时坐下等待,无座时离开,直至等到理发师自己理发。
关键字:
理发师,顾客,PV操作。
设计思想
打瞌睡的理发师问题是一种同步问题的抽象描述。
计算机系统中的每个进程都可以消费或生产某类资源,当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
而当某个进程释放资源时,则它就相当一个生产者。
因此此题可看作是n个生产者和1个消费者问题。
顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。
并且,第1个到来的顾客应负责唤醒理发师;如果不是第1个到达的顾客,则在有空椅子的情况下坐下等待,否则离开理发店(该消息可由计数器count获得)。
所以可以通过一个有界缓冲区把理发师和顾客联系起来。
而其中的信号也具有两种功能:
一是跟踪资源的理发师和顾客的计数器;二是协调资源的理发师和顾客之间的同步器。
通过对信号进行P、V操作来实现有关问题和相关描述。
1、数据结构:
1、信号量:
intCustom;//所有到达的顾客,包括正在被理发的顾客,所以一般情况下,Custom比Wait_Person大1
intMutex;//用于实现全局变量Wait——preson访问的互斥
intWait_Leave;//等待离开信号量,用来表示几个顾客等待离开,只要理发师为其理发完毕,他就可以离开了
2、全局变量:
int*Is_Sleeping;//当前理发师是否在睡觉
3、函数:
voidprint1(intWait_person)
voidprint2(intID)
4:
Linux提供的多线程函数:
intpthread_create(pthread_t*—thread,_constpthread_attr_t*attr,void*(*start_rtn)(void*),void*arg);
intpthread_join__P((pthread_t__th,void**__thread_return));pthread_attr_init(&attr);
pthread_attr_getschedparam(&attr,¶m);
param.sched_priority=newprio;
pthread_attr_setschedparam(&attr,¶m);
pthread_create(&tid,&attr,(void*)myfunction,myarg);
pthread_detach(thread_id);pthread_tpthread_self(void);
二、程序模块:
1、理发师模块流程图:
2、顾客模块流程图:
3、主程序流程图:
4、PV操作伪代码
intwaiting=0;//等候理发的顾客数
intchairs=n;//为顾客准备的椅子数
semaphorecustomers=0,barbers=0,mutex=1;
barber()
{
while(TRUE);//理完一人,还有顾客吗?
P(cutomers);//若无顾客,理发师睡眠
P(mutex);//进程互斥
waiting-=1;//等候顾客数少一个
V(barbers);//理发师去为一个顾客理发
V(mutex);//开放临界区
cut-hair();//正在理发
}
customer()
{
P(mutex);//进程互斥
if(waiting)
{
waiting+=1;//等候顾客数加1
V(customers);//必要的话唤醒理发师
V(mutex);//开放临界区
P(barbers);//无理发师,顾客坐着养神
get-haircut();//一个顾客坐下等理/
}
elseV(mutex);//人满了,离开
}
三、测试结果:
1、代码编辑:
2、编译运行:
3、运行结果:
设计总结
本次课程设计完成了多进程同步方法理发师问题全部过程,结果满足设计要求,验证无误。
设计过程中也遇到不少困难,尤其是关于多进程程序的设计实现。
特别需要注意的是由于进程的数据共享会带来其他一些问题,while循环中的各个循环小模块需要严格区别开来,才能使输出结果正确有序。
这些正是编写多进程程序时最需要注意的地方。
通过本次设计,我较好地掌握了通过研究Linux的进程机制和信号量实现PV操作的全过程,尤其是对多进程程序设计方法有了更深的理解,开拓了思路,锻炼了实践动手能手,达到了课程设计目的。
参考文献
1.汤子瀛,哲凤屏.《计算机操作系统》.西安电子科技大学学出版社.
2.王清,李光明.《计算机操作系统》.冶金工业出版社.
3.孙钟秀等.操作系统教程.高等教育出版社
4.曾明. Linux操作系统应用教程.陕西科学技术出版社.
5.张丽芬,刘利雄.《操作系统实验教程》.清华大学出版社.
6.孟静, 操作系统教程--原理和实例分析.高等教育出版社
7.周长林,计算机操作系统教程.高等教育出版社
8.张尧学,计算机操作系统教程,清华大学出版社
9.任满杰,操作系统原理实用教程,电子工业出版社
致谢
在此次课程设计的过程中,我首先要感谢我的指导老师王燕老师,给了我很大的帮助,与此同时班里的同学也教会了我很多相关Linux系统的许多知识,对此次课程设计的程序的调试工作给予了大力的帮助,通过这次课程设计,我学会了Linux系统下编程,调试以及运行C语言程序,同时更深刻地了解了操作系统的相关同步问题原理,使我学到了操作系统的更多知识。
附录:
源代码
#include
#include
#include
#include
#include
#include
#include
#include
#defineN5
#defineM20
intCustom;
intMutex;
intWait_Leave;
int*Is_Sleeping;
voidprint1(intWait_person)
{
if(!
Wait_person)
{
printf("Nocustomerhere,gotosleep.\n");
*Is_Sleeping=1;
}
}
voidprint2(intID)
{
if(*Is_Sleeping)
{
printf("Newcustomer%dcomes,weakupthebarber.\n",ID);
*Is_Sleeping=0;
}
else
printf("Newcustomer%dcomes,therearesomeschairsfree,sitsandwaites.\n",ID);
}
intmain()
{
structsembufP,V;
unionsemunarg;
intPid,i=0;
int*Wait_Person;
//映射共享内存,临界区
Wait_Person=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
*Wait_Person=0;
Is_Sleeping=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
*Is_Sleeping=0;
Custom=semget(IPC_PRIVATE,1,IPC_CREAT|00666);
Mutex=semget(IPC_PRIVATE,1,IPC_CREAT|00666);
Wait_Leave=semget(IPC_PRIVATE,1,IPC_CREAT|00666);
arg.val=0;
if(semctl(Custom,0,SETVAL,arg)==-1)
perror("semctlsemevalerror");
arg.val=1;
if(semctl(Mutex,0,SETVAL,arg)==-1)
perror("semctlsemevalerror");
arg.val=0;
if(semctl(Wait_Leave,0,SETVAL,arg)==-1)
perror("semctlsemevalerror");
V.sem_num=0;
V.sem_op=1;
V.sem_flg=SEM_UNDO;
P.sem_num=0;
P.sem_op=-1;
P.sem_flg=SEM_UNDO;
Pid=fork();
if(Pid==0)
{//理发师进程
while
(1)
{
semop(Mutex,&P,1);
print1(*Wait_Person);
semop(Mutex,&V,1);
semop(Custom,&P,1);
semop(Mutex,&P,1);
(*Wait_Person)--;
semop(Mutex,&V,1);
printf("Barberisworking!
\n");
sleep(3);
printf("Onejobfinished.\n");
semop(Wait_Leave,&V,1);
}
printf("******************Lastoneisfinished,closethedodr.**********************\n");
}
else
{
while
(1)
{
if(Pid==0)
{
semop(Mutex,&P,1);
if((*Wait_Person)>=N)
{
semop(Mutex,&V,1);
printf("Newcustomer%dcomes,thereisnochairandgoaway.\n",getpid());
exit(0);
}
else
{
print2(getpid());唤醒理发师,否则,等待
(*Wait_Person)++;
semop(Mutex,&V,1);
semop(Custom,&V,1);
semop(Wait_Leave,&P,1);
printf("Customer%dfinished,getoutofhere.\n",getpid());
exit(0);
}
}
else
{
sleep(rand()%100/30.0);
if(i{
Pid=fork();
i++;
}
else
break;
}
}
if(i==M)
{
wait(NULL);
}
}
return0;
}