《大工19春《操作系统》大作业题目及要求【题目四答案】.pdf》由会员分享,可在线阅读,更多相关《大工19春《操作系统》大作业题目及要求【题目四答案】.pdf(19页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、网络教育学院网络教育学院操作系统课操作系统课 程程 设设 计计题题目目:进程同步与互斥 生产者与消费者问题学习中心:学习中心:专专业:业:年年级:级:学学号:号:学学生:生:1.1.谈谈你对本课程学习过程中的心得体会与建议?谈谈你对本课程学习过程中的心得体会与建议?答:转眼间,一个学期的操作系统课程就要结束了,在这个学期,通过老师的传授和课本以及课下的阅读学习,让我对计算机操作系统的一些实现原理和简单的操作过程有了基本的了解。在学习操作系统之前,我在前面几个学期学习了数字电路、计算机组成原理、微机原理和汇编语言等课程,这些课程让我了解了计算机硬件如处理器、随机访问存储器、输入输出设备、磁盘驱动
2、器等部件的组成及工作原理,于是我就曾想过自己亲手组装,或者在脑海中虚拟组装一下也可以,把这些互相分离的计算机大部件连接起来,万事俱备,然后通上电,期待着显示器出现想要出现的画面。然而,并非如愿以偿,因为事实上,还缺少了一个重要的部分软件,更确切的说操作系统。经过近乎一个学期的学习,我知道了,操作系统是一个由许多软件构成的庞大的程序集合,它不仅仅单是为用户提供友好界面,更重要的是它还管理着计算机系统的全部硬件资源、软件资源及数据资源,从而使计算机各个组成部件能够顺利高效地、资源最大限度地发挥作用。在这次课程设计中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在实
3、验课上,我们学会了很多学习的方法。而这是以后最实用的,真的是受益匪浅。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。这对于我们的将来也有很大的帮助。回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,但可喜的
4、是最终都得到了解决。此次设计也让我明白了思路即出路,有什么不懂不明白的地方要及时请教或上网查询,只要认真钻研,动脑思考,动手实践,就没有弄不懂的知识,收获颇丰。进程同步与互斥进程同步与互斥 生产者与消费者问题生产者与消费者问题一、设计思路:一、设计思路:1.11.1 生产者消费者问题生产者消费者问题生产者消费者问题(Producer_consumer)是一个经典的进程同步问题。它描述的是:有一群生产者进程在生产产品,并将此产品提供给消费者进程去消费。为使生产者进程和消费者进程能并发执行,在它们之间设置有个缓冲区的缓冲池,生产者进程可将它所生产的产品放入一个缓冲区中,消费者进程可从一个缓冲区取得
5、一个产品消费。尽管所有的生产者进程和消费者进程都是以异步的方式运行的,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装有消息尚未被取走产品的缓冲区投放产品。如下图所示:1.21.2、生产者和消费者原理分析、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品
6、被生产出来。1.31.3、生产者与消费者功能描述:、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。二、基本内容二、基本内容进程同步是指几个进程相互合作,一个进程到达某个点后,除非另一个进程已经完成某些操作,否则就不得不停下来,等待这些操作的结束,这就是
7、进程同步的概念。生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。本作业要求设计在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。生产者消费者问题是一种同步问题的抽象描述。计算机系统中的每个进程都可以消费或生产某类资源,当系统中某一进程使用某一资源时,
8、可以看作是消耗,且该进程称为消费者。而当某个进程释放资源时,则它就相当一个生产者。通过一个有界缓冲区把生产者和消费者联系起来。假定生产者和消费者是相互等效的,只要缓冲区未满,生产者就可以将产品送入缓冲区,类似地,只要缓冲区未空,消费者就可以从缓冲区中去走物品并消费它。生产者和消费者的同步关系将禁止生产者向满的缓冲区输送产品,也禁止消费者从空的缓冲区中提取物品。在生产者消费者问题中,信号灯具有两种功能。首先,它是跟踪资源的生产和消费的计数器;其次,它是协调资源的生产者和消费者之间的同步器。消费者通过再一指派给它的信号灯上做 P 操作来表示消耗资源,而生产者通过在同一信号灯上做 V 操作来表示生产
9、资源。再这种信号灯的实施中,计数在每次 P 操作后减 1,而在每次 V 操作中加 1。个这一计数器的初始值是可利用的资源数目。当资源是不可利用时,将申请资源的进程放置在等待队列中。如果有一个资源释放,在等待队列中的第一个进程被唤醒并得到资源的控制权。为解决这一类生产者消费者问题,设置了两个同步信号灯,一个说明空缓冲区的数目,用empty 表示,其初值为有界缓冲区的大小 n,另一个说明缓冲区的数目,用 full 表示,其初制值为 0。由于有界缓冲区是一个零界资源,必须互斥使用,所以另外还需设置一个互斥信号灯 mutex,起初值为 1。假定在生产者和消费者之间的公用缓冲区中,具有 n 个缓冲区,这
10、时可以利用互斥信号量 mutex 实现诸进程对缓冲池的互斥使用;利用信号量 empty 和 full分别表示缓冲池中空缓冲区和满缓冲区的数量。又假定这些生产者和消费者互相等效果,只要缓冲池未满,生产者便可以将消息送入缓冲池;只要缓冲池未空,消费者便可以从缓冲池中取走一个消息。在生产者-消费者问题中应注意:首先,在每个程序中用于互斥的wait(mutex)和 signal(mutex)必须成对出现;其次,对资源信号量 empty 和 full的 wait 和 signal 操作,同样需要成对地出现,但它们分别处于不同的程序中。生产者与消费者进程共享一个大小固定的缓冲区。其中,一个或多个生产者生产
11、数据,并将生产的数据存入缓冲区,并有一个或多个消费者从缓冲区中取数据。假设缓冲区的大小为 n(存储单元的个数),它可以被生产者和消费者循环使用。分别设置两个指针 in 和 out,指向生产者将存放数据的存储单元和消费者将取出数据的存储单元,如图,指针 in 和 out 初始化指向缓冲区的第一个存储单元。生产者从第一个存储单元开始存放数据,一次存放一条数据一条数据且in 指针向后移一个位置,当 in 指针指向第 n 个存储单元,下一次将指向第一个存储单元,如此循环反复使用缓冲区。消费者从缓冲区中逐条取走数据,一次取一条数据,相应的存储单元变为“空”,可以被生产者再次使用。每次取走一条数据,out
12、 指针向后移一个存储单元位置。试想,如果不控制生产者与消费者,将会产生什么结果?1 2 3 4 5 6 7 8 n In out1 2 3 4 5 6 7 8 n In out其中,in 表示存数据位置,out 表示取数据位置:被占用单元:空存储单元图:生产者/消费者循环使用缓冲区首先,生产者和消费者可能同时进入缓冲区,甚至可能同时读/写一个存储单元,将导致执行结果不确定。这显然是不允许的。所以,必须使生产者和消费者互斥进入缓冲区。即某时刻只允许一个实体(生产者或消费者)访问缓冲区,生产者互斥消费者和其他任何生产者。其次,生产者不能向满的缓冲区写数据,消费者也不能在空缓冲区中取数据,即生产者与
13、消费者必须同步。当生产者产生出数据,需要将其存入缓冲区之前,首先检查缓冲区中是否有“空”存储单元,若缓冲区存储单元全部用完,则生产者必须阻塞等待,直到消费者取走一个存储单元的数据,唤醒它。若缓冲区内有“空”存储单元,生产者需要判断此时是否有别的生产者或消费者正在使用缓冲区,若是有,则阻塞等待,否则,获得缓冲区的使用权,将数据存入缓冲区,释放缓冲区的使用权。消费者取数据之前,首先检查缓冲区中是否存在装有数据的存储单元,若缓冲区为“空”,则阻塞等待,否则,判断缓冲区是否正在被使用,若正被使用,若正被使用,则阻塞等待,否则,获得缓冲区的使用权,进入缓冲区取数据,释放缓冲区的使用权。其执行流程如图所示
14、,伪代码如图所示。2、涉及的数据结构用资源向量 Available。这是一个含有m 个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果 Availablej=K,则表示系统中县有 RJ 类资源 K 个。需求矩阵 MAX。这是一个N*M 的矩阵,它定义了系统中N 个进程中的每一个进程对 M 类资源的最大需求。如果MAXi,j=K,则表示进程I 需要 RJ 类资源的最大数目为 K。矩阵 Allocation。这也是一个 N*M 的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果All
15、ocationi,j=K,则表示进程i 当前已分得 RJ 类资源的数目为 K。矩阵 Need。这也是一个 N*M 的矩阵,用以表示每一个进程尚需的各类资源数。如果 Needi,j=K,则表示进程 I 还需要 RJ 类资源 K 个,方能完成其任务。上述三个矩阵间存在下述关系:Needi,j=MAXi,j-Allocationi,j三、数据流程图:三、数据流程图:3.13.1、生产者、生产者3.23.2、消费者、消费者3.33.3 模块说明:模块说明:constunsignedshort SIZE_OF_BUFFER =10;/缓冲区长度unsignedshort ProductID =0;/产品
16、号unsignedshort ConsumeID =0;/将被消耗的产品号unsignedshort in =0;/产品进缓冲区时的缓冲区下标unsignedshort out =0;/产品出缓冲区时的缓冲区下标int g_bufferSIZE_OF_BUFFER;/缓冲区是个循环队列bool g_continue =true;/控制程序结束 HANDLE g_hMutex;/用于线程间的互斥 HANDLE g_hFullSemaphore;/当缓冲区满时迫使生产者等待 HANDLE g_hEmptySemaphore;/当缓冲区空时迫使消费者等待 DWORD WINAPI Producer(
17、LPVOID);/生产者线程 DWORD WINAPI Consumer(LPVOID);/消费者线程3.43.4 源程序源程序#include#include const unsigned short SIZE_OF_BUFFER=20;/有界缓冲区长度int g_bufferSIZE_OF_BUFFER;/开辟缓冲区,用数组表示,可以看成是一个循环队列unsigned short ProductID=0;/新生产出来的产品的产品号unsigned short ConsumeID=0;/被消耗的产品的产品号unsigned short in=0;/产品进缓冲区时的缓冲区下标,用于记录生产者的
18、指针位置unsigned short out=0;/产品出缓冲区时的缓冲区下标,用于记录消费者的指针位置bool g_continue=1;/控制程序运行:1 表示继续运行,0 表示停止运行HANDLE g_hMutex;/线程间的互斥信号量HANDLE g_hFullSemaphore;/资源信号量:缓冲区满HANDLE g_hEmptySemaphore;/资源信号量:缓冲区空DWORD WINAPI Producer(LPVOID);/生产者线程DWORD WINAPI Consumer(LPVOID);/消费者线程const unsigned short PRODUCERS_COUNT
19、=4;/生产者的个数const unsigned short CONSUMERS_COUNT=3;/消费者的个数constunsignedshortTHREADS_COUNT=PRODUCERS_COUNT+CONSUMERS_COUNT;/总线程数HANDLE hThreadsPRODUCERS_COUNT;/各线程的 handleDWORD producerIDCONSUMERS_COUNT;/生产者线程的标识符DWORD consumerIDTHREADS_COUNT;/消费者线程的标识符/*-*/生产一个产品,输出其 ID 号void Produce()/*-*/*-把 新 生 产 的
20、 产 品 放 入 缓 冲 区 开 始-*/把新生产的产品放入缓冲区生产一个产品结束std:coutstd:endl;std:cerr生产一个产品:+ProductID;std:coutstd:endl;生产一个产品开始void Append()std:cerr把生产的产品送入缓冲区;g_bufferin=ProductID;in=(in+1)%SIZE_OF_BUFFER;std:cerrstd:endl;std:cout缓冲区产品生产者/消费者std:endl;/新产品放入缓冲区后,输出缓冲区当前的状态for(int i=0;iSIZE_OF_BUFFER;+i)/输出缓冲区下标if(i10
21、)std:couti g_bufferi;elsestd:couti g_bufferi;if(i=in)if(i=out)if(g_bufferi10)std:cout ;if(g_bufferi10)std:cout ;elsestd:cout ;std:cout-生产者;/输出生产者的指针位置elsestd:cout ;std:cout-消费者;/输出消费者的指针位置std:coutstd:endl;/*-把 新 生 产 的 产 品 放 入 缓 冲 区 结 束-*/*-*/void Consume()/消费一个产品/*-*/*-从 缓 冲 区 中 取 出 一 个 产 品 开 始-*/从缓
22、冲区中取出一个产品void Take()std:coutstd:endl;std:cerr从缓冲区取出一个产品;ConsumeID=g_bufferout;out=(out+1)%SIZE_OF_BUFFER;std:cerrstd:endl;消费一个产品结束std:coutstd:endl;std:cerr消费一个产品:ConsumeID;std:coutstd:endl;消费一个产品开始std:coutstd:endl;std:cout缓冲区产品生产者/消费者std:endl;/取出一个产品后,输出缓冲区当前的状态for(int i=0;iSIZE_OF_BUFFER;+i)/输出缓冲区下
23、标if(i10)std:couti g_bufferi;elsestd:couti g_bufferi;if(i=in)if(i=out)std:coutstd:endl;if(g_bufferi10)std:cout ;if(g_bufferi10)std:cout ;elsestd:cout ;std:cout-生产者;/输出生产者的指针位置elsestd:cout ;std:cout-消费者;/输出消费者的指针位置/*-从 缓 冲 区 中 取 出 一 个 产 品 结 束-*/*-生产者线程-*/生产者线程DWORD WINAPI Producer(LPVOID lpPara)while(
24、g_continue)/资源信号量的 P 操作WaitForSingleObject(g_hFullSemaphore,INFINITE);/互斥信号量的 P 操作WaitForSingleObject(g_hMutex,INFINITE);/生产一个产品Produce();/把新生产的产品放入缓冲区Append();Sleep(2000);/互斥信号量的 V 操作ReleaseMutex(g_hMutex);/资源信号量的 V 操作ReleaseSemaphore(g_hEmptySemaphore,1,NULL);return 0;/*-生产者线程-*/开始结束/*-消费者线程开-*/消费
25、者线程DWORD WINAPI Consumer(LPVOID lpPara)while(g_continue)/资源信号量的 P 操作WaitForSingleObject(g_hEmptySemaphore,INFINITE);/互斥信号量的 P 操作WaitForSingleObject(g_hMutex,INFINITE);/从缓冲区中取出一个产品Take();/消费一个产品Consume();Sleep(2000);/互斥信号量的 V 操作ReleaseMutex(g_hMutex);/资源信号量的 V 操作ReleaseSemaphore(g_hFullSemaphore,1,NU
26、LL);return 0;/*-消费者线程结-*/*-创建生产者线程开-*/void createPT()/创建生产者线程始束始hThreadsi=CreateThread(NULL,0,Producer,NULL,0,&producerIDi);/*-*/*-*/void createCT()/创建消费者线程hThreadsPRODUCERS_COUNT+j=CreateThread(NULL,0,Consumer,NULL,0,&for(int j=0;jCONSUMERS_COUNT;+j)创建消费者线程开始创建生产者线程结束if(hThreadsi=NULL)g_continue=0;
27、for(int i=0;iPRODUCERS_COUNT;+i)consumerIDj);/*-*/*-主函数开始创建消费者线程结束if(hThreadsj=NULL)g_continue=0;-*/void main()/创建互斥信号量g_hMutex=CreateMutex(NULL,FALSE,NULL);/创建资源信号量g_hFullSemaphore=CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL););/创建生产者线程createPT();/创建消费者线程createCT();g_hEmptySemaphore
28、=CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL/不按回车键的话程序会一直运行下去/*-*/主函数结束while(g_continue)/按回车键终止程序if(getchar()g_continue=0;四、四、总结:总结:生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。