第一篇:生產(chǎn)者與消費(fèi)者的問題-----操作系統(tǒng)課程設(shè)計(jì)
閩江學(xué)院 計(jì)算機(jī)系 網(wǎng)絡(luò)操作系統(tǒng)課程設(shè)計(jì)
設(shè)計(jì)內(nèi)容:進(jìn)程機(jī)制與并發(fā)程序設(shè)計(jì)——linux下生產(chǎn)者與消費(fèi)者的問題實(shí)現(xiàn)
目錄:
一、設(shè)計(jì)內(nèi)容····························3
二、設(shè)計(jì)思想····························4
三、系統(tǒng)結(jié)構(gòu)····························5
四、PV操作代碼··························5
五、C++程序代碼·························6
六、運(yùn)行結(jié)果截圖························9
七、參考文獻(xiàn)····························11
八、實(shí)驗(yàn)總結(jié)····························11
一、設(shè)計(jì)內(nèi)容
進(jìn)程機(jī)制與并發(fā)程序設(shè)計(jì)————linux下生產(chǎn)者與消費(fèi)者的問題實(shí)現(xiàn) 1.實(shí)驗(yàn)?zāi)康?/p>
(1)掌握基本的同步互斥算法,理解生產(chǎn)者和消費(fèi)者同步的問題模型。(2)了解linux中多線程的并發(fā)執(zhí)行機(jī)制,線程間的同步和互斥。
2、實(shí)驗(yàn)環(huán)境:C/C++語(yǔ)言編譯器
3、實(shí)驗(yàn)要求
(1)創(chuàng)建生產(chǎn)者和消費(fèi)者線程
在linux環(huán)境下,創(chuàng)建一個(gè)控制臺(tái)進(jìn)程,在此進(jìn)程中創(chuàng)建n個(gè)線程來(lái)模擬生產(chǎn)者或者消費(fèi)者。這些線程的信息由本程序定義的“測(cè)試用例文件”中予以指定。
該文件的格式和含義如下: 3 1 P 3 2 P 4 3 C 4 1 4 P 2 5 C 3 1 2 4 第一行說(shuō)明程序中設(shè)置幾個(gè)臨界區(qū),其余每行分別描述了一個(gè)生產(chǎn)者或者消費(fèi)者線程的信息。每一行的各字段間用Tab鍵隔開。不管是消費(fèi)者還是生產(chǎn)者,都有一個(gè)對(duì)應(yīng)的線程號(hào),即每一行開始字段那個(gè)整數(shù)。第二個(gè)字段用字母P或者C區(qū)分是生產(chǎn)者還是消費(fèi)者。第三個(gè)字段表示在進(jìn)入相應(yīng)線程后,在進(jìn)行生產(chǎn)和消費(fèi)動(dòng)作前的休眠時(shí)間,以秒計(jì)時(shí);這樣做的目的是可以通過(guò)調(diào)整這一列參數(shù),控制開始進(jìn)行生產(chǎn)和消費(fèi)動(dòng)作的時(shí)間。如果是代表生產(chǎn)者,則該行只有三個(gè)字段。如果代表消費(fèi)者,則該行后邊還有若干字段,代表要求消費(fèi)的產(chǎn)品所對(duì)應(yīng)的生產(chǎn)者的線程號(hào)。所以務(wù)必確認(rèn)這些對(duì)應(yīng)的線程號(hào)存在并且該線程代表一個(gè)生產(chǎn)者。(2)生產(chǎn)和消費(fèi)的規(guī)則
在按照上述要求創(chuàng)建線程進(jìn)行相應(yīng)的讀寫操作時(shí),還需要符合以下要求:
①共享緩沖區(qū)存在空閑空間時(shí),生產(chǎn)者即可使用共享緩沖區(qū)。
②從上邊的測(cè)試數(shù)據(jù)文件例子可以看出,某一生產(chǎn)者生產(chǎn)一個(gè)產(chǎn)品后,可能不止一個(gè)消費(fèi)者,或者一個(gè)消費(fèi)者多次地請(qǐng)求消費(fèi)該產(chǎn)品。此時(shí),只有當(dāng)所有的消費(fèi)需求都被滿足以后,該產(chǎn)品所在的共享緩沖區(qū)才可以被釋放,并作為空閑空間允許新的生產(chǎn)者使用。
③每個(gè)消費(fèi)者線程的各個(gè)消費(fèi)需求之間存在先后順序。例上述測(cè)試用例文件包含一行信息“5 C 3 l 2 4”,可知這代表一個(gè)消費(fèi)者線程,該線程請(qǐng)求消費(fèi)1,2,4號(hào)生產(chǎn)者線程生產(chǎn)的產(chǎn)品。而這種消費(fèi)是有嚴(yán)格順序的,消費(fèi)1號(hào)線程產(chǎn)品的請(qǐng)求得到滿足后才能繼續(xù)往下請(qǐng)求2號(hào)生產(chǎn)者線程的產(chǎn)品。
④要求在每個(gè)線程發(fā)出讀寫操作申請(qǐng)、開始讀寫操作和結(jié)束讀寫操作時(shí)分別顯示提示信息。(3)相關(guān)基礎(chǔ)知識(shí)
本實(shí)驗(yàn)所使用的生產(chǎn)者和消費(fèi)者模型具有如下特點(diǎn):
本實(shí)驗(yàn)的多個(gè)緩沖區(qū)不是環(huán)形循環(huán)的,也不要求按順序訪問。生產(chǎn)者可以把產(chǎn)品放到目前某一個(gè)空緩沖區(qū)中。
消費(fèi)者只消費(fèi)指定生產(chǎn)者的產(chǎn)品。
在測(cè)試用例文件中指定了所有的生產(chǎn)和消費(fèi)的需求,只有當(dāng)共享緩沖區(qū)的數(shù)據(jù)滿足了所有關(guān)于它的消費(fèi)需求后,此共享緩沖區(qū)才可以作為空閑空間允許新的生產(chǎn)者使用。
本實(shí)驗(yàn)在為生產(chǎn)者分配緩沖區(qū)時(shí)各生產(chǎn)者間必須互斥,此后各個(gè)生產(chǎn)者的具體生產(chǎn)活動(dòng)可以并發(fā)。而消費(fèi)者之間只有在對(duì)同一產(chǎn)品進(jìn)行消費(fèi)時(shí)才需要互斥,同時(shí)它們?cè)谙M(fèi)過(guò)程結(jié)束時(shí)需要判斷該消費(fèi)對(duì)象是否已經(jīng)消費(fèi)完畢并清除該產(chǎn)品。
linux用來(lái)實(shí)現(xiàn)同步和互斥的實(shí)體。在linux中,常見的同步對(duì)象有:信號(hào)量(Semaphore)、互斥量(Mutex)、臨界段(CriticalSection)等。使用這些對(duì)象都分為三個(gè)步驟,一是創(chuàng)建或者初始化:接著請(qǐng)求該同步對(duì)象,隨即進(jìn)入臨界區(qū),這一步對(duì)應(yīng)于互斥量的上鎖;最后釋放該同步對(duì)象,這對(duì)應(yīng)于互斥量的解鎖。這些同步對(duì)象在一個(gè)線程中創(chuàng)建,在其他線程中都可以使用,從而實(shí)現(xiàn)同步互斥。
二、設(shè)計(jì)思想
生產(chǎn)者進(jìn)程與消費(fèi)者進(jìn)程是經(jīng)典的同步互斥關(guān)系。系統(tǒng)創(chuàng)建兩類進(jìn)程:proceducer()和consumer(),分別用來(lái)描述生產(chǎn)者和消費(fèi)者的行為。生產(chǎn)者與消費(fèi)者問題是指若干進(jìn)程通過(guò)循環(huán)緩沖池區(qū)交換數(shù)據(jù)。如下圖所示,生產(chǎn)者進(jìn)程不斷向循環(huán)緩沖池區(qū)中寫入數(shù)據(jù)(即生產(chǎn)數(shù)據(jù)),而消費(fèi)者進(jìn)程不斷從循環(huán)緩沖池區(qū)中讀出數(shù)據(jù)(即消費(fèi)數(shù)據(jù))。循環(huán)緩沖池共有N個(gè)緩沖區(qū),緩沖區(qū)可以暫存一個(gè)產(chǎn)品,任何時(shí)刻只能有一個(gè)進(jìn)程課對(duì)循環(huán)緩沖池進(jìn)行操作。所有生產(chǎn)者和消費(fèi)者要協(xié)調(diào)工作,以完成數(shù)據(jù)的交換。只要有空緩沖區(qū),生產(chǎn)者就可以把產(chǎn)品送入緩沖區(qū);只要有滿緩沖區(qū),消費(fèi)者就可以從緩沖區(qū)中取走物品。
為了解決生產(chǎn)者和消費(fèi)者問題,應(yīng)該設(shè)置信號(hào)量和變量如下: full: 滿緩沖區(qū)資源信號(hào)量,初值為0; empty:空緩沖區(qū)資源信號(hào)量,初值為n; in: 生產(chǎn)者指針,初值均為0; out: 消費(fèi)者指針,均為0;
mutex:緩沖區(qū)操作的互斥信號(hào)量,初值為1
三、系統(tǒng)結(jié)構(gòu)
PCB* readyhead=NULL, * readytail=NULL;// 就緒隊(duì)列——鏈表結(jié)構(gòu) PCB* consumerhead=NULL, * consumertail=NULL;// 消費(fèi)者隊(duì)列 PCB* producerhead=NULL, * producertail=NULL;// 生產(chǎn)者隊(duì)列 processproc()---給PCB分配內(nèi)存,產(chǎn)生相應(yīng)的的進(jìn)程 Pempty()---如果緩沖區(qū)滿,該進(jìn)程進(jìn)入生產(chǎn)者等待隊(duì)列;
linkqueue(exe,&producertail);// 把就緒隊(duì)列里的進(jìn)程放入生產(chǎn)者隊(duì)列的尾部 執(zhí)行順序:Main()---empty---in---full---out---finish 當(dāng)緩沖池為空時(shí),生產(chǎn)者生產(chǎn)產(chǎn)品in緩沖池 in=in+1 當(dāng)緩沖池為滿時(shí),消費(fèi)者消費(fèi)產(chǎn)品out緩沖池 out=out+1
四、PV操作代碼
semaphore empty=n;semaphore full=0;semaphore mutex=1;message buffer[n];int in=0;
int out=0;void main(){ parbegin(proceducer(),consumer());}
void proceducer(){ do { prodece a new meddage;P(empty);P(mutex);send a new message to buffer[in];in=(in+1)%n;V(mutex);V(full);} while(true);} void consumer(){ do { P(full);P(mutex);get a message from buffer[out];out=(out+1)%n;V(mutex);V(empty);comsume a message;}while(true);}
五、C++程序代碼
#include “windows.h” #include “iostream.h” #include “math.h”
#define random(rand()*10000)/RAND_MAX //定義一個(gè)隨機(jī)函數(shù)來(lái)生產(chǎn)產(chǎn)品,并且使兩個(gè)顧產(chǎn)品間的時(shí)間少于10秒
int long waiting(0);//正在等待的產(chǎn)品的數(shù)目
int buffer;//空位的總數(shù)目
char empty;//緩沖區(qū)空
char full;//緩沖區(qū)滿
int count(0);//產(chǎn)品的號(hào)碼數(shù)
int finish(0);//生產(chǎn)完畢的產(chǎn)品數(shù)目 DWORD a;void proceduce()
{
Sleep(10000);cout<<“緩沖區(qū)已空!”< } void getconsum(){ Sleep(10001);//產(chǎn)品被生產(chǎn)的函數(shù),為了合理區(qū)分生產(chǎn)產(chǎn)品 cout<<“第”< HANDLE Mutex=CreateMutex(NULL, FALSE, “Mutex”);//用來(lái)實(shí)現(xiàn)進(jìn)程的互斥 HANDLE proceducer=CreateSemaphore(NULL, 1,1, “proceducer”);//定義信號(hào)量來(lái)進(jìn)行線程間的同步 HANDLE consumer=CreateSemaphore(NULL,0,3,“consum”);DWORD WINAPI consum(LPVOID pParm2)//消費(fèi)的線程 { WaitForSingleObject(Mutex ,INFINITE);//p(mutex)來(lái)進(jìn)行互斥操作 count++;//生產(chǎn)的是第幾個(gè)產(chǎn)品 cout<<“第 ”< { if(waiting!=0){ cout<<“此時(shí)有”< else cout<<“沒有產(chǎn)品在等待”< ReleaseMutex(Mutex);//釋放互斥量,以便其他線程使用 WaitForSingleObject(proceducer,INFINITE);//等待生產(chǎn) getconsum();//消費(fèi)并取走 } else { cout<<“緩沖區(qū)已滿,第”< return 0;} DWORD WINAPI proceducers(LPVOID pParm1)//生產(chǎn)者的線程 { while(true)//一直執(zhí)行 { WaitForSingleObject(consum,INFINITE);//p(customers),等待產(chǎn)品 WaitForSingleObject(Mutex,INFINITE);//等待互斥量 waiting--;//等待的產(chǎn)品數(shù)減一 ReleaseSemaphore(proceducer,1,NULL);//釋放信號(hào)量 ResumeThread(proceducer);//喚醒消費(fèi)進(jìn)程 ReleaseMutex(Mutex);//v(mutex);proceduce();//生產(chǎn) finish++;//消費(fèi)的產(chǎn)品數(shù)加1 } return 0;} int main(int argc, char* argv[]){ cout<<“請(qǐng)輸入緩沖區(qū)空位的總數(shù)目:”;cin>>buffer;cout<<“緩沖區(qū)共有”< cout< HANDLE hThread1;HANDLE hThread2;hThread2=::CreateThread(NULL,0,proceducers,NULL,0,NULL);//產(chǎn)生一個(gè)生產(chǎn)者進(jìn)程 while(full!='y'){ Sleep(random);//產(chǎn)品隨機(jī)進(jìn)入 hThread1=::CreateThread(NULL,0,consum,NULL,a,NULL);cout< { cout<<“已經(jīng)為”< else;} if(full=='y'){ cout<<“********對(duì)不起,緩沖區(qū)已滿********”< } 六、運(yùn)行結(jié)果截圖 緩沖區(qū)空位總數(shù)目為1時(shí)運(yùn)行結(jié)果截圖: 緩沖區(qū)空位總數(shù)目為0和3時(shí)運(yùn)行結(jié)果截圖(其余部分如上當(dāng)緩沖區(qū)空位總數(shù)目為1時(shí)的截圖) 七、參考文獻(xiàn) 1、計(jì)算機(jī)網(wǎng)絡(luò)操作系統(tǒng)原理與應(yīng)用 孔憲軍 呂濱(本學(xué)期教科書) 2、網(wǎng)絡(luò)操作系統(tǒng)課程設(shè)計(jì)計(jì)劃書 陳衛(wèi)老師 3、C程序設(shè)計(jì)(第三版)譚浩強(qiáng) 八、實(shí)驗(yàn)總結(jié) 剛剛看到課程設(shè)計(jì)的內(nèi)容與要求時(shí),不禁有點(diǎn)無(wú)從下手的感覺。經(jīng)過(guò)一番思考后,才決定選擇設(shè)計(jì)“進(jìn)程機(jī)制與并發(fā)程序設(shè)計(jì)——linux下生產(chǎn)者與消費(fèi)者的問題實(shí)現(xiàn)”這部分。設(shè)計(jì)這部分不僅僅需要用到C/C++編程,還需要編寫相關(guān)的PV原語(yǔ)。由于自己的PV原語(yǔ)部分和C/C++編程學(xué)的不是很好,因此對(duì)我來(lái)說(shuō)有點(diǎn)難。于是我就積極利用書本上的知識(shí)來(lái)編寫PV原語(yǔ),C/C++編程是參考書上的指點(diǎn)以及網(wǎng)絡(luò)資源編寫出來(lái)的。不懂得地方查資料、上網(wǎng)找、問問其他同學(xué),最后終于慢慢的把課程設(shè)計(jì)做出來(lái)了。通過(guò)這次課程設(shè)計(jì),才感覺到自己還是平時(shí)動(dòng)手少,要經(jīng)常動(dòng)手去做實(shí)驗(yàn)才能真正學(xué)到東西。尤其是一些C/C++編程和PV原語(yǔ)的編寫更需要平時(shí)多加練習(xí)才能學(xué)好用好。特別是C/C++編程在遇到語(yǔ)法有多處錯(cuò)誤時(shí),不能急,要冷靜下來(lái)慢慢修改,知道程序正確。雖然是自己獨(dú)立做的課程設(shè)計(jì),但是其中還是有很多不懂的東西是問同學(xué)的,因此了解到學(xué)習(xí)不是單獨(dú)的,應(yīng)該是相互交流相互學(xué)習(xí)的。 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) (操作系統(tǒng)課程設(shè)計(jì)) 生 產(chǎn) 者 和 消 費(fèi) 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) 者 學(xué)生姓名: 學(xué)生學(xué)號(hào): 班 級(jí): 0311401、02、03、04班制 二〇一三年十二月 一、課程題目分析 這個(gè)題目是生產(chǎn)者向消費(fèi)者提供商品,消費(fèi)者消耗商品,并且兩組人共用同一緩沖區(qū)。生產(chǎn)者提供了商品之后消費(fèi)者才能去取商品,消費(fèi)者若不取走商品則當(dāng)緩沖區(qū)用完之后生產(chǎn)者則不能再向緩沖區(qū)中添加新的商品。 思考問題: (1)對(duì)于生產(chǎn)者進(jìn)程:每產(chǎn)生一個(gè)數(shù)據(jù),則需去訪問共用緩沖區(qū)是否有已滿,未滿則可以將該數(shù)據(jù)存入并通知消費(fèi)者進(jìn)程,否則不能。 (2)對(duì)于消費(fèi)者進(jìn)程:每當(dāng)想去消費(fèi)(取出數(shù)據(jù))時(shí),則需訪問緩沖區(qū)是否為空,為空則不能消費(fèi)(取出數(shù)據(jù)),否則可以取,并通知生產(chǎn)者。 (3)緩沖區(qū)是個(gè)臨界資源,所有的進(jìn)程對(duì)于該空間都是共享的,所以,還有互斥問題存在。 二、課程設(shè)計(jì)目的 通過(guò)實(shí)驗(yàn)?zāi)M生產(chǎn)者與消費(fèi)者之間的關(guān)系,了解并掌握他們之間的關(guān)系及原理。由此增加對(duì)進(jìn)程同步問題的了解: (1)掌握基本的同步互斥算法,理解生產(chǎn)者與消費(fèi)者模型 (2)了解windows中多線程(多進(jìn)程)的并發(fā)執(zhí)行機(jī)制,線程(進(jìn)程)間的同步于互斥 (3)學(xué)習(xí)使用windows中基本的同步對(duì)象,掌握相應(yīng)的API。 三、課程設(shè)計(jì)內(nèi)容 有n個(gè)生產(chǎn)者和m個(gè)消費(fèi)者,連接在具有k個(gè)單位緩沖區(qū)的有界環(huán)轉(zhuǎn)緩沖上,湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) 故又稱有界緩沖問題。其中Pi和Cj都是并發(fā)進(jìn)程,只要緩沖區(qū)未滿,生產(chǎn)者進(jìn)程Pi所生產(chǎn)的產(chǎn)品就可投入緩沖區(qū);類似地,只要緩沖區(qū)非空,消費(fèi)者進(jìn)程Cj就可以從緩沖區(qū)取走并消耗產(chǎn)品。 四、開發(fā)環(huán)境 操作系統(tǒng):Windows系統(tǒng) 編寫語(yǔ)言:C++語(yǔ)言 五、系統(tǒng)分析設(shè)計(jì) (一)算法原理 生產(chǎn)者——消費(fèi)者問題是典型的進(jìn)程同步問題,這些進(jìn)程必須按照一定的生產(chǎn)率和消費(fèi)率來(lái)訪問共享緩沖區(qū),用P、V操作解決生產(chǎn)者和消費(fèi)者共享單緩沖區(qū)的問題,可設(shè)置兩個(gè)信號(hào)量empty和full,其初值分別為1和0,empty指示能否向緩沖區(qū)放入產(chǎn)品,full指示能否從緩沖區(qū)取出產(chǎn)品。為了使其協(xié)調(diào)工作,必須使用一個(gè)信號(hào)量mutex(初值為1),以限制生產(chǎn)者和消費(fèi)者互斥地對(duì)緩沖區(qū)進(jìn)行存取,另用兩個(gè)信號(hào)量empty1(初值為緩沖區(qū)大小)和full1(初值為0),以保證生產(chǎn)者不向已滿的緩沖區(qū)中放入產(chǎn)品,消費(fèi)者不從空緩沖區(qū)中取產(chǎn)品。 (二)功能描述 生產(chǎn)者功能描述:在同一個(gè)進(jìn)程地址空間內(nèi)執(zhí)行兩個(gè)線程。生產(chǎn)者線程生產(chǎn)物品,然后將物品放置在一個(gè)空緩沖區(qū)中供消費(fèi)者線程消費(fèi)。當(dāng)生產(chǎn)者線程生產(chǎn)物品時(shí),如果沒有空緩沖區(qū)可用,那么生產(chǎn)者線程必須等待消費(fèi)者線程釋放出一個(gè)空緩沖區(qū)。 消費(fèi)者功能描述:消費(fèi)者線程從緩沖區(qū)獲得物品,然后釋放緩沖區(qū),當(dāng)消費(fèi)者線程消費(fèi)物品時(shí),如果沒有滿的緩沖區(qū),那么消費(fèi)者線程將被阻塞,直到新的物品被生產(chǎn)出來(lái)。 (三)算法流程圖 生產(chǎn)者流程圖: 消費(fèi)者流程圖: 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) 總的流程圖: 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) 開始Int i=1,n鍵盤輸入數(shù)字,初始化 n SeqSquare *b;b=new SeqSquare(n);鍵盤輸入數(shù)字,改變i的值i==0?Y退出Ncout<<“請(qǐng)輸入正確的菜單項(xiàng)進(jìn)行操作!”< (四)數(shù)據(jù)結(jié)構(gòu)及部分函數(shù)描述 (1)類SeqSquare:對(duì)類SeqSquare的聲明及其中一些函數(shù) class SeqSquare { public: SeqSquare(int n);~SeqSquare();void P(int x);//p操作 void V(int x);//v操作 bool IsEmpty();//判斷是否為空 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) bool IsFull();//判斷是否已滿 void deca();void decb();int getSize();int getmaxSize();int gettop();int geta();int getb();protected: private: };說(shuō)明:①用動(dòng)態(tài)整型數(shù)組*elements來(lái)代表緩沖區(qū),不管是生產(chǎn)產(chǎn)品還是對(duì)已有產(chǎn)品的消費(fèi)都需要訪問該緩沖區(qū)。②函數(shù)IsFull()用于判斷緩沖區(qū)是否已滿,生產(chǎn)者能否使用緩沖區(qū)。③函數(shù)IsEmpty()用于判斷緩沖區(qū)是否為空,消費(fèi)者能否使用緩沖區(qū)。 (2)生產(chǎn)者和消費(fèi)者操作及顯示函數(shù)showbuf: void producer(SeqSquare *a)//生產(chǎn)者操作 { } void consumer(SeqSquare *a)//消費(fèi)者操作 { } //緩沖區(qū)顯示 void showbuf(SeqSquare *a){ }(3)在實(shí)現(xiàn)本程序的生產(chǎn)者消費(fèi)者模型時(shí),具體地通過(guò)以下同步對(duì)象實(shí)現(xiàn)互斥: int *elements;int top,a,b,maxSize;a->P(1);a->V(1);int i=a->getSize();湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) ①設(shè)一個(gè)互斥量Mutex,以實(shí)現(xiàn)生產(chǎn)者在查詢和保留緩沖區(qū)的下一個(gè)空位置時(shí)進(jìn)行互斥。 ②每一個(gè)生產(chǎn)者用一個(gè)信號(hào)量與消費(fèi)者同步,通過(guò)設(shè)置Full實(shí)現(xiàn),該組信號(hào)量用于表示相應(yīng)產(chǎn)品以生產(chǎn)。同時(shí)用一個(gè)表示空緩沖區(qū)數(shù)目的信號(hào)量Empty進(jìn)行類似的同步,指示緩沖區(qū)中是否存在空位置,以便開始生產(chǎn)下一個(gè)產(chǎn)品。 (四)調(diào)試過(guò)程 為解決生產(chǎn)者、消費(fèi)者問題,應(yīng)該設(shè)置兩個(gè)資源信號(hào)量,其中一個(gè)表示空緩沖區(qū)的數(shù)目,用Full表示,其初值為用戶輸入的緩沖區(qū)的大小,另一個(gè)表示緩沖區(qū)中產(chǎn)品的數(shù)目,用Empty表示,其初值為0.另外,由于緩沖區(qū)是一個(gè)臨界資源,必須互斥使用,所以還需要再設(shè)置一個(gè)互斥信號(hào)量Mutex,其初值為1.在生產(chǎn)者、消費(fèi)者問題中,信號(hào)量實(shí)現(xiàn)兩種功能。首先,他是生產(chǎn)產(chǎn)品和消費(fèi)產(chǎn)品的計(jì)數(shù)器,計(jì)數(shù)器的初值是可使用的資源數(shù)目(緩沖區(qū)的長(zhǎng)度)。其次,他是確保產(chǎn)品的生產(chǎn)者和消費(fèi)者之間的動(dòng)作同步的同步器。 生產(chǎn)者要生產(chǎn)一個(gè)產(chǎn)品時(shí),首先對(duì)資源信號(hào)量Full和互斥信號(hào)量Mutex進(jìn)行P操作,申請(qǐng)資源。如果可以通過(guò)的話,就生產(chǎn)一個(gè)產(chǎn)品,并把產(chǎn)品送人緩沖區(qū)。然后對(duì)互斥信號(hào)量Mutex和資源信號(hào)量Empty進(jìn)行V操作,釋放資源。 消費(fèi)者要消費(fèi)一個(gè)產(chǎn)品時(shí),首先對(duì)資源信號(hào)量Empty和互斥信號(hào)量Mutex進(jìn)行P操作,申請(qǐng)資源。如果可以通過(guò)的話就從緩沖區(qū)取出一個(gè)產(chǎn)品并消費(fèi)掉。然后對(duì)互斥信號(hào)量Mutex和資源信號(hào)量Full進(jìn)行V操作,釋放資源。 如果緩沖區(qū)中已經(jīng)沒有可用資源,就把申請(qǐng)資源的進(jìn)程添加到等待隊(duì)列的隊(duì)尾。如果有一個(gè)資源被釋放,在等待隊(duì)列中的第一個(gè)進(jìn)程被喚醒并取得這個(gè)資源的使用權(quán)。 (五)參考資料 《操作系統(tǒng)教程》 孫鐘秀 高等教育出版社 《C++程序設(shè)計(jì)》 譚浩強(qiáng) 高等教育出版社 六、運(yùn)行實(shí)例及結(jié)果分析 (一)運(yùn)行實(shí)例 緩沖區(qū)大小為3,先生產(chǎn)一件產(chǎn)品,顯示緩沖區(qū),再接著生產(chǎn)一件產(chǎn)品,消耗一件產(chǎn)品,顯示緩沖區(qū),在消耗兩件產(chǎn)品,再生產(chǎn)4件產(chǎn)品,改變緩沖區(qū)的大小為6,顯示緩沖區(qū),選擇一個(gè)未出現(xiàn)的選項(xiàng),退出程序。 (二)結(jié)果顯示 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) (三)結(jié)果分析 (1)在每個(gè)程序中需要先做P,后做V,二者要成對(duì)出現(xiàn),夾在二者中間的代碼段就是該進(jìn)程的臨界區(qū)。 (2)對(duì)同步信號(hào)量full和empty的P,V操作同樣必須成對(duì)出現(xiàn),但它們分別位于不同的程序中。 (3)無(wú)論在生產(chǎn)者進(jìn)程中還是消費(fèi)者進(jìn)程中,兩個(gè)P操作的次序不能顛倒:應(yīng)先執(zhí)行同步信號(hào)量的P操作,然后執(zhí)行互斥信號(hào)量的P操作。否則可能造成進(jìn)程死鎖。 七、個(gè)人體驗(yàn) 雖然我也很想用java語(yǔ)言寫這個(gè)程序,但是由于自己學(xué)藝不精,所以只能用C++寫。通過(guò)這個(gè)實(shí)驗(yàn)我發(fā)現(xiàn)我以前有很多知識(shí)都忘記了,重新拿起課本學(xué)習(xí)9 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) 時(shí)發(fā)現(xiàn)原來(lái)很多不懂得問題都有了新的認(rèn)識(shí),有一種豁然開朗的感覺。也為我考研開了一個(gè)好的開頭。 我認(rèn)為我完成的這個(gè)設(shè)計(jì)做的比較出色的地方是對(duì)C++語(yǔ)言中類以及數(shù)組的運(yùn)用,其實(shí)這里我對(duì)數(shù)組的操作是按照“先進(jìn)先出”的方法進(jìn)行運(yùn)作的,這是參考了棧的工作原理,因?yàn)榫彌_區(qū)一般也是堆棧,比較符合設(shè)計(jì)要求。 這次實(shí)驗(yàn)中我感覺做的很粗糙,自己所想的模擬過(guò)程的確得到實(shí)現(xiàn)了,但是感覺靈活性不太高,思考還不過(guò)全面,應(yīng)該以后多注意一下,多考慮考慮才是。 在這次實(shí)驗(yàn)中我重新將《C++程序設(shè)計(jì)》和《數(shù)據(jù)結(jié)構(gòu)》的幾個(gè)重要章節(jié)復(fù)習(xí)了一遍,對(duì)類、數(shù)組、C++的I/O流類庫(kù)以及堆棧的語(yǔ)句格式、注意細(xì)節(jié)都再一次熟悉,感覺蠻有趣的。不過(guò),在編程過(guò)程中許多語(yǔ)句的小問題還真是出現(xiàn)不少,而且感覺自己對(duì)C++強(qiáng)大豐富的語(yǔ)句方法用得太呆板,不夠靈活,總是想到那些常用的,而忽略了顆粒讓語(yǔ)句更簡(jiǎn)短的方法,以后要多多注意才是。 八、附錄 // 生產(chǎn)者消費(fèi)者1.cpp : Defines the entry point for the console application.// #include “stdafx.h” #include “iostream” using namespace std;class SeqSquare { public: SeqSquare(int n);~SeqSquare();void P(int x); //p操作 void V(int x); //v操作 bool IsEmpty(); //判斷是否為空 bool IsFull(); //判斷是否已滿 void deca();void decb();int getSize();int getmaxSize();int gettop();int geta();int getb();protected: private: int *elements;int top,a,b,maxSize;};10 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) bool SeqSquare::IsEmpty() //判斷是否為空 { return(top==-1)?true:false;} bool SeqSquare::IsFull() //判斷是否已滿 { return(top>=maxSize-1)?true:false;} void SeqSquare::deca(){ a--;} void SeqSquare::decb(){ b--;} int SeqSquare::getSize(){ return top+1;} int SeqSquare::getmaxSize(){ return maxSize;} int SeqSquare::gettop(){ return top;} int SeqSquare::geta(){ return a;} int SeqSquare::getb(){ 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) return b;} SeqSquare::SeqSquare(int n){ top =-1;a = b =0;maxSize = n;elements = new int[maxSize];} void SeqSquare::P(int x){ if(IsFull()==true){ a=a+1;} else { elements[++top] = x; } } void SeqSquare::V(int x){ if(IsEmpty()==true){ b = b+1;} else { x = elements[top--]; } } 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) void producer(SeqSquare *a) //生產(chǎn)者操作 { a->P(1);} void consumer(SeqSquare *a) //消費(fèi)者操作 { a->V(1);} SeqSquare::~SeqSquare(){ delete elements;} //緩沖區(qū)顯示 void showbuf(SeqSquare *a){ int i=a->getSize(); } int main(){ int i,n;cout<<“請(qǐng)輸入緩沖區(qū)大小:”< cout<<“請(qǐng)選擇操作: ”< 4.退出系統(tǒng)。 ”< ”< switch(i) { case 1: producer(s); if(s->geta()==0) { 湖北民族學(xué)院信息工程學(xué)院11級(jí)計(jì)算機(jī)專業(yè)操作系統(tǒng)課程設(shè)計(jì) cout< } else { cout< s->deca(); } break; case 2: consumer(s); if(s->getb()==0) { cout< } else { cout< } break; case 3: showbuf(s); cout< ”<<“可用空間為:”<<(n-s->getSize())< break; case 4: cout< break; case 5: cout< cin>>n; s = new SeqSquare(n); cout< break; default: cout< } } return 0;} 實(shí) 驗(yàn) 二 經(jīng) 典 的 生 產(chǎn) 者 — 消 費(fèi) 者 問 題 一、目的 實(shí)現(xiàn)對(duì)經(jīng)典的生產(chǎn)者—消費(fèi)者問題的模擬,以便更好的理解經(jīng)典進(jìn)程同步問題。 二、實(shí)驗(yàn)內(nèi)容及要求 編制生產(chǎn)者—消費(fèi)者算法,模擬一個(gè)生產(chǎn)者、一個(gè)消費(fèi)者,共享一個(gè)緩沖池的情形。 1、實(shí)現(xiàn)對(duì)經(jīng)典的生產(chǎn)者—消費(fèi)者問題的模擬,以便更好的理解此經(jīng)典進(jìn)程同步問題。生產(chǎn)者- 消費(fèi)者問題是典型的 PV 操作問題,假設(shè)系統(tǒng)中有一個(gè)比較大的緩沖池,生產(chǎn)者的任務(wù)是只要緩沖池未滿就可以將生產(chǎn)出的產(chǎn)品放入其中,而消費(fèi)者的任務(wù)是只要緩沖池未空就可以從緩沖池中拿走產(chǎn) 品。緩沖池被占用時(shí),任何進(jìn)程都不能訪問。 2、每一個(gè)生產(chǎn)者都要把自己生產(chǎn)的產(chǎn)品放入緩沖池,每個(gè)消費(fèi)者從緩沖池中取走產(chǎn)品消費(fèi)。在這種情況下,生產(chǎn)者消費(fèi)者進(jìn)程同步,因?yàn)橹挥型ㄟ^(guò)互通消息才知道是否能存入產(chǎn)品或者取走產(chǎn)品。他們之間也存在互斥,即生產(chǎn)者消費(fèi)者必須互斥訪問緩沖池,即不能有兩個(gè)以上的進(jìn)程同時(shí)進(jìn)行。 三、生產(chǎn)者和消費(fèi)者原理分析 在同一個(gè)進(jìn)程地址空間內(nèi)執(zhí)行兩個(gè)線程。 生產(chǎn)者線程生產(chǎn)物品,然后將物品放置在一個(gè)空緩沖區(qū)中供消費(fèi)者線程消費(fèi)。 消費(fèi)者線程從緩沖區(qū)中獲得物品,然后釋放緩沖區(qū)。 當(dāng)生產(chǎn)者線程生產(chǎn)物品時(shí),如果沒有空緩沖區(qū)可用,那么生產(chǎn)者線程必須等待消費(fèi)者線程釋放一個(gè)空緩沖區(qū)。 當(dāng)消費(fèi)者線程消費(fèi)物品時(shí),如果沒有滿的緩沖區(qū),那么消費(fèi)者線程將被阻擋,直到新的物品被生產(chǎn)出來(lái)。 四、生產(chǎn)者與消費(fèi)者功能描述: 生產(chǎn)者功能描述:在同一個(gè)進(jìn)程地址空間內(nèi)執(zhí)行兩個(gè)線程。生產(chǎn)者線程生產(chǎn)物品,然后將物品放置在一個(gè)空緩沖區(qū)中供消費(fèi)者線程消費(fèi)。當(dāng)生產(chǎn)者線程生產(chǎn)物品時(shí),如果沒有空緩沖區(qū)可用,那么生產(chǎn)者線程必須等待消費(fèi)者線程釋放出一個(gè)空緩沖區(qū)。 消費(fèi)者功能描述:消費(fèi)者線程從緩沖區(qū)獲得物品,然后釋放緩沖區(qū),當(dāng)消費(fèi)者線程消費(fèi)物品時(shí),如果沒有滿的緩沖區(qū),那么消費(fèi)者線程將被阻塞,直到新的物品被生產(chǎn)出來(lái)。 五、實(shí)驗(yàn)環(huán)境 操作系統(tǒng)環(huán)境: Windows 系統(tǒng)。編程語(yǔ)言: C#。 六、生產(chǎn)者與消費(fèi)者的思路和設(shè)計(jì) 1、程序流程圖 (1)生產(chǎn)者 開 始 生產(chǎn)產(chǎn)品 Wait empty ≤ 0 Y N Wait 緩沖區(qū)內(nèi)已滿,已無(wú) 可用緩沖區(qū) N Mutex=1 Y 緩沖區(qū)正被其他 程占用 進(jìn) 存入緩沖區(qū) empty = empty-1 Signal Signal(full)結(jié) 束 (2)消費(fèi)者 開 始 Wait(full)消費(fèi)請(qǐng)求 full ≤ 0 Y N Wait 緩沖區(qū)內(nèi)產(chǎn)品已空,不能進(jìn)行消費(fèi) N Mutex=1 Y 消 費(fèi) 緩沖區(qū)正被其他 程占用 進(jìn) full = full-1 Signal Signal 結(jié) 束 2、主要程序代碼 // 初始化變量 private void Form1_Load(object sender, EventArgs e){ mutex = 1;// 互斥信號(hào)量 full = 0;// 緩沖池中滿緩沖區(qū)的數(shù)量 empty = 5;// 緩沖池中空緩沖區(qū)的數(shù)量 count1 = 0;// 生產(chǎn)的產(chǎn)品數(shù)目 i = 0;= “1”;= “0”;= “5”;} // 消費(fèi)者從緩沖區(qū)中消費(fèi)一個(gè)產(chǎn)品 private void consumer_Click(object sender, EventArgs e){ if(full > 0){ // 消費(fèi)者已進(jìn)入互斥臨界區(qū) if(mutex == 1)// 申請(qǐng)進(jìn)入臨界區(qū) { mutex = 0;// 消費(fèi)者已進(jìn)入互斥臨界區(qū) = “0”;= true;// 啟動(dòng)消費(fèi)者消費(fèi)緩沖區(qū)產(chǎn)品 } else {(“ 緩沖區(qū)被占用,請(qǐng)等待。。 ”, “ 信息提 ”;} } else {(“ 緩沖區(qū)為空,不能消費(fèi)!”, “ 信息提示 ”,;} } // 生產(chǎn)者向緩沖區(qū)中存入一個(gè)產(chǎn)品 private void producer_Click(object sender, EventArgs e){ count1 = count1 + if(empty > 0){ 1; // // 生產(chǎn)一個(gè)產(chǎn)品 有緩沖區(qū)可放產(chǎn)品 if(mutex == 1){ // 申請(qǐng)進(jìn)入臨界區(qū) mutex = 0; // 生產(chǎn)者已進(jìn)入臨界區(qū) = “0”; ();// 啟動(dòng)生產(chǎn)者將產(chǎn)品放入緩沖區(qū) } else { // 不能進(jìn)入臨界區(qū) count1 = count1-1;(“ 緩沖區(qū)被占用,請(qǐng)等待。。 ”, “ 信息提示 ”,;} } else {(“ 緩沖區(qū)已滿!”, “ 信息提示 ”,;// 無(wú)緩沖區(qū)可放產(chǎn)品 count1 = count1-1;} } // 生產(chǎn)者 private void timer1_Tick_1(object sender, EventArgs e){ if(bool1){ switch(count1){ case 1: = true;break;case 2: = true;break;case 3: = true;break;case 4: = true;break;case 5: = true;break;} = “ 生產(chǎn)者進(jìn)程占用緩沖區(qū),請(qǐng)等待。。 ”;bool1 = false;} else { switch(count1){ case 1: = false;break;case 2: = false;break;case 3: = false;break;case 4: = false;break;case 5: = false;break;} = “ 生產(chǎn)者進(jìn)程占用緩沖區(qū),請(qǐng)等待。。 ”;bool1 = true;} i = i + 1;if(i == 5) { // 循環(huán)緩沖區(qū),首尾相接 i = 0;= false;mutex = 1;= “1”;switch(count1){ case 1: = true;break;case 2: = true;break;case 3: = true;break;case 4: = true;break;case 5: = true;break;} full = full + 1;=();empty = empty-1;=();= “ 生產(chǎn)結(jié)束!”;} } // 消費(fèi)者 private void timer_consumer_Tick(object sender, EventArgs e){ if(bool1){ switch(count1){ case 1: = true;break;case 2: = true;break;case 3: = true;break;case 4: = true;break;case 5: = true;break;} = “ 消費(fèi)者進(jìn)程占用緩沖區(qū),請(qǐng)等待。。 ”;bool1 =false;} else{ switch(count1){ case 1: = false;break;case 2: = false;break;case 3: = false;break;case 4: = false;break;case 5: = false;break;} = “ 消費(fèi)者進(jìn)程占用緩沖區(qū),請(qǐng)等待。。 ”;bool1= true;} i = i + 1;if(i==5){ i = 0;= false;mutex = 1;= “1”;switch(count1){ case 1: = false;break;case 2: = false;break;case 3: = false;break;case 4: = false;break;case 5: = false;break;} count1 = count1-1;full = full-1;=();empty = empty+1;=();=“ 消費(fèi)結(jié)束! ”;} 3、運(yùn)行界面和運(yùn)行結(jié)果 一般情況下,點(diǎn)一次生產(chǎn)者按紐,mutex 由 1 變?yōu)?0,緩沖區(qū)呈現(xiàn)閃爍狀態(tài)(表示正在存儲(chǔ)),此時(shí)不可以再進(jìn)行緩沖區(qū)操作,否則將顯示“生產(chǎn)者進(jìn)程正在占用緩沖區(qū),請(qǐng)等待”。閃爍約秒后,mutex 由 0 變?yōu)?1,閃爍停止,表示存儲(chǔ)過(guò)程結(jié)束;點(diǎn)一次消費(fèi)者按紐,mutex 由 1 變?yōu)?0,緩沖區(qū)呈現(xiàn)閃爍狀態(tài)(表示正在消費(fèi)),此時(shí)不可以再進(jìn)行緩沖區(qū)操作,否則將顯示“消費(fèi)者進(jìn)程正在占用緩 沖區(qū),請(qǐng)等待”。閃爍約秒后,mutex 由 0 變?yōu)?1,閃爍停止,表示消費(fèi)過(guò)程結(jié)束。緩沖池滿后,若再點(diǎn)生產(chǎn)者按紐,會(huì)給出信息提示: “緩沖區(qū)已滿!”。 緩沖池空后,若再點(diǎn)消費(fèi)者按紐,也會(huì)給出信息提示: “緩沖區(qū)為空,不能消費(fèi)!”。 在存儲(chǔ)狀態(tài)或消費(fèi)狀態(tài)(閃爍狀態(tài)),無(wú)論是點(diǎn)生產(chǎn)者按紐還是消費(fèi)者按紐都會(huì)給出“緩沖區(qū)被占用,請(qǐng)等待。”信息提示。 七、心得體會(huì) 本次實(shí)驗(yàn)是關(guān)于生產(chǎn)者與消費(fèi)者之間互斥和同步的問題。問題的是指是 P、V 操作,實(shí)驗(yàn)設(shè)一個(gè)共享緩沖區(qū),生產(chǎn)者和消費(fèi)者互斥的使用,當(dāng)一個(gè)線程使用緩沖區(qū)的時(shí)候,另一個(gè)讓其等待直到前一 個(gè)線程釋放緩沖區(qū)為止。 生產(chǎn)者與消費(fèi)者是一個(gè)與現(xiàn)實(shí)有關(guān)的經(jīng)驗(yàn)問題,通過(guò)此原理舉一反三可以解決其他類似的問題。 通過(guò)本實(shí)驗(yàn)設(shè)計(jì),我們對(duì)操作系統(tǒng)的 P、V 進(jìn)一步的認(rèn)識(shí),深入的了解 P、V 操作的實(shí)質(zhì)和其重 要性。課本的理論知識(shí)進(jìn)一步闡述了現(xiàn)實(shí)中的實(shí)際問題。 實(shí)驗(yàn)中,我們小組分工合作,共同學(xué)習(xí),雖然在實(shí)驗(yàn)中遇到了一些問題,但在老師和同學(xué)的細(xì)心指導(dǎo)和熱心幫助下解決了。同時(shí),了解到團(tuán)隊(duì)精神的重要性,也為以后的學(xué)習(xí)和工作打下了堅(jiān)實(shí)的基礎(chǔ),同時(shí)積累了寶貴的經(jīng)驗(yàn)。 實(shí)驗(yàn)報(bào)告五 ——生產(chǎn)者和消費(fèi)者問題 姓名:叢菲 學(xué)號(hào):20100830205 班級(jí):信息安全二班 一、實(shí)習(xí)內(nèi)容 ? ? 1、模擬操作系統(tǒng)中進(jìn)程同步和互斥 2、實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者問題的算法實(shí)現(xiàn) 二、實(shí)習(xí)目的 ? ? ? ? ? 1、熟悉臨界資源、信號(hào)量及PV操作的定義與物理意義 2、了解進(jìn)程通信的方法 3、掌握進(jìn)程互斥與進(jìn)程同步的相關(guān)知識(shí) 4、掌握用信號(hào)量機(jī)制解決進(jìn)程之間的同步與互斥問題 5、實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者問題,深刻理解進(jìn)程同步問題 三、實(shí)習(xí)題目 ? 在Linux操作系統(tǒng)下用C實(shí)現(xiàn)經(jīng)典同步問題:生產(chǎn)者—消費(fèi)者,具體要求如下: (1)一個(gè)大小為10的緩沖區(qū),初始狀態(tài)為空。 (2)2個(gè)生產(chǎn)者,隨機(jī)等待一段時(shí)間,往緩沖區(qū)中添加數(shù)據(jù),若緩沖區(qū)已滿,等待消費(fèi)者取走數(shù)據(jù)之后再添加,重復(fù)10次。 (3)2個(gè)消費(fèi)者,隨機(jī)等待一段時(shí)間,從緩沖區(qū)中讀取數(shù)據(jù),若緩沖區(qū)為空,等待生產(chǎn)者添加數(shù)據(jù)之后再讀取,重復(fù)10次。? 提示 本實(shí)驗(yàn)的主要目的是模擬操作系統(tǒng)中進(jìn)程同步和互斥。在系統(tǒng)進(jìn)程并發(fā)執(zhí)行異步推進(jìn)的過(guò)程中,由于資源共享和進(jìn)程間合作而造成進(jìn)程間相互制約。進(jìn)程間的相互制約有兩種不同的方式。 (1)間接制約。這是由于多個(gè)進(jìn)程共享同一資源(如CPU、共享輸入/輸出設(shè)備)而引起的,即共享資源的多個(gè)進(jìn)程因系統(tǒng)協(xié)調(diào)使用資源而相互制約。 (2)直接制約。只是由于進(jìn)程合作中各個(gè)進(jìn)程為完成同一任務(wù)而造成的,即并發(fā)進(jìn)程各自的執(zhí)行結(jié)果互為對(duì)方的執(zhí)行條件,從而限制各個(gè)進(jìn)程的執(zhí)行速度。 生產(chǎn)者和消費(fèi)者是經(jīng)典的進(jìn)程同步問題,在這個(gè)問題中,生產(chǎn)者不斷的向緩沖區(qū)中寫入數(shù)據(jù),而消費(fèi)者則從緩沖區(qū)中讀取數(shù)據(jù)。生產(chǎn)者進(jìn)程和消費(fèi)者對(duì)緩沖區(qū)的操作是互斥,即當(dāng)前只能有一個(gè)進(jìn)程對(duì)這個(gè)緩沖區(qū)進(jìn)行操作,生產(chǎn)者進(jìn)入操作緩沖區(qū)之前,先要看緩沖區(qū)是否已滿,如果緩沖區(qū)已滿,則它必須等待消費(fèi)者進(jìn)程將數(shù)據(jù)取出才能寫入數(shù)據(jù),同樣的,消費(fèi)者進(jìn)程從緩沖區(qū)讀取數(shù)據(jù)之前,也要判斷緩沖區(qū)是否為空,如果為空,則必須等待生產(chǎn)者進(jìn)程寫入數(shù)據(jù)才能讀取數(shù)據(jù)。 在本實(shí)驗(yàn)中,進(jìn)程之間要進(jìn)行通信來(lái)操作同一緩沖區(qū)。一般來(lái)說(shuō),進(jìn)程間的通信根據(jù)通信內(nèi)容可以劃分為兩種:即控制信息的傳送與大批量數(shù)據(jù)傳送。有時(shí),也把進(jìn)程間控制在本實(shí)驗(yàn)中,進(jìn)程之間要進(jìn)行通信來(lái)操作同一緩沖區(qū)。一般來(lái)說(shuō),進(jìn)程間的通信根據(jù)通信內(nèi)容可以劃分為兩種:即控制信息的傳送與大批量數(shù)據(jù)傳送。有時(shí),也把進(jìn)程間控制信息的交換稱為低級(jí)通信,而把進(jìn)程間大批量數(shù)據(jù)的交換稱為高級(jí)通信。 目前,計(jì)算機(jī)系統(tǒng)中用得比較普遍的高級(jí)通信機(jī)制可分為3大類:共享存儲(chǔ)器系統(tǒng)、消息傳遞系統(tǒng)及管道通信系統(tǒng)。 ? 共享存儲(chǔ)器系統(tǒng) 共享存儲(chǔ)器系統(tǒng)為了傳送大量數(shù)據(jù),在存儲(chǔ)器中劃出一塊共享存儲(chǔ)區(qū),諸進(jìn)程可通過(guò)對(duì)共享存儲(chǔ)區(qū)進(jìn)行讀數(shù)據(jù)或?qū)憯?shù)據(jù)以實(shí)現(xiàn)通信。進(jìn)程在通信之前,向系統(tǒng)申請(qǐng)共享存儲(chǔ)區(qū)中的一個(gè)分區(qū),并為它指定一個(gè)分區(qū)關(guān)鍵字。信息的交換稱為低級(jí)通信,而把進(jìn)程間大批量數(shù)據(jù)的交換稱為高級(jí)通信。 目前,計(jì)算機(jī)系統(tǒng)中用得比較普遍的高級(jí)通信機(jī)制可分為3大類:共享存儲(chǔ)器系統(tǒng)、消息傳遞系統(tǒng)及管道通信系統(tǒng)。 ? 消息傳遞系統(tǒng) 在消息傳遞系統(tǒng)中,進(jìn)程間的數(shù)據(jù)交換以消息為單位,在計(jì)算機(jī)網(wǎng)絡(luò)中被稱為報(bào)文。消息傳遞系統(tǒng)的實(shí)現(xiàn)方式又可以分為以下兩種:(1)直接通信方式 發(fā)送進(jìn)程可將消息直接發(fā)送給接收進(jìn)程,即將消息掛在接收進(jìn)程的消息緩沖隊(duì)列上,而接收進(jìn)程可從自己的消息緩沖隊(duì)列中取得消息。(2)間接通信方式 發(fā)送進(jìn)程將消息發(fā)送到指定的信箱中,而接收進(jìn)程從信箱中取得消息。這種通信方式又稱信箱通信方式,被廣泛地應(yīng)用于計(jì)算機(jī)網(wǎng)絡(luò)中。相應(yīng)地,該消息傳遞系統(tǒng)被稱為電子郵件系統(tǒng)。 ? 管道通信系統(tǒng) 向管道提供輸入的發(fā)送進(jìn)程,以字符流方式將大量的數(shù)據(jù)送入管道,而接收進(jìn)程從管道中接收數(shù)據(jù)。由于發(fā)送進(jìn)程和接收進(jìn)程是利用管道進(jìn)行通信的,故稱為管道通信。為了協(xié)調(diào)發(fā)送和接收雙方的通信,管道通信機(jī)制必須提供以下3方面的協(xié)調(diào)功能。(1)互斥 當(dāng)一個(gè)進(jìn)程正在對(duì)pipe文件進(jìn)行讀或?qū)懖僮鲿r(shí),另一個(gè)進(jìn)程必須等待。(2)同步 當(dāng)寫進(jìn)程把一定數(shù)量的數(shù)據(jù)寫入pipe文件后,便阻塞等待,直到讀進(jìn)程取走數(shù)據(jù)后,再把寫進(jìn)程喚醒。 (3)確認(rèn)對(duì)方是否存在 只有確定對(duì)方已存在時(shí),才能進(jìn)行管道通信,否則會(huì)造成因?qū)Ψ讲淮嬖诙鵁o(wú)限制地等待。在這個(gè)問題當(dāng)中,我們采用信號(hào)量機(jī)制進(jìn)行進(jìn)程之間的通信,設(shè)置兩個(gè)信號(hào)量,空的信號(hào)量和滿的信號(hào)量。在Linux系統(tǒng)中,一個(gè)或多個(gè)信號(hào)量構(gòu)成一個(gè)信號(hào)量集合。使用信號(hào)量機(jī)制可以實(shí)現(xiàn)進(jìn)程之間的同步和互斥,允許并發(fā)進(jìn)程一次對(duì)一組信號(hào)量進(jìn)行相同或不同的操作。每個(gè)P、V操作不限于減1或加1,而是可以加減任何整數(shù)。在進(jìn)程終止時(shí),系統(tǒng)可根據(jù)需要自動(dòng)消除所有被進(jìn)程操作過(guò)的信號(hào)量的影響 1.緩沖區(qū)采用循環(huán)隊(duì)列表示,利用頭、尾指針來(lái)存放、讀取數(shù)據(jù),以及判斷隊(duì)列是否為空。緩沖區(qū)中數(shù)組大小為10; 2.利用隨機(jī)函數(shù)rand()得到A~Z的一個(gè)隨機(jī)字符,作為生產(chǎn)者每次生產(chǎn)的數(shù)據(jù),存放到緩沖區(qū)中; 3.使用shmget()系統(tǒng)調(diào)用實(shí)現(xiàn)共享主存段的創(chuàng)建,shmget()返回共享內(nèi)存區(qū)的ID。對(duì)于已經(jīng)申請(qǐng)到的共享段,進(jìn)程需把它附加到自己的虛擬空間中才能對(duì)其進(jìn)行讀寫。 4.信號(hào)量的建立采用semget()函數(shù),同時(shí)建立信號(hào)量的數(shù)量。在信號(hào)量建立后,調(diào)用semctl()對(duì)信號(hào)量進(jìn)行初始化,例如本實(shí)習(xí)中,可以建立兩個(gè)信號(hào)量SEM_EMPTY、SEM_FULL,初始化時(shí)設(shè)置SEM_EMPTY為10,SEM_FULL為0。使用操 作信號(hào)的函數(shù)semop()做排除式操作,使用這個(gè)函數(shù)防止對(duì)共享內(nèi)存的同時(shí)操作。對(duì)共享內(nèi)存操作完畢后采用shmctl()函數(shù)撤銷共享內(nèi)存段。 5.使用循環(huán),創(chuàng)建2個(gè)生產(chǎn)者以及2個(gè)消費(fèi)者,采用函數(shù)fork()創(chuàng)建一個(gè)新的進(jìn)程。6.一個(gè)進(jìn)程的一次操作完成后,采用函數(shù)fflush()刷新緩沖區(qū)。7.程序最后使用semctl()函數(shù)釋放內(nèi)存。模擬程序的程序流程圖如下所示: 1.主程序流程圖: 2.生產(chǎn)者進(jìn)程流程圖 3.消費(fèi)者進(jìn)程流程圖 4.P操作流程圖 5.V操作流程圖 四、實(shí)現(xiàn)代碼為: // exet5.cpp //#include “stdafx.h” #include = {7,10,1,2,10,3,10,4,2,3,10,3,2,1,2,10,1,7,10,1};void build();void LRU(); int main(intargc, char *argv[]){ printf(“Random sequence is as follows:n”);build();printf(“nInvoking LRU Algorithn: n”);LRU();return 0;} void build(){ inti = 0;for(i=0;i { process[i] =(int)(10.0*rand()/(RAND_MAX));printf(“%d ”,process[i]); } printf(“n”);} void LRU(){ int flag[mSIZE] = {0};inti = 0, j = 0;int m =-1, n =-1;int max =-1,maxflag = 0;int count = 0;for(i = 0;i //Find the first free Physical Block for(j=0;j { if(memery[j] == 0) { m = j;break; } } //Find if there are same processes for(j = 0;j { if(memery[j] == process[i]) { n = j; } } //Find free PB for(j = 0;j { if(flag[j]>maxflag) { maxflag = flag[j];max = j; } } if(n ==-1)// Find no same process { if(m!=-1)// find free PB { memery[m] = process[i];flag[m] = 0;for(j = 0;j <= m;j++) { flag[j]++; } m =-1; } else //NO find free PB { memery[max] = process[i];flag[max] = 0; for(j = 0;j { flag[j]++; } max =-1;maxflag = 0;count++; } } else // Find same process { memery[n] = process[i];flag[n] = 0;if(m!=-1)//find free PB { flag[m] = 0; } for(j = 0;j { flag[j]++; } max =-1;maxflag = 0; n =-1; } for(j = 0;j { printf(“%d ”,memery[j]); } printf(“n”);} printf(“nThe is: %dn”,count);} times of page conversion 五、在虛擬機(jī)上的具體操作及結(jié)果 執(zhí)行exe5.c文件 選擇Applications?Acecessories?Terminal,執(zhí)行文件: 依次預(yù)處理?編譯?匯編?連接?執(zhí)行用文件,編譯通過(guò)之后-o執(zhí)行。報(bào)錯(cuò)!!錯(cuò)誤顯示為很多頭文件沒有預(yù)定義。連續(xù)查找之后得知原因是鏈接不上pthread庫(kù) 在執(zhí)行命令后面加上-pthread,即新命令格式為:gcc-oexe5exe5.c–lpthread,重新執(zhí)行后的結(jié)果顯示如下截圖: 其中1表示緩沖區(qū)被生產(chǎn)者producer1或者二producer2寫入了Item,0表示沒有寫入數(shù)據(jù)或者被消費(fèi)者consumer1或者consumer2消耗掉 六、實(shí)驗(yàn)總結(jié)及思考 1、本次實(shí)驗(yàn)是關(guān)于生產(chǎn)者與消費(fèi)者之間互斥和同步的問題。問題的是指是P、V操作,實(shí)驗(yàn)設(shè)一個(gè)共享緩沖區(qū),生產(chǎn)者和消費(fèi)者互斥的使用,當(dāng)一個(gè)線程使用緩沖區(qū)的時(shí)候,另一個(gè)讓其等待直到前一個(gè)線程釋放緩沖區(qū)為止。 2、實(shí)驗(yàn)中包含的知識(shí)點(diǎn)很多,包括臨界區(qū)資源共享問題、信號(hào)量定義、PV操作流程、進(jìn)程間的通信方式(消息傳遞和共享內(nèi)存)、進(jìn)程同步和互斥、信號(hào)量機(jī)制解決進(jìn)程之間的同步與互斥問題等等。加深了對(duì)于本部分內(nèi)容的理解 通過(guò)本實(shí)驗(yàn)設(shè)計(jì),我們對(duì)操作系統(tǒng)的P、V進(jìn)一步的認(rèn)識(shí),深入的了解P、V操作的實(shí)質(zhì)和其重要性。課本的理論知識(shí)進(jìn)一步闡述了現(xiàn)實(shí)中的實(shí)際問題。 臨界區(qū)管理實(shí)現(xiàn) 本組組員:周琪皓,董泉偉,鐘佳鋒,張倬慎 0 引言 隨著多處理機(jī)體系結(jié)構(gòu)的演變和分布式與并行系統(tǒng)的發(fā)展,并發(fā)多任務(wù)的程序設(shè)計(jì)技術(shù)已愈來(lái)愈顯得重要,多線程設(shè)計(jì)模式在這些技術(shù)的發(fā)展中起著重要作用。在現(xiàn)代操作系統(tǒng)中,利用進(jìn)(線)程間的并發(fā)性實(shí)現(xiàn)程序中并發(fā)成分的并行執(zhí)行,可大大提高系統(tǒng)的處理能力和效率,但也可能帶來(lái)諸如執(zhí)行結(jié)果的不確定性等不良現(xiàn)象,因此并發(fā)系統(tǒng)中處理好進(jìn)(線)程間的互斥與同步就顯得至關(guān)重要。C++語(yǔ)言中的多線程機(jī)制是解決線程間的互斥與同步問題的重要工具,其應(yīng)用(如網(wǎng)絡(luò)多媒體應(yīng)用、工業(yè)自動(dòng)化控制等)很廣泛,很復(fù)雜且常易出錯(cuò)。因此在應(yīng)用程序設(shè)計(jì)過(guò)程中,要考慮多個(gè)線程如何同步使用進(jìn)程的共享資源,如何讓一個(gè)線程與另一個(gè)線程協(xié)調(diào)合作,以免產(chǎn)生線程間的訪問沖突。語(yǔ)言提供的多線程機(jī)制能有避免同一共享互斥資源被多個(gè)線程同時(shí)訪問,維護(hù)數(shù)據(jù)的一致性、安全性。生產(chǎn)者/消費(fèi)者問題可作為并發(fā)進(jìn)程的同步和互斥問題的一個(gè)抽象模型,廣泛應(yīng)用于通信和控制系統(tǒng)中。本文基于C++語(yǔ)言中的多線程機(jī)制,實(shí)現(xiàn)操作系統(tǒng)中生產(chǎn)者/消費(fèi)者問題,以助人們更好地透解同步概念及其實(shí)現(xiàn)方法。1 課程設(shè)計(jì)目的 通過(guò)模擬操作者生產(chǎn)者經(jīng)典問題的實(shí)現(xiàn),以及關(guān)于信號(hào)量和互斥鎖對(duì)于多線程的運(yùn)用,深入理解操作系統(tǒng)中多線程同步法的理論知識(shí), 加深對(duì)教材中的重要算法的理解。同時(shí)通過(guò)編程實(shí)現(xiàn)這些算法,更好地掌握操作系統(tǒng)的原理及實(shí)現(xiàn)方法,提高綜合運(yùn)用各專業(yè)課知識(shí)的能力。2 課程設(shè)計(jì)題目和要求 2.1 課程設(shè)計(jì)題目 題目: 臨界區(qū)管理實(shí)現(xiàn).2.2課程設(shè)計(jì)目的與要求 初始條件: 1.操作系統(tǒng):Windows 2.程序設(shè)計(jì)語(yǔ)言:C++語(yǔ)言 3.有界緩沖區(qū)內(nèi)設(shè)有20個(gè)存儲(chǔ)單元,其初值為0。放入/取出的數(shù)據(jù)項(xiàng)按增序設(shè)定為1-20這20個(gè)整型數(shù)。 技術(shù)要求: 1、生產(chǎn)者和消費(fèi)者各有兩個(gè)以上。多個(gè)生產(chǎn)者或 多個(gè)消費(fèi)者之間須有共享對(duì)緩沖區(qū)進(jìn)行操作 的函數(shù)代碼。每個(gè)生產(chǎn)者和消費(fèi)者對(duì)有界緩沖 區(qū)進(jìn)行操作后,即時(shí)顯示有界緩沖區(qū)的全部?jī)?nèi) 容,當(dāng)前指針位置。 2、編寫多線程同步方法解決生產(chǎn)者-消費(fèi)者的程 序,并完成對(duì)進(jìn)程進(jìn)行模擬同步和互斥的控制。2 設(shè)計(jì)總體思路 2.1 多線程編程思想 編寫Windows下的多線程程序,需要使用頭文件pthread.h以及windows.h.在LINUX下進(jìn)行多線程編程首先要用到CreateThread()這個(gè)函數(shù).函數(shù)CreateThread()用來(lái)創(chuàng)建一個(gè)線程,它的原型為: HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes DWORD dwStackSize, // initial thread stack size LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function LPVOID lpParameter, // argument for new thread DWORD dwCreationFlags, // creation flags LPDWORD lpThreadId);// pointer to receive thread ID 第一個(gè)參數(shù)是指向SECURITY_ATTRIBUTES型態(tài)的結(jié)構(gòu)的指針。在Windows 98中忽略該參數(shù)。在Windows NT中,它被設(shè)為NULL。第二個(gè)參數(shù)是用于新線程的初始堆棧大小,默認(rèn)值為0。在任何情況下,Windows根據(jù)需要?jiǎng)討B(tài)延長(zhǎng)堆棧的大小。第三個(gè)參數(shù)是指向線程函數(shù)的指標(biāo)。函數(shù)名稱沒有限制,但是必須以下列形式聲明: DWORD WINAPI ThreadProc(PVOID pParam);第四個(gè)參數(shù)為傳遞給ThreadProc的參數(shù)。這樣主線程和從屬線程就可以共享數(shù)據(jù)。第五個(gè)參數(shù)通常為0,但當(dāng)建立的線程不馬上執(zhí)行時(shí)為旗標(biāo)CREATE_SUSPENDED。線程將暫停直到呼叫ResumeThread來(lái)恢復(fù)線程的執(zhí)行為止。第六個(gè)參數(shù)是一個(gè)指標(biāo),指向接受執(zhí)行緒ID值的變量。2.1.1線程數(shù)據(jù) 在單線程的程序里,有兩種基本的數(shù)據(jù):全局變量和局部變量。但在多線程程序里,還有第三種數(shù)據(jù)類型:線程數(shù)據(jù)。它和全局變量很象,在線程內(nèi)部,各個(gè)函數(shù)可以象使用全局變量一樣調(diào)用它,但它對(duì)線程外部的其它線程是不可見的。這種數(shù)據(jù)的必要性是顯而易見的。例如我們常見的變量errno,它返回標(biāo)準(zhǔn)的出錯(cuò)信息。它顯然不能是一個(gè)局部變量,幾乎每個(gè)函數(shù)都應(yīng)該可以調(diào)用它;但它又不能是一個(gè)全局變量,否則在A線程里輸出的很可能是B線程的出錯(cuò)信息。ThreadHandle[0]=CreateThread(NULL,0,Producer,NULL,0,&producer1)其六個(gè)參數(shù)分別表示為安全設(shè)置,堆棧大小,入口函數(shù),函數(shù)參數(shù),啟動(dòng)選項(xiàng),輸出線程 ID,返回線程句柄。2.1.2 互斥鎖 互斥鎖用來(lái)保證一段時(shí)間內(nèi)只有一個(gè)線程在執(zhí)行一段代碼,必要性顯而易見:假設(shè)各個(gè)線程向同一個(gè)文件順序?qū)懭霐?shù)據(jù),最后得到的結(jié)果一定是災(zāi)難性的.函數(shù)mutex = CreateMutex(NULL,FALSE,NULL);用來(lái)生成一個(gè)互斥鎖.NULL參數(shù)表明使用默認(rèn)屬性.如果需要聲明特定屬性的互斥鎖,須調(diào)用函數(shù) CreateMutex(NULL,FALSE,NULL) WaitForSingleObject(mutex,INFINITE)聲明開始用互斥鎖上鎖,直至調(diào)用ReleaseMutex(mutex)為止,均被上鎖,即同一時(shí)間只能被一個(gè)線程調(diào)用執(zhí)行.當(dāng)一個(gè)線程執(zhí)行到pthread_mutex_lock處時(shí),如果該鎖此時(shí)被另一個(gè)線程使用,那么此線程被阻塞,即程序?qū)⒌却搅硪粋€(gè)線程釋放此互斥鎖.2.1.3 信號(hào)量 信號(hào)量本質(zhì)上是一個(gè)非負(fù)的整數(shù)計(jì)數(shù)器,它被用來(lái)控制對(duì)公共資源的訪問。當(dāng)公共資源增加時(shí),調(diào)用函數(shù)aitForSingleObject(empty,INFINITE)增加信號(hào)量。只有當(dāng)信號(hào)量值大于0時(shí),才能使用公共資源,使用后,函數(shù)WaitForSingleObject(full,INFINITE)減少信號(hào)量。 函數(shù) ReleaseSemaphore(full,1,NULL)用來(lái)增加信號(hào)量的值。當(dāng)有線程阻塞在這個(gè)信號(hào)量上時(shí),調(diào)用這個(gè)函數(shù)會(huì)使其中的一個(gè)線程不在阻塞,選擇機(jī)制同樣是由線程的調(diào)度策略決定的。函數(shù)ReleaseSemaphor()用來(lái)釋放信號(hào)量。2.2 設(shè)計(jì)原理 生產(chǎn)者線程和消費(fèi)者線程共享同一個(gè)緩沖隊(duì)列,生產(chǎn)者線程向緩沖區(qū)中寫數(shù)據(jù),消費(fèi)者線程從緩沖區(qū)中取數(shù)據(jù)。但兩者必須在使用緩沖隊(duì)列資源時(shí)保持互斥,否則可能會(huì)導(dǎo)致在寫入時(shí)產(chǎn)生數(shù)據(jù)覆蓋,在讀出時(shí)得到錯(cuò)誤數(shù)據(jù)。因而要在程序中設(shè)置一個(gè)互斥鎖或公用信號(hào)量,用于保證線程間的互斥執(zhí)行。同時(shí)生產(chǎn)者線程和消費(fèi)者線程必須保持同步關(guān)系,因?yàn)樯a(chǎn)者線程的執(zhí)行為消費(fèi)者線程提供了需要的數(shù)據(jù),是其執(zhí)行的前提。反之,消費(fèi)者線程的執(zhí)行為生產(chǎn)者線程騰出了空閑的緩沖單元,為寫數(shù)據(jù)提供了條件。即消費(fèi)者線程執(zhí)行的前提:緩沖隊(duì)列中至少有一個(gè)單元有數(shù)據(jù);生產(chǎn)者線程執(zhí)行的前提:緩沖隊(duì)列中至少有一個(gè)單元是空的。在設(shè)計(jì)過(guò)程中,利用信號(hào)量和wait、signal原語(yǔ)操作來(lái)實(shí)現(xiàn)。如圖1所示: 圖1 生產(chǎn)者、消費(fèi)者共享有界緩沖區(qū) 2.3 原語(yǔ)操作實(shí)現(xiàn) The structure of the producer process do { // 生產(chǎn)產(chǎn)品 wait(empty);wait(mutex);// 往Buffer中放入產(chǎn)品 signal(mutex);signal(full);} while(true);The structure of the consumer process do { wait(full);wait(mutex);// 從Buffer中取出產(chǎn)品 signal(mutex);signal(empty);// 消費(fèi)產(chǎn)品 } while(true);3 開發(fā)環(huán)境與工具 系統(tǒng)平臺(tái):Windows環(huán)境 實(shí)現(xiàn)語(yǔ)言:C++語(yǔ)言 開發(fā)工具:Vs2012 4 概要設(shè)計(jì) 4.1 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì) 通過(guò)分析課程設(shè)計(jì)要求,具體設(shè)計(jì)出如下數(shù)據(jù)結(jié)構(gòu): 1.int buffer[20]={0};//定義緩沖區(qū)空間大小 2.包含數(shù)據(jù)結(jié)構(gòu)pthread_t 它記錄一個(gè)線程的號(hào),主要包括下面幾個(gè)函數(shù),完成不同的功能: ThreadHandle[0]=CreateThread(NULL,0,Producer,NULL,0,&producer1);//創(chuàng)建一個(gè)線程。ExitThread(0);CloseHandle(ThreadHandle[0]);//等待一個(gè)線程結(jié)束。4.2 程序模塊實(shí)現(xiàn) 4.2.1 生產(chǎn)者(Producer)模塊 生產(chǎn)者線程向一緩沖區(qū)中寫入數(shù)據(jù),且寫入緩沖區(qū)的數(shù)目不能超過(guò)緩沖區(qū)容量。當(dāng)生產(chǎn)者產(chǎn)生出數(shù)據(jù),需要將其存入緩沖區(qū)之前,首先檢查緩沖區(qū)中是否有“空”存儲(chǔ)單元,若緩沖區(qū)存儲(chǔ)單元全部用完,則生產(chǎn)者必須阻塞等待,直到消費(fèi)者取走一個(gè)存儲(chǔ)單元的數(shù)據(jù),喚醒它。若緩沖區(qū)內(nèi)有“空”存儲(chǔ)單元,生產(chǎn)者需要判斷此時(shí)是否有別的生產(chǎn)者或消費(fèi)者正在使用緩沖區(qū),若是有,則阻塞等待,否則,獲得緩沖區(qū)的使用權(quán),將數(shù)據(jù)存入緩沖區(qū),釋放緩沖區(qū)的使用權(quán),其流程圖如圖2所示: 生產(chǎn)一條數(shù)據(jù)No是否可用存儲(chǔ)單元等待資源,阻塞Yes被喚醒No是否可用Yes存入一條數(shù)據(jù)等待使用權(quán),阻塞被喚醒歸還使用權(quán)數(shù)據(jù)單元加1,喚醒消費(fèi)者 圖生產(chǎn)者流程圖 //生產(chǎn)者線程 DWORD WINAPI Producer(LPVOID lpPara){ do{ WaitForSingleObject(empty,INFINITE);沖區(qū)減1 WaitForSingleObject(mutex,INFINITE);上鎖 //空緩//信號(hào)量 buffer[in]=in+1;//往Buffer中放入產(chǎn)品 in=(in+1)%BUFFER_SIZE;//放入指針調(diào)整,為下次送出做準(zhǔn)備 printAll();ReleaseMutex(mutex);//信號(hào)量解鎖 ReleaseSemaphore(full,1,NULL);//滿緩沖區(qū)加1,即當(dāng)公共資源增加時(shí),調(diào)用函數(shù)ReleaseSemaphore()增加信號(hào)量 }while(1);} 4.2.2 消費(fèi)者(Consumer)模塊 消費(fèi)者線程從緩沖區(qū)中讀取數(shù)據(jù),且消費(fèi)者讀取的數(shù)目不能超過(guò)生產(chǎn)者寫入的數(shù)目。消費(fèi)者取數(shù)據(jù)之前,首先檢查緩沖區(qū)中是否存在裝有數(shù)據(jù)的存儲(chǔ)單元,若緩沖區(qū)為“空”,則阻塞等待,否則,判斷緩沖區(qū)是否正在被使用,若正被使用,若正被使用,則阻塞等待,否則,獲得緩沖區(qū)的使用權(quán),進(jìn)入緩沖區(qū)取數(shù)據(jù),釋放緩沖區(qū)的使用權(quán)。其執(zhí)行流程如圖3所示: No是否可用存儲(chǔ)單元等待資源,阻塞Yes被喚醒是否可用No等待使用權(quán),阻塞Yes被喚醒取出一條數(shù)據(jù)歸還使用權(quán)空緩沖區(qū)加1,喚醒一個(gè)生產(chǎn)者消費(fèi)數(shù)據(jù) 圖3 消費(fèi)者流程圖 //消費(fèi)者線程 DWORD WINAPI Consumer(LPVOID lpPara){ do{ WaitForSingleObject(full,INFINITE);區(qū)減1 WaitForSingleObject(mutex,INFINITE);量上鎖 //滿緩沖 //信號(hào) buffer[out]=0;//從Buffer中取出產(chǎn)品 out=(out+1)%BUFFER_SIZE;//取指針調(diào)整,為下次取做準(zhǔn)備 printAll();ReleaseMutex(mutex);//信號(hào)量解鎖 ReleaseSemaphore(empty,1,NULL);//空緩沖區(qū)加1 }while(1);} 5 詳細(xì)設(shè)計(jì) 5.1 源程序代碼 #include #include 進(jìn)入Windows開發(fā)環(huán)境后,通過(guò)Vs2012編輯器在其中編寫。進(jìn)入Vs2012的命令,對(duì)程序執(zhí)行編譯運(yùn)行命令后,即可在屏幕上顯示出程序運(yùn)行的結(jié)果,其運(yùn)行結(jié)果如下圖5所示: 總結(jié) 其實(shí)在做這道題目時(shí)花費(fèi)了好長(zhǎng)時(shí)間,第一點(diǎn)是書上大多介紹的是關(guān)于UNIX系統(tǒng)下的消費(fèi)者生產(chǎn)者線程問題,因此一開始調(diào)試不出來(lái),后來(lái)查閱了有一些資料知道要在windows平臺(tái)下運(yùn)行必須要導(dǎo)入 以及第二篇:操作系統(tǒng)課程設(shè)計(jì)生產(chǎn)者消費(fèi)者
第三篇:操作系統(tǒng)實(shí)驗(yàn)報(bào)告經(jīng)典生產(chǎn)者—消費(fèi)者問題
第四篇:實(shí)驗(yàn)報(bào)告五 生產(chǎn)者和消費(fèi)者問題
第五篇:操作系統(tǒng)課程設(shè)計(jì)__用多線程同步方法解決生產(chǎn)者