第一篇:操作系統(tǒng)課程設(shè)計__用多線程同步方法解決生產(chǎn)者
臨界區(qū)管理實現(xiàn) 本組組員:周琪皓,董泉偉,鐘佳鋒,張倬慎 0 引言 隨著多處理機體系結(jié)構(gòu)的演變和分布式與并行系統(tǒng)的發(fā)展,并發(fā)多任務(wù)的程序設(shè)計技術(shù)已愈來愈顯得重要,多線程設(shè)計模式在這些技術(shù)的發(fā)展中起著重要作用。在現(xiàn)代操作系統(tǒng)中,利用進(線)程間的并發(fā)性實現(xiàn)程序中并發(fā)成分的并行執(zhí)行,可大大提高系統(tǒng)的處理能力和效率,但也可能帶來諸如執(zhí)行結(jié)果的不確定性等不良現(xiàn)象,因此并發(fā)系統(tǒng)中處理好進(線)程間的互斥與同步就顯得至關(guān)重要。C++語言中的多線程機制是解決線程間的互斥與同步問題的重要工具,其應(yīng)用(如網(wǎng)絡(luò)多媒體應(yīng)用、工業(yè)自動化控制等)很廣泛,很復(fù)雜且常易出錯。因此在應(yīng)用程序設(shè)計過程中,要考慮多個線程如何同步使用進程的共享資源,如何讓一個線程與另一個線程協(xié)調(diào)合作,以免產(chǎn)生線程間的訪問沖突。語言提供的多線程機制能有避免同一共享互斥資源被多個線程同時訪問,維護數(shù)據(jù)的一致性、安全性。生產(chǎn)者/消費者問題可作為并發(fā)進程的同步和互斥問題的一個抽象模型,廣泛應(yīng)用于通信和控制系統(tǒng)中。本文基于C++語言中的多線程機制,實現(xiàn)操作系統(tǒng)中生產(chǎn)者/消費者問題,以助人們更好地透解同步概念及其實現(xiàn)方法。1 課程設(shè)計目的 通過模擬操作者生產(chǎn)者經(jīng)典問題的實現(xiàn),以及關(guān)于信號量和互斥鎖對于多線程的運用,深入理解操作系統(tǒng)中多線程同步法的理論知識, 加深對教材中的重要算法的理解。同時通過編程實現(xiàn)這些算法,更好地掌握操作系統(tǒng)的原理及實現(xiàn)方法,提高綜合運用各專業(yè)課知識的能力。2 課程設(shè)計題目和要求 2.1 課程設(shè)計題目 題目: 臨界區(qū)管理實現(xiàn).2.2課程設(shè)計目的與要求 初始條件:
1.操作系統(tǒng):Windows 2.程序設(shè)計語言:C++語言
3.有界緩沖區(qū)內(nèi)設(shè)有20個存儲單元,其初值為0。放入/取出的數(shù)據(jù)項按增序設(shè)定為1-20這20個整型數(shù)。
技術(shù)要求:
1、生產(chǎn)者和消費者各有兩個以上。多個生產(chǎn)者或 多個消費者之間須有共享對緩沖區(qū)進行操作 的函數(shù)代碼。每個生產(chǎn)者和消費者對有界緩沖 區(qū)進行操作后,即時顯示有界緩沖區(qū)的全部內(nèi) 容,當前指針位置。
2、編寫多線程同步方法解決生產(chǎn)者-消費者的程 序,并完成對進程進行模擬同步和互斥的控制。2 設(shè)計總體思路 2.1 多線程編程思想 編寫Windows下的多線程程序,需要使用頭文件pthread.h以及windows.h.在LINUX下進行多線程編程首先要用到CreateThread()這個函數(shù).函數(shù)CreateThread()用來創(chuàng)建一個線程,它的原型為:
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 第一個參數(shù)是指向SECURITY_ATTRIBUTES型態(tài)的結(jié)構(gòu)的指針。在Windows 98中忽略該參數(shù)。在Windows NT中,它被設(shè)為NULL。第二個參數(shù)是用于新線程的初始堆棧大小,默認值為0。在任何情況下,Windows根據(jù)需要動態(tài)延長堆棧的大小。第三個參數(shù)是指向線程函數(shù)的指標。函數(shù)名稱沒有限制,但是必須以下列形式聲明: DWORD WINAPI ThreadProc(PVOID pParam);第四個參數(shù)為傳遞給ThreadProc的參數(shù)。這樣主線程和從屬線程就可以共享數(shù)據(jù)。第五個參數(shù)通常為0,但當建立的線程不馬上執(zhí)行時為旗標CREATE_SUSPENDED。線程將暫停直到呼叫ResumeThread來恢復(fù)線程的執(zhí)行為止。第六個參數(shù)是一個指標,指向接受執(zhí)行緒ID值的變量。2.1.1線程數(shù)據(jù) 在單線程的程序里,有兩種基本的數(shù)據(jù):全局變量和局部變量。但在多線程程序里,還有第三種數(shù)據(jù)類型:線程數(shù)據(jù)。它和全局變量很象,在線程內(nèi)部,各個函數(shù)可以象使用全局變量一樣調(diào)用它,但它對線程外部的其它線程是不可見的。這種數(shù)據(jù)的必要性是顯而易見的。例如我們常見的變量errno,它返回標準的出錯信息。它顯然不能是一個局部變量,幾乎每個函數(shù)都應(yīng)該可以調(diào)用它;但它又不能是一個全局變量,否則在A線程里輸出的很可能是B線程的出錯信息。ThreadHandle[0]=CreateThread(NULL,0,Producer,NULL,0,&producer1)其六個參數(shù)分別表示為安全設(shè)置,堆棧大小,入口函數(shù),函數(shù)參數(shù),啟動選項,輸出線程 ID,返回線程句柄。2.1.2 互斥鎖 互斥鎖用來保證一段時間內(nèi)只有一個線程在執(zhí)行一段代碼,必要性顯而易見:假設(shè)各個線程向同一個文件順序?qū)懭霐?shù)據(jù),最后得到的結(jié)果一定是災(zāi)難性的.函數(shù)mutex = CreateMutex(NULL,FALSE,NULL);用來生成一個互斥鎖.NULL參數(shù)表明使用默認屬性.如果需要聲明特定屬性的互斥鎖,須調(diào)用函數(shù)
CreateMutex(NULL,FALSE,NULL)
WaitForSingleObject(mutex,INFINITE)聲明開始用互斥鎖上鎖,直至調(diào)用ReleaseMutex(mutex)為止,均被上鎖,即同一時間只能被一個線程調(diào)用執(zhí)行.當一個線程執(zhí)行到pthread_mutex_lock處時,如果該鎖此時被另一個線程使用,那么此線程被阻塞,即程序?qū)⒌却搅硪粋€線程釋放此互斥鎖.2.1.3 信號量 信號量本質(zhì)上是一個非負的整數(shù)計數(shù)器,它被用來控制對公共資源的訪問。當公共資源增加時,調(diào)用函數(shù)aitForSingleObject(empty,INFINITE)增加信號量。只有當信號量值大于0時,才能使用公共資源,使用后,函數(shù)WaitForSingleObject(full,INFINITE)減少信號量。
函數(shù) ReleaseSemaphore(full,1,NULL)用來增加信號量的值。當有線程阻塞在這個信號量上時,調(diào)用這個函數(shù)會使其中的一個線程不在阻塞,選擇機制同樣是由線程的調(diào)度策略決定的。函數(shù)ReleaseSemaphor()用來釋放信號量。2.2 設(shè)計原理 生產(chǎn)者線程和消費者線程共享同一個緩沖隊列,生產(chǎn)者線程向緩沖區(qū)中寫數(shù)據(jù),消費者線程從緩沖區(qū)中取數(shù)據(jù)。但兩者必須在使用緩沖隊列資源時保持互斥,否則可能會導(dǎo)致在寫入時產(chǎn)生數(shù)據(jù)覆蓋,在讀出時得到錯誤數(shù)據(jù)。因而要在程序中設(shè)置一個互斥鎖或公用信號量,用于保證線程間的互斥執(zhí)行。同時生產(chǎn)者線程和消費者線程必須保持同步關(guān)系,因為生產(chǎn)者線程的執(zhí)行為消費者線程提供了需要的數(shù)據(jù),是其執(zhí)行的前提。反之,消費者線程的執(zhí)行為生產(chǎn)者線程騰出了空閑的緩沖單元,為寫數(shù)據(jù)提供了條件。即消費者線程執(zhí)行的前提:緩沖隊列中至少有一個單元有數(shù)據(jù);生產(chǎn)者線程執(zhí)行的前提:緩沖隊列中至少有一個單元是空的。在設(shè)計過程中,利用信號量和wait、signal原語操作來實現(xiàn)。如圖1所示:
圖1 生產(chǎn)者、消費者共享有界緩沖區(qū)
2.3 原語操作實現(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);// 消費產(chǎn)品 } while(true);3 開發(fā)環(huán)境與工具 系統(tǒng)平臺:Windows環(huán)境 實現(xiàn)語言:C++語言 開發(fā)工具:Vs2012 4 概要設(shè)計 4.1 數(shù)據(jù)結(jié)構(gòu)設(shè)計 通過分析課程設(shè)計要求,具體設(shè)計出如下數(shù)據(jù)結(jié)構(gòu): 1.int buffer[20]={0};//定義緩沖區(qū)空間大小 2.包含數(shù)據(jù)結(jié)構(gòu)pthread_t 它記錄一個線程的號,主要包括下面幾個函數(shù),完成不同的功能: ThreadHandle[0]=CreateThread(NULL,0,Producer,NULL,0,&producer1);//創(chuàng)建一個線程。ExitThread(0);CloseHandle(ThreadHandle[0]);//等待一個線程結(jié)束。4.2 程序模塊實現(xiàn) 4.2.1 生產(chǎn)者(Producer)模塊 生產(chǎn)者線程向一緩沖區(qū)中寫入數(shù)據(jù),且寫入緩沖區(qū)的數(shù)目不能超過緩沖區(qū)容量。當生產(chǎn)者產(chǎn)生出數(shù)據(jù),需要將其存入緩沖區(qū)之前,首先檢查緩沖區(qū)中是否有“空”存儲單元,若緩沖區(qū)存儲單元全部用完,則生產(chǎn)者必須阻塞等待,直到消費者取走一個存儲單元的數(shù)據(jù),喚醒它。若緩沖區(qū)內(nèi)有“空”存儲單元,生產(chǎn)者需要判斷此時是否有別的生產(chǎn)者或消費者正在使用緩沖區(qū),若是有,則阻塞等待,否則,獲得緩沖區(qū)的使用權(quán),將數(shù)據(jù)存入緩沖區(qū),釋放緩沖區(qū)的使用權(quán),其流程圖如圖2所示: 生產(chǎn)一條數(shù)據(jù)No是否可用存儲單元等待資源,阻塞Yes被喚醒No是否可用Yes存入一條數(shù)據(jù)等待使用權(quán),阻塞被喚醒歸還使用權(quán)數(shù)據(jù)單元加1,喚醒消費者 圖生產(chǎn)者流程圖
//生產(chǎn)者線程 DWORD WINAPI Producer(LPVOID lpPara){ do{ WaitForSingleObject(empty,INFINITE);沖區(qū)減1 WaitForSingleObject(mutex,INFINITE);上鎖 //空緩//信號量 buffer[in]=in+1;//往Buffer中放入產(chǎn)品 in=(in+1)%BUFFER_SIZE;//放入指針調(diào)整,為下次送出做準備 printAll();ReleaseMutex(mutex);//信號量解鎖 ReleaseSemaphore(full,1,NULL);//滿緩沖區(qū)加1,即當公共資源增加時,調(diào)用函數(shù)ReleaseSemaphore()增加信號量 }while(1);}
4.2.2 消費者(Consumer)模塊 消費者線程從緩沖區(qū)中讀取數(shù)據(jù),且消費者讀取的數(shù)目不能超過生產(chǎn)者寫入的數(shù)目。消費者取數(shù)據(jù)之前,首先檢查緩沖區(qū)中是否存在裝有數(shù)據(jù)的存儲單元,若緩沖區(qū)為“空”,則阻塞等待,否則,判斷緩沖區(qū)是否正在被使用,若正被使用,若正被使用,則阻塞等待,否則,獲得緩沖區(qū)的使用權(quán),進入緩沖區(qū)取數(shù)據(jù),釋放緩沖區(qū)的使用權(quán)。其執(zhí)行流程如圖3所示:
No是否可用存儲單元等待資源,阻塞Yes被喚醒是否可用No等待使用權(quán),阻塞Yes被喚醒取出一條數(shù)據(jù)歸還使用權(quán)空緩沖區(qū)加1,喚醒一個生產(chǎn)者消費數(shù)據(jù) 圖3 消費者流程圖 //消費者線程 DWORD WINAPI Consumer(LPVOID lpPara){ do{ WaitForSingleObject(full,INFINITE);區(qū)減1 WaitForSingleObject(mutex,INFINITE);量上鎖 //滿緩沖 //信號 buffer[out]=0;//從Buffer中取出產(chǎn)品 out=(out+1)%BUFFER_SIZE;//取指針調(diào)整,為下次取做準備 printAll();ReleaseMutex(mutex);//信號量解鎖 ReleaseSemaphore(empty,1,NULL);//空緩沖區(qū)加1 }while(1);} 5 詳細設(shè)計 5.1 源程序代碼 #include #include 進入Windows開發(fā)環(huán)境后,通過Vs2012編輯器在其中編寫。進入Vs2012的命令,對程序執(zhí)行編譯運行命令后,即可在屏幕上顯示出程序運行的結(jié)果,其運行結(jié)果如下圖5所示: 總結(jié) 其實在做這道題目時花費了好長時間,第一點是書上大多介紹的是關(guān)于UNIX系統(tǒng)下的消費者生產(chǎn)者線程問題,因此一開始調(diào)試不出來,后來查閱了有一些資料知道要在windows平臺下運行必須要導(dǎo)入 以及 題目: 用多線程同步方法解決睡眠理發(fā)師問題(Sleeping-Barber Problem)初始條件: 1.操作系統(tǒng):Linux 2.程序設(shè)計語言:C語言 3.設(shè)有一個理發(fā)師,5把椅子(另外還有一把理發(fā)椅),幾把椅子可用連續(xù)存儲單元。 要求完成的主要任務(wù):(包括課程設(shè)計工作量及其技術(shù)要求,以及說明書撰寫等具體要求) 1.技術(shù)要求: 1)為每個理發(fā)師/顧客產(chǎn)生一個線程,設(shè)計正確的同步算法 2)每個顧客進入理發(fā)室后,即時顯示“Entered” 及其線程自定義標識,還同時顯示理發(fā)室共有幾名顧客及其所坐的位置。3)至少有10個顧客,每人理發(fā)至少3秒鐘。4)多個顧客須共享操作函數(shù)代碼。 2. 設(shè)計說明書內(nèi)容要求: 1)設(shè)計題目與要求 2)總的設(shè)計思想及系統(tǒng)平臺、語言、工具等。3)數(shù)據(jù)結(jié)構(gòu)與模塊說明(功能與流程圖) 4)給出用戶名、源程序名、目標程序名和源程序及其運行結(jié)果。(要注明存儲各個程序及其運行結(jié)果的主機IP地址和目錄。) 5)運行結(jié)果與運行情況 (提示:(1)連續(xù)存儲區(qū)可用數(shù)組實現(xiàn)。 (2)編譯命令可用: cc-lpthread-o 目標文件名 源文件名(3)多線程編程方法參見附件。) 1設(shè)計題目與要求 1.1 設(shè)計題目 用多線程同步方法解決睡眠理發(fā)師問題(Sleeping-Barber Problem)1.2 設(shè)計要求 1.2.1 初始條件 (1)操作系統(tǒng):Linux(2)程序設(shè)計語言:C語言 (3)設(shè)有一個理發(fā)師,5把椅子(另外還有一把理發(fā)椅),幾把椅子可用連續(xù)存儲單元。 1.2.2 技術(shù)要求 (1)為每個理發(fā)師/顧客產(chǎn)生一個線程,設(shè)計正確的同步算法 (2)每個顧客進入理發(fā)室后,即時顯示“Entered” 及其線程自定義標識,還同時顯示理發(fā)室共有幾名顧客及其所坐的位置。(3)至少有10個顧客,每人理發(fā)至少3秒鐘。(4)多個顧客須共享操作函數(shù)代碼??傮w設(shè)計思想及開發(fā)環(huán)境與工具 2.1 總體設(shè)計思想 題目中要求描述理發(fā)師和顧客的行為,因此需要兩類線程barber()和customer()分別描述理發(fā)師和顧客的行為。其中,理發(fā)師有活動有理發(fā)和睡覺兩個事件;等待和理發(fā)二個事件。店里有固定的椅子數(shù),上面坐著等待的顧客,顧客在到來這個事件時,需判斷有沒有空閑的椅子,理發(fā)師決定要理發(fā)或睡覺時,也要判斷椅子上有沒有顧客。所以,顧客和理 發(fā)師之間的關(guān)系表現(xiàn)為: (1)理發(fā)師和顧客之間同步關(guān)系:當理發(fā)師睡覺時顧客近來需要喚醒理發(fā)師為其理發(fā),當有顧客時理發(fā)師為其理發(fā),沒有的時候理發(fā)師睡覺。 (2)理發(fā)師和顧客之間互斥關(guān)系:由于每次理發(fā)師只能為一個人理發(fā),且可供等侯的椅子有限只有n把,即理發(fā)師和椅子是臨界資源,所以顧客之間是互斥的關(guān)系。(3)故引入3個信號量和一個控制變量: ⅰ控制變量waiting用來記錄等候理發(fā)的顧客數(shù),初值為0; ⅱ信號量customers用來記錄等候理發(fā)的顧客數(shù),并用作阻塞理發(fā)師進程,初值為0; ⅲ信號量barbers用來記錄正在等候顧客的理發(fā)師數(shù),并用作阻塞顧客進程,初值為1; ⅳ信號量mutex用于互斥,初值為1 2.2 多線程編程原理 此次在Linux下進行多線程編程需要用到pthread_create和pthread_join這兩個函數(shù)。 2.2.1 創(chuàng)建一個線程 pthread_create用來創(chuàng)建一個線程,原型為: extern int pthread_create((pthread_t *__thread,__const pthread_attr_t *__attr,void *(*__start_routine)(void *), void *__arg))第一個參數(shù)為指向線程標識符的指針,第二個參數(shù)用來設(shè)置線程屬性,第三個參數(shù)是線程運行函數(shù)的起始地址,最后一個參數(shù)是運行函數(shù)的參數(shù)。函數(shù)thread不需要參數(shù)時,最后一個參數(shù)設(shè)為空指針。第二個參數(shù)設(shè)為空指針時,將生成默認屬性的線程。創(chuàng)建線程成功后,新創(chuàng)建的線程則運行參數(shù)三和參數(shù)四確定的函數(shù),原來的線程則繼續(xù)運行下一行代碼。 2.2.2 等待一個線程結(jié)束 pthread_join用來等待一個線程的結(jié)束,函數(shù)原型為: extern int pthread_join __P((pthread_t __th, void **__thread_return)); 第一個參數(shù)為被等待的線程標識符,第二個參數(shù)為一個用戶定義的指針,它可以用來存 儲被等待線程的返回值。這個函數(shù)是一個線程阻塞的函數(shù),調(diào)用它的函數(shù)將一直等待到被 等待的線程結(jié)束為止,當函數(shù)返回時,被等待線程的資源被收回。 2.2.3 信號量 (1)函數(shù)sem_init()用來初始化一個信號量,函數(shù)原型為: extern int sem_init __P((sem_t *__sem, int __pshared, unsigned int __value));sem為指向信號量結(jié)構(gòu)的一個指針;pshared不為0時此信號量在進程間共享,否則只能為當前進程的所有線程共享;value給出了信號量的初始值。(2)函數(shù)sem_post(sem_t *sem)用來增加信號量的值。 當有線程阻塞在這個信號量上時,調(diào)用這個函數(shù)會使其中的一個線程不在阻塞,選擇機制同樣是由線程的調(diào)度策略決定的。 (3)函數(shù)sem_wait(sem_t *sem)被用來阻塞當前線程直到信號量sem的值大于0,解除阻塞后將sem的值減一,表明公共資源經(jīng)使用后減少。函數(shù)sem_trywait(sem_t *sem)是函數(shù)sem_wait()的非阻塞版本,它直接將信號量sem的值減一。 2.3 偽碼實現(xiàn) difine n 5; //為顧客準備的椅子數(shù)為5 semaphore mutex=1; //用于互斥 semaphore customers=0;//等候理發(fā)的顧客數(shù) semaphore barbers=1;//正在等候顧客的理發(fā)師數(shù) int waiting=0; //等候理發(fā)的顧客數(shù) //理發(fā)師線程 void barber(){ while(true)//判斷有無顧客 { wait(customers);//若無顧客,理發(fā)師睡眠 wait(mutex);//互斥 waiting--;//等候顧客數(shù)少一個 signal(mutex);//釋放臨界資源 signal(barber);//cut_hair;// } } //顧客線程 void customer(){ wait(mutex);// if(waiting 理發(fā)師去為一個顧客理發(fā) 正在理發(fā) 互斥 如果有空椅子,則等待 等候顧客數(shù)加1 釋放臨界資源 如果理發(fā)師睡覺,喚醒理發(fā)師理發(fā)師在理發(fā), 顧客等候 顧客坐下等理發(fā)師 店里人滿了,顧客離開 2.4 開發(fā)環(huán)境與工具 系統(tǒng)平臺:LINUX環(huán)境 實現(xiàn)語言:C語言 開發(fā)工具:NANO編輯器 3數(shù)據(jù)結(jié)構(gòu)與模塊說明 3.1 數(shù)據(jù)結(jié)構(gòu) 通過分析課程設(shè)計要求,定義以下的數(shù)據(jù): sem_t mutex,customers,barbers;//design three semaphores: mutex,customer,barbers int waiting=0;//the number of waiting customers int chair[5];3.2程序模塊說明 3.2.1主函數(shù)模塊 主函數(shù)流程圖如下: 3.2.2 理發(fā)師模塊 理發(fā)師模塊函數(shù)流程圖如下: 3.2.3 顧客模塊 顧客模塊函數(shù)流程圖如下: 源程序代碼 #include #include //design three semaphores: mutex,customer,barbers sem_t mutex,customers,barbers;int waiting=0;//the number of waiting customers int chair[5];void * barber();void * customer(void *arg); int main(int argc,char *argv[]){ //create 10 semaphores and one Barber semaphore pthread_t Customer_id[10],Barber_id;int i;sem_init(&mutex,0,1);//init mutex semaphore to 1 sem_init(&customers,0,0);//init semaphore customers to 0 sem_init(&barbers,0,1); for(i=0;i<5;i++)pthread_create(&Barber_id,NULL,(void*)barber,NULL);for(i=0;i<10;i++)pthread_create(&Customer_id[i],NULL,(void*)customer,(void*)(i+1));for(i=0;i<10;i++)pthread_join(Customer_id[i],NULL);for(i=0;i<5;i++)pthread_join(Barber_id,NULL);return 0;} //creat barber pthread void * barber(){ int i;int next;//wait(customers),if no customers,barber sleeping sem_wait(&customers);sem_wait(&mutex);//wait(mutex)waiting--;//the numer of waiting reduce one for(i=0;i<5;i++){ if(chair[i]!=0){ next= chair[i];chair[i]=0;break;} } printf(“The barber is cutting %dth customer's hairn”,next);sleep(3);sem_post(&mutex);sem_post(&barbers);} //creat customer pthread void * customer(void *arg){ int i;sem_wait(&mutex);//wait(mutex)if(waiting if(waiting waiting++;//the numer of waiting plus one for(i=0;i<5;i++){ if(chair[i]==0){ chair[i]=(int)arg;break;} } printf(“***************************************************n”);printf(“Entered:Number %d customer comes,and sits at %d n”,(int)arg,(i+1));printf(“There are %d customer on the chairn”,waiting);printf(“The customers' location are:”);for(i=0;i<5;i++)printf(“%d ”,chair[i]);printf(“n”); sleep(1);sem_post(&mutex);//signal(mutex)sem_post(&customers);//signal(customers)sem_wait(&barbers);//wait(barbers)} else chair { printf(“Number %d comes,there are no chairs,the customer %d is leavingn”,(int)arg,(int)arg);sem_post(&mutex);} } 5.2.1 編輯,編譯和運行的過程圖 5.2.2 錯誤部分截圖 5.2.3 正確運行結(jié)果圖 第一次運行結(jié)果如下圖: 第二次運行結(jié)果如下圖: 第三次運行結(jié)果如下圖; 6調(diào)試記錄 6.1調(diào)試記錄 周一因有培訓(xùn)與課設(shè)時間沖突,故沒有上機操作,查閱了相關(guān)書籍,并在網(wǎng)上查找了相關(guān)資料,了解了linux多線程編程的原理,應(yīng)注意的問題,及一些常用命令 周二先設(shè)計出了該程序的偽代碼即其wait、signal操作。然后,根據(jù)其要求進行編程,由于使用的是多線程編程,開始進行編譯的時候,編譯命令輸入錯誤,沒有輸入-lpthread,程序總是出現(xiàn)錯誤。同時,創(chuàng)建線程函數(shù)時,由于對其格式輸入錯誤導(dǎo)致程序無法運行。例如sb.c,sb1.c等都為本次調(diào)試時的程序。 周三主要是不斷的調(diào)試并完善程序。程序可以運行,但與要求總有些不符,故不斷的進行修改,并對其輸出的格式進行完善,使其輸出看起來美觀一些,容易觀察一些。例如s.c,b.c等程序為此次調(diào)試結(jié)果。 周四主要是在原有代碼的基礎(chǔ)上,使程序更完整些。并進行結(jié)果的截圖,開始設(shè)計并編寫課程設(shè)計報告。 6.2自我評析和總結(jié) 通過本次編程我熟悉了linux 下的多線程編程和信號量實現(xiàn)wait、signal操作的全過程,對同步和互斥問題也有了更深一步的理解,同時,也使我對linux編程有了更多的了解,在很多方面,它與在windows下編程有著很大的不同,對與多線程來說更方便一些。 設(shè)計過程中也遇到不少困難,尤其是對于多線程的實現(xiàn),結(jié)果總是不如想象中完美。比如其顧客編號的輸出有時會不按順序,輸入有點亂。另外,有時,輸出結(jié)束后,程序仍無法結(jié)束,必須強制性關(guān)閉終端才可以結(jié)束程序,這是本程序的一個不足之處。 在本次課程設(shè)計中我深深感覺到自己掌握的知識還遠遠不夠,我明白光是知道書本上的知識是遠遠不夠的,一定要把理論知識和實踐結(jié)合起來。同時,要多多學(xué)習(xí)linux的操作。 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 (操作系統(tǒng)課程設(shè)計) 生 產(chǎn) 者 和 消 費 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 者 學(xué)生姓名: 學(xué)生學(xué)號: 班 級: 0311401、02、03、04班制 二〇一三年十二月 一、課程題目分析 這個題目是生產(chǎn)者向消費者提供商品,消費者消耗商品,并且兩組人共用同一緩沖區(qū)。生產(chǎn)者提供了商品之后消費者才能去取商品,消費者若不取走商品則當緩沖區(qū)用完之后生產(chǎn)者則不能再向緩沖區(qū)中添加新的商品。 思考問題: (1)對于生產(chǎn)者進程:每產(chǎn)生一個數(shù)據(jù),則需去訪問共用緩沖區(qū)是否有已滿,未滿則可以將該數(shù)據(jù)存入并通知消費者進程,否則不能。 (2)對于消費者進程:每當想去消費(取出數(shù)據(jù))時,則需訪問緩沖區(qū)是否為空,為空則不能消費(取出數(shù)據(jù)),否則可以取,并通知生產(chǎn)者。 (3)緩沖區(qū)是個臨界資源,所有的進程對于該空間都是共享的,所以,還有互斥問題存在。 二、課程設(shè)計目的 通過實驗?zāi)M生產(chǎn)者與消費者之間的關(guān)系,了解并掌握他們之間的關(guān)系及原理。由此增加對進程同步問題的了解: (1)掌握基本的同步互斥算法,理解生產(chǎn)者與消費者模型 (2)了解windows中多線程(多進程)的并發(fā)執(zhí)行機制,線程(進程)間的同步于互斥 (3)學(xué)習(xí)使用windows中基本的同步對象,掌握相應(yīng)的API。 三、課程設(shè)計內(nèi)容 有n個生產(chǎn)者和m個消費者,連接在具有k個單位緩沖區(qū)的有界環(huán)轉(zhuǎn)緩沖上,湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 故又稱有界緩沖問題。其中Pi和Cj都是并發(fā)進程,只要緩沖區(qū)未滿,生產(chǎn)者進程Pi所生產(chǎn)的產(chǎn)品就可投入緩沖區(qū);類似地,只要緩沖區(qū)非空,消費者進程Cj就可以從緩沖區(qū)取走并消耗產(chǎn)品。 四、開發(fā)環(huán)境 操作系統(tǒng):Windows系統(tǒng) 編寫語言:C++語言 五、系統(tǒng)分析設(shè)計 (一)算法原理 生產(chǎn)者——消費者問題是典型的進程同步問題,這些進程必須按照一定的生產(chǎn)率和消費率來訪問共享緩沖區(qū),用P、V操作解決生產(chǎn)者和消費者共享單緩沖區(qū)的問題,可設(shè)置兩個信號量empty和full,其初值分別為1和0,empty指示能否向緩沖區(qū)放入產(chǎn)品,full指示能否從緩沖區(qū)取出產(chǎn)品。為了使其協(xié)調(diào)工作,必須使用一個信號量mutex(初值為1),以限制生產(chǎn)者和消費者互斥地對緩沖區(qū)進行存取,另用兩個信號量empty1(初值為緩沖區(qū)大?。┖蚮ull1(初值為0),以保證生產(chǎn)者不向已滿的緩沖區(qū)中放入產(chǎn)品,消費者不從空緩沖區(qū)中取產(chǎn)品。 (二)功能描述 生產(chǎn)者功能描述:在同一個進程地址空間內(nèi)執(zhí)行兩個線程。生產(chǎn)者線程生產(chǎn)物品,然后將物品放置在一個空緩沖區(qū)中供消費者線程消費。當生產(chǎn)者線程生產(chǎn)物品時,如果沒有空緩沖區(qū)可用,那么生產(chǎn)者線程必須等待消費者線程釋放出一個空緩沖區(qū)。 消費者功能描述:消費者線程從緩沖區(qū)獲得物品,然后釋放緩沖區(qū),當消費者線程消費物品時,如果沒有滿的緩沖區(qū),那么消費者線程將被阻塞,直到新的物品被生產(chǎn)出來。 (三)算法流程圖 生產(chǎn)者流程圖: 消費者流程圖: 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 總的流程圖: 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 開始Int i=1,n鍵盤輸入數(shù)字,初始化 n SeqSquare *b;b=new SeqSquare(n);鍵盤輸入數(shù)字,改變i的值i==0?Y退出Ncout<<“請輸入正確的菜單項進行操作!”< (四)數(shù)據(jù)結(jié)構(gòu)及部分函數(shù)描述 (1)類SeqSquare:對類SeqSquare的聲明及其中一些函數(shù) class SeqSquare { public: SeqSquare(int n);~SeqSquare();void P(int x);//p操作 void V(int x);//v操作 bool IsEmpty();//判斷是否為空 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 bool IsFull();//判斷是否已滿 void deca();void decb();int getSize();int getmaxSize();int gettop();int geta();int getb();protected: private: };說明:①用動態(tài)整型數(shù)組*elements來代表緩沖區(qū),不管是生產(chǎn)產(chǎn)品還是對已有產(chǎn)品的消費都需要訪問該緩沖區(qū)。②函數(shù)IsFull()用于判斷緩沖區(qū)是否已滿,生產(chǎn)者能否使用緩沖區(qū)。③函數(shù)IsEmpty()用于判斷緩沖區(qū)是否為空,消費者能否使用緩沖區(qū)。 (2)生產(chǎn)者和消費者操作及顯示函數(shù)showbuf: void producer(SeqSquare *a)//生產(chǎn)者操作 { } void consumer(SeqSquare *a)//消費者操作 { } //緩沖區(qū)顯示 void showbuf(SeqSquare *a){ }(3)在實現(xiàn)本程序的生產(chǎn)者消費者模型時,具體地通過以下同步對象實現(xiàn)互斥: int *elements;int top,a,b,maxSize;a->P(1);a->V(1);int i=a->getSize();湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 ①設(shè)一個互斥量Mutex,以實現(xiàn)生產(chǎn)者在查詢和保留緩沖區(qū)的下一個空位置時進行互斥。 ②每一個生產(chǎn)者用一個信號量與消費者同步,通過設(shè)置Full實現(xiàn),該組信號量用于表示相應(yīng)產(chǎn)品以生產(chǎn)。同時用一個表示空緩沖區(qū)數(shù)目的信號量Empty進行類似的同步,指示緩沖區(qū)中是否存在空位置,以便開始生產(chǎn)下一個產(chǎn)品。 (四)調(diào)試過程 為解決生產(chǎn)者、消費者問題,應(yīng)該設(shè)置兩個資源信號量,其中一個表示空緩沖區(qū)的數(shù)目,用Full表示,其初值為用戶輸入的緩沖區(qū)的大小,另一個表示緩沖區(qū)中產(chǎn)品的數(shù)目,用Empty表示,其初值為0.另外,由于緩沖區(qū)是一個臨界資源,必須互斥使用,所以還需要再設(shè)置一個互斥信號量Mutex,其初值為1.在生產(chǎn)者、消費者問題中,信號量實現(xiàn)兩種功能。首先,他是生產(chǎn)產(chǎn)品和消費產(chǎn)品的計數(shù)器,計數(shù)器的初值是可使用的資源數(shù)目(緩沖區(qū)的長度)。其次,他是確保產(chǎn)品的生產(chǎn)者和消費者之間的動作同步的同步器。 生產(chǎn)者要生產(chǎn)一個產(chǎn)品時,首先對資源信號量Full和互斥信號量Mutex進行P操作,申請資源。如果可以通過的話,就生產(chǎn)一個產(chǎn)品,并把產(chǎn)品送人緩沖區(qū)。然后對互斥信號量Mutex和資源信號量Empty進行V操作,釋放資源。 消費者要消費一個產(chǎn)品時,首先對資源信號量Empty和互斥信號量Mutex進行P操作,申請資源。如果可以通過的話就從緩沖區(qū)取出一個產(chǎn)品并消費掉。然后對互斥信號量Mutex和資源信號量Full進行V操作,釋放資源。 如果緩沖區(qū)中已經(jīng)沒有可用資源,就把申請資源的進程添加到等待隊列的隊尾。如果有一個資源被釋放,在等待隊列中的第一個進程被喚醒并取得這個資源的使用權(quán)。 (五)參考資料 《操作系統(tǒng)教程》 孫鐘秀 高等教育出版社 《C++程序設(shè)計》 譚浩強 高等教育出版社 六、運行實例及結(jié)果分析 (一)運行實例 緩沖區(qū)大小為3,先生產(chǎn)一件產(chǎn)品,顯示緩沖區(qū),再接著生產(chǎn)一件產(chǎn)品,消耗一件產(chǎn)品,顯示緩沖區(qū),在消耗兩件產(chǎn)品,再生產(chǎn)4件產(chǎn)品,改變緩沖區(qū)的大小為6,顯示緩沖區(qū),選擇一個未出現(xiàn)的選項,退出程序。 (二)結(jié)果顯示 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 (三)結(jié)果分析 (1)在每個程序中需要先做P,后做V,二者要成對出現(xiàn),夾在二者中間的代碼段就是該進程的臨界區(qū)。 (2)對同步信號量full和empty的P,V操作同樣必須成對出現(xiàn),但它們分別位于不同的程序中。 (3)無論在生產(chǎn)者進程中還是消費者進程中,兩個P操作的次序不能顛倒:應(yīng)先執(zhí)行同步信號量的P操作,然后執(zhí)行互斥信號量的P操作。否則可能造成進程死鎖。 七、個人體驗 雖然我也很想用java語言寫這個程序,但是由于自己學(xué)藝不精,所以只能用C++寫。通過這個實驗我發(fā)現(xiàn)我以前有很多知識都忘記了,重新拿起課本學(xué)習(xí)9 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 時發(fā)現(xiàn)原來很多不懂得問題都有了新的認識,有一種豁然開朗的感覺。也為我考研開了一個好的開頭。 我認為我完成的這個設(shè)計做的比較出色的地方是對C++語言中類以及數(shù)組的運用,其實這里我對數(shù)組的操作是按照“先進先出”的方法進行運作的,這是參考了棧的工作原理,因為緩沖區(qū)一般也是堆棧,比較符合設(shè)計要求。 這次實驗中我感覺做的很粗糙,自己所想的模擬過程的確得到實現(xiàn)了,但是感覺靈活性不太高,思考還不過全面,應(yīng)該以后多注意一下,多考慮考慮才是。 在這次實驗中我重新將《C++程序設(shè)計》和《數(shù)據(jù)結(jié)構(gòu)》的幾個重要章節(jié)復(fù)習(xí)了一遍,對類、數(shù)組、C++的I/O流類庫以及堆棧的語句格式、注意細節(jié)都再一次熟悉,感覺蠻有趣的。不過,在編程過程中許多語句的小問題還真是出現(xiàn)不少,而且感覺自己對C++強大豐富的語句方法用得太呆板,不夠靈活,總是想到那些常用的,而忽略了顆粒讓語句更簡短的方法,以后要多多注意才是。 八、附錄 // 生產(chǎn)者消費者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級計算機專業(yè)操作系統(tǒng)課程設(shè)計 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級計算機專業(yè)操作系統(tǒng)課程設(shè)計 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級計算機專業(yè)操作系統(tǒng)課程設(shè)計 void producer(SeqSquare *a) //生產(chǎn)者操作 { a->P(1);} void consumer(SeqSquare *a) //消費者操作 { a->V(1);} SeqSquare::~SeqSquare(){ delete elements;} //緩沖區(qū)顯示 void showbuf(SeqSquare *a){ int i=a->getSize(); } int main(){ int i,n;cout<<“請輸入緩沖區(qū)大?。骸? cout<<“請選擇操作: ”< 4.退出系統(tǒng)。 ”< ”< switch(i) { case 1: producer(s); if(s->geta()==0) { 湖北民族學(xué)院信息工程學(xué)院11級計算機專業(yè)操作系統(tǒng)課程設(shè)計 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;} 閩江學(xué)院 計算機系 網(wǎng)絡(luò)操作系統(tǒng)課程設(shè)計 設(shè)計內(nèi)容:進程機制與并發(fā)程序設(shè)計——linux下生產(chǎn)者與消費者的問題實現(xiàn) 目錄: 一、設(shè)計內(nèi)容····························3 二、設(shè)計思想····························4 三、系統(tǒng)結(jié)構(gòu)····························5 四、PV操作代碼··························5 五、C++程序代碼·························6 六、運行結(jié)果截圖························9 七、參考文獻····························11 八、實驗總結(jié)····························11 一、設(shè)計內(nèi)容 進程機制與并發(fā)程序設(shè)計————linux下生產(chǎn)者與消費者的問題實現(xiàn) 1.實驗?zāi)康?/p> (1)掌握基本的同步互斥算法,理解生產(chǎn)者和消費者同步的問題模型。(2)了解linux中多線程的并發(fā)執(zhí)行機制,線程間的同步和互斥。 2、實驗環(huán)境:C/C++語言編譯器 3、實驗要求 (1)創(chuàng)建生產(chǎn)者和消費者線程 在linux環(huán)境下,創(chuàng)建一個控制臺進程,在此進程中創(chuàng)建n個線程來模擬生產(chǎn)者或者消費者。這些線程的信息由本程序定義的“測試用例文件”中予以指定。 該文件的格式和含義如下: 3 1 P 3 2 P 4 3 C 4 1 4 P 2 5 C 3 1 2 4 第一行說明程序中設(shè)置幾個臨界區(qū),其余每行分別描述了一個生產(chǎn)者或者消費者線程的信息。每一行的各字段間用Tab鍵隔開。不管是消費者還是生產(chǎn)者,都有一個對應(yīng)的線程號,即每一行開始字段那個整數(shù)。第二個字段用字母P或者C區(qū)分是生產(chǎn)者還是消費者。第三個字段表示在進入相應(yīng)線程后,在進行生產(chǎn)和消費動作前的休眠時間,以秒計時;這樣做的目的是可以通過調(diào)整這一列參數(shù),控制開始進行生產(chǎn)和消費動作的時間。如果是代表生產(chǎn)者,則該行只有三個字段。如果代表消費者,則該行后邊還有若干字段,代表要求消費的產(chǎn)品所對應(yīng)的生產(chǎn)者的線程號。所以務(wù)必確認這些對應(yīng)的線程號存在并且該線程代表一個生產(chǎn)者。(2)生產(chǎn)和消費的規(guī)則 在按照上述要求創(chuàng)建線程進行相應(yīng)的讀寫操作時,還需要符合以下要求: ①共享緩沖區(qū)存在空閑空間時,生產(chǎn)者即可使用共享緩沖區(qū)。 ②從上邊的測試數(shù)據(jù)文件例子可以看出,某一生產(chǎn)者生產(chǎn)一個產(chǎn)品后,可能不止一個消費者,或者一個消費者多次地請求消費該產(chǎn)品。此時,只有當所有的消費需求都被滿足以后,該產(chǎn)品所在的共享緩沖區(qū)才可以被釋放,并作為空閑空間允許新的生產(chǎn)者使用。 ③每個消費者線程的各個消費需求之間存在先后順序。例上述測試用例文件包含一行信息“5 C 3 l 2 4”,可知這代表一個消費者線程,該線程請求消費1,2,4號生產(chǎn)者線程生產(chǎn)的產(chǎn)品。而這種消費是有嚴格順序的,消費1號線程產(chǎn)品的請求得到滿足后才能繼續(xù)往下請求2號生產(chǎn)者線程的產(chǎn)品。 ④要求在每個線程發(fā)出讀寫操作申請、開始讀寫操作和結(jié)束讀寫操作時分別顯示提示信息。(3)相關(guān)基礎(chǔ)知識 本實驗所使用的生產(chǎn)者和消費者模型具有如下特點: 本實驗的多個緩沖區(qū)不是環(huán)形循環(huán)的,也不要求按順序訪問。生產(chǎn)者可以把產(chǎn)品放到目前某一個空緩沖區(qū)中。 消費者只消費指定生產(chǎn)者的產(chǎn)品。 在測試用例文件中指定了所有的生產(chǎn)和消費的需求,只有當共享緩沖區(qū)的數(shù)據(jù)滿足了所有關(guān)于它的消費需求后,此共享緩沖區(qū)才可以作為空閑空間允許新的生產(chǎn)者使用。 本實驗在為生產(chǎn)者分配緩沖區(qū)時各生產(chǎn)者間必須互斥,此后各個生產(chǎn)者的具體生產(chǎn)活動可以并發(fā)。而消費者之間只有在對同一產(chǎn)品進行消費時才需要互斥,同時它們在消費過程結(jié)束時需要判斷該消費對象是否已經(jīng)消費完畢并清除該產(chǎn)品。 linux用來實現(xiàn)同步和互斥的實體。在linux中,常見的同步對象有:信號量(Semaphore)、互斥量(Mutex)、臨界段(CriticalSection)等。使用這些對象都分為三個步驟,一是創(chuàng)建或者初始化:接著請求該同步對象,隨即進入臨界區(qū),這一步對應(yīng)于互斥量的上鎖;最后釋放該同步對象,這對應(yīng)于互斥量的解鎖。這些同步對象在一個線程中創(chuàng)建,在其他線程中都可以使用,從而實現(xiàn)同步互斥。 二、設(shè)計思想 生產(chǎn)者進程與消費者進程是經(jīng)典的同步互斥關(guān)系。系統(tǒng)創(chuàng)建兩類進程:proceducer()和consumer(),分別用來描述生產(chǎn)者和消費者的行為。生產(chǎn)者與消費者問題是指若干進程通過循環(huán)緩沖池區(qū)交換數(shù)據(jù)。如下圖所示,生產(chǎn)者進程不斷向循環(huán)緩沖池區(qū)中寫入數(shù)據(jù)(即生產(chǎn)數(shù)據(jù)),而消費者進程不斷從循環(huán)緩沖池區(qū)中讀出數(shù)據(jù)(即消費數(shù)據(jù))。循環(huán)緩沖池共有N個緩沖區(qū),緩沖區(qū)可以暫存一個產(chǎn)品,任何時刻只能有一個進程課對循環(huán)緩沖池進行操作。所有生產(chǎn)者和消費者要協(xié)調(diào)工作,以完成數(shù)據(jù)的交換。只要有空緩沖區(qū),生產(chǎn)者就可以把產(chǎn)品送入緩沖區(qū);只要有滿緩沖區(qū),消費者就可以從緩沖區(qū)中取走物品。 為了解決生產(chǎn)者和消費者問題,應(yīng)該設(shè)置信號量和變量如下: full: 滿緩沖區(qū)資源信號量,初值為0; empty:空緩沖區(qū)資源信號量,初值為n; in: 生產(chǎn)者指針,初值均為0; out: 消費者指針,均為0; mutex:緩沖區(qū)操作的互斥信號量,初值為1 三、系統(tǒng)結(jié)構(gòu) PCB* readyhead=NULL, * readytail=NULL;// 就緒隊列——鏈表結(jié)構(gòu) PCB* consumerhead=NULL, * consumertail=NULL;// 消費者隊列 PCB* producerhead=NULL, * producertail=NULL;// 生產(chǎn)者隊列 processproc()---給PCB分配內(nèi)存,產(chǎn)生相應(yīng)的的進程 Pempty()---如果緩沖區(qū)滿,該進程進入生產(chǎn)者等待隊列; linkqueue(exe,&producertail);// 把就緒隊列里的進程放入生產(chǎn)者隊列的尾部 執(zhí)行順序:Main()---empty---in---full---out---finish 當緩沖池為空時,生產(chǎn)者生產(chǎn)產(chǎn)品in緩沖池 in=in+1 當緩沖池為滿時,消費者消費產(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 //定義一個隨機函數(shù)來生產(chǎn)產(chǎn)品,并且使兩個顧產(chǎn)品間的時間少于10秒 int long waiting(0);//正在等待的產(chǎn)品的數(shù)目 int buffer;//空位的總數(shù)目 char empty;//緩沖區(qū)空 char full;//緩沖區(qū)滿 int count(0);//產(chǎn)品的號碼數(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”);//用來實現(xiàn)進程的互斥 HANDLE proceducer=CreateSemaphore(NULL, 1,1, “proceducer”);//定義信號量來進行線程間的同步 HANDLE consumer=CreateSemaphore(NULL,0,3,“consum”);DWORD WINAPI consum(LPVOID pParm2)//消費的線程 { WaitForSingleObject(Mutex ,INFINITE);//p(mutex)來進行互斥操作 count++;//生產(chǎn)的是第幾個產(chǎn)品 cout<<“第 ”< { if(waiting!=0){ cout<<“此時有”< else cout<<“沒有產(chǎn)品在等待”< ReleaseMutex(Mutex);//釋放互斥量,以便其他線程使用 WaitForSingleObject(proceducer,INFINITE);//等待生產(chǎn) getconsum();//消費并取走 } 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);//釋放信號量 ResumeThread(proceducer);//喚醒消費進程 ReleaseMutex(Mutex);//v(mutex);proceduce();//生產(chǎn) finish++;//消費的產(chǎn)品數(shù)加1 } return 0;} int main(int argc, char* argv[]){ cout<<“請輸入緩沖區(qū)空位的總數(shù)目:”;cin>>buffer;cout<<“緩沖區(qū)共有”< cout< HANDLE hThread1;HANDLE hThread2;hThread2=::CreateThread(NULL,0,proceducers,NULL,0,NULL);//產(chǎn)生一個生產(chǎn)者進程 while(full!='y'){ Sleep(random);//產(chǎn)品隨機進入 hThread1=::CreateThread(NULL,0,consum,NULL,a,NULL);cout< { cout<<“已經(jīng)為”< else;} if(full=='y'){ cout<<“********對不起,緩沖區(qū)已滿********”< } 六、運行結(jié)果截圖 緩沖區(qū)空位總數(shù)目為1時運行結(jié)果截圖: 緩沖區(qū)空位總數(shù)目為0和3時運行結(jié)果截圖(其余部分如上當緩沖區(qū)空位總數(shù)目為1時的截圖) 七、參考文獻 1、計算機網(wǎng)絡(luò)操作系統(tǒng)原理與應(yīng)用 孔憲軍 呂濱(本學(xué)期教科書) 2、網(wǎng)絡(luò)操作系統(tǒng)課程設(shè)計計劃書 陳衛(wèi)老師 3、C程序設(shè)計(第三版)譚浩強 八、實驗總結(jié) 剛剛看到課程設(shè)計的內(nèi)容與要求時,不禁有點無從下手的感覺。經(jīng)過一番思考后,才決定選擇設(shè)計“進程機制與并發(fā)程序設(shè)計——linux下生產(chǎn)者與消費者的問題實現(xiàn)”這部分。設(shè)計這部分不僅僅需要用到C/C++編程,還需要編寫相關(guān)的PV原語。由于自己的PV原語部分和C/C++編程學(xué)的不是很好,因此對我來說有點難。于是我就積極利用書本上的知識來編寫PV原語,C/C++編程是參考書上的指點以及網(wǎng)絡(luò)資源編寫出來的。不懂得地方查資料、上網(wǎng)找、問問其他同學(xué),最后終于慢慢的把課程設(shè)計做出來了。通過這次課程設(shè)計,才感覺到自己還是平時動手少,要經(jīng)常動手去做實驗才能真正學(xué)到東西。尤其是一些C/C++編程和PV原語的編寫更需要平時多加練習(xí)才能學(xué)好用好。特別是C/C++編程在遇到語法有多處錯誤時,不能急,要冷靜下來慢慢修改,知道程序正確。雖然是自己獨立做的課程設(shè)計,但是其中還是有很多不懂的東西是問同學(xué)的,因此了解到學(xué)習(xí)不是單獨的,應(yīng)該是相互交流相互學(xué)習(xí)的。 操 作 系 統(tǒng) 實 驗 報 告 (2)學(xué)院:計算機科學(xué)與技術(shù)學(xué)院 班級:計091 學(xué)號:姓名: 時間:2011/12/30 目 錄 1.實驗名稱……………………………………………………3 2.實驗?zāi)康摹? 3.實驗內(nèi)容……………………………………………………3 4.實驗要求……………………………………………………3 5.實驗原理……………………………………………………3 6.實驗環(huán)境……………………………………………………4 7.實驗設(shè)計……………………………………………………4 7.1數(shù)據(jù)結(jié)構(gòu)設(shè)計……………………………………………………………………4 7.2算法設(shè)計…………………………………………………………………………6 7.3功能模塊設(shè)計……………………………………………………………………7 8.實驗運行結(jié)果………………………………………………8 9.實驗心得……………………………………………………9 附錄:源代碼(部分)…………………………………………………………………9 一、實驗名稱: 用C++實現(xiàn)銀行家算法 二、實驗?zāi)康模?/p> 通過自己編程來實現(xiàn)銀行家算法,進一步理解銀行家算法的概念及含義,提高對銀行家算法的認識,同時提高自己的動手實踐能力。 各種死鎖防止方法能夠阻止發(fā)生死鎖,但必然會降低系統(tǒng)的并發(fā)性并導(dǎo)致低效的資源利用率。死鎖避免卻與此相反,通過合適的資源分配算法確保不會出現(xiàn)進程循環(huán)等待鏈,從而避免死鎖。本實驗旨在了解死鎖產(chǎn)生的條件和原因,并采用銀行家算法有效地防止死鎖的發(fā)生。 三、實驗內(nèi)容: 利用C++,實現(xiàn)銀行家算法 四、實驗要求: 1.完成銀行家算法的設(shè)計 2.設(shè)計有n個進程共享m個系統(tǒng)資源的系統(tǒng),進程可動態(tài)的申請和釋放資源,系統(tǒng)按各進程的申請動態(tài)的分配資源。 五、實驗原理: 系統(tǒng)中的所有進程放入進程集合,在安全狀態(tài)下系統(tǒng)收到進程的資源請求后,先把資源試探性的分配給它。之后,系統(tǒng)將剩下的可用資源和進程集合中的其他進程還需要的資源數(shù)作比較,找出剩余資源能夠滿足的最大需求量的進程,從而保證進程運行完畢并歸還全部資源。這時,把這個進程從進程集合中刪除,歸還其所占用的所有資源,系統(tǒng)的剩余資源則更多,反復(fù)執(zhí)行上述步驟。最后,檢查進程集合,若為空則表明本次申請可行,系統(tǒng)處于安全狀態(tài),可以真正執(zhí)行本次分配,否則,本次資源分配暫不實施,讓申請資源的進程等待。 銀行家算法是一種最有代表性的避免死鎖的算法。在避免死鎖方法中允許進程動態(tài)地申請資源,但系統(tǒng)在進行資源分配之前,應(yīng)先計算此次分配資源的安全性,若分配不會導(dǎo)致系統(tǒng)進入不安全狀態(tài),則分配,否則等待。為實現(xiàn)銀行家算法,系統(tǒng)必須設(shè)置若干數(shù)據(jù)結(jié)構(gòu)。要解釋銀行家算法,必須先解釋操作系統(tǒng)安全狀態(tài)和不安全狀態(tài)。安全序列是指一個進程序列{P1,…,Pn}是安全的,如果對于每一個進程Pi(1≤i≤n),它以后尚需要的資源量不超過系統(tǒng)當前剩余資源量與所有進程Pj(j < i)當前占有資源量之和。 安全狀態(tài):如果存在一個由系統(tǒng)中所有進程構(gòu)成的安全序列P1,…,Pn,則系統(tǒng)處于安全狀態(tài)。安全狀態(tài)一定是沒有死鎖發(fā)生。 不安全狀態(tài):不存在一個安全序列。不安全狀態(tài)不一定導(dǎo)致死鎖。 我們可以把操作系統(tǒng)看作是銀行家,操作系統(tǒng)管理的資源相當于銀行家管理的資金,進程向操作系統(tǒng)請求分配資源相當于用戶向銀行家貸款。 為保證資金的安全,銀行家規(guī)定: (1)當一個顧客對資金的最大需求量不超過銀行家現(xiàn)有的資金時就可接納該顧客; (2)顧客可以分期貸款,但貸款的總數(shù)不能超過最大需求量; (3)當銀行家現(xiàn)有的資金不能滿足顧客尚需的貸款數(shù)額時,對顧客的貸款可推遲支付,但總能使顧客在有限的時間里得到貸款; (4)當顧客得到所需的全部資金后,一定能在有限的時間里歸還所有的資金.操作系統(tǒng)按照銀行家制定的規(guī)則為進程分配資源,當進程首次申請資源時,要測試該進程對資源的最大需求量,如果系統(tǒng)現(xiàn)存的資源可以滿足它的最大需求量則按當前的申請量分配資源,否則就推遲分配。當進程在執(zhí)行中繼續(xù)申請資源時,先測試該進程本次申請的資源數(shù)是否超過了該資源所剩余的總量。若超過則拒絕分配資源,若能滿足則按當前的申請量分配資源,否則也要推遲分配。 六、實驗環(huán)境: Win-7系統(tǒng) Visual C++ 6.0 七、實驗設(shè)計: 1.數(shù)據(jù)結(jié)構(gòu)設(shè)計 定義結(jié)構(gòu)體: struct Process//進程屬性構(gòu)成 { Source claim;//進程最大需求量 Source allocation;//進程占有量 Source claim_allocation;//進程需求量 Source currentAvail;//進程可獲得量 }; 定義類對象: class Source //資源的基本構(gòu)成以及功能 { private: public: int R1;//定義三類類資源 int R2;int R3; Source(int r1 = 0,int r2 = 0,int r3 = 0){ R1=r1;R2=r2;R3=r3;} Source(Source& s){ R1=s.R1;R2=s.R2;R3=s.R3;} void setSource(int r1 = 0,int r2 = 0,int r3 = 0)//設(shè)置各類資源 { R1=r1;R2=r2;R3=r3;} void add(Source s)//加法 { R1=R1+s.R1;R2=R2+s.R2;R3=R3+s.R3;} void sub(Source s)//減法 { R1=R1-s.R1;R2=R2-s.R2;R3=R3-s.R3;} bool lower(Source s)//比較 { if(R1 > s.R1)return false; if(R2 > s.R2)return false; if(R3 > s.R3)return false; return true;} }; class Data//封裝所有數(shù)據(jù) { public: Process *p;//進程指針 Source sum;//總資源量 Source available;//可獲得量 Source ask;//請求量 int pLength;//進程個數(shù) int * ruler;//邏輯尺 void clearProcess()//進程currentAvail清零 { for(int i=0;i { p[i].currentAvail.setSource(0, 0, 0);} } }; class DataInit//封裝初始化數(shù)據(jù)函數(shù)類 { private: public: DataInit()//構(gòu)造函數(shù) { } void initLength(Data *db)//設(shè)置進程個數(shù) { int n; cout<<“輸入進程數(shù): ”; cin>>n; db->pLength = n; db->p = new Process[n]; if(!db->p) {cout<<“error!no enough memory space!”;return;} db->ruler = new int[n]; if(!db->ruler) {cout<<“error!no enough memory space!”;return;} } 2.算法設(shè)計 class FindSafeList//尋找安全序列 { private: public: FindSafeList()//構(gòu)造函數(shù) {} bool checkList(Data *db)//檢查一個序列安全性 { int i=0;//i用于循環(huán) db->p[db->ruler[i]].currentAvail.add(db->available);//將當前系統(tǒng)可用資源量賦給該序列的第一個進程 if(!db->p[db->ruler[i]].claim_allocation.lower(db->p[db->ruler[i]].currentAvail))//若當前進程currentAvail小于該進程需求量(claim-allocation),返回false {return false;} for(i=1;i< db->pLength;i++) { //當前進程的可獲得資源量currentAvail獲得前一個進程的未釋放資源前可獲得資源量currentAvail db->p[db->ruler[i]].currentAvail.add(db->p[db->ruler[i-1]].currentAvail); //當前進程的可獲得資源量currentAvail獲得前一個進程的釋放的資源量 db->p[db->ruler[i]].currentAvail.add(db->p[db->ruler[i-1]].allocation); //若當前進程currentAvail小于該進程需求量(claim-allocation),返回false if(!db->p[db->ruler[i]].claim_allocation.lower(db->p[db->ruler[i]].currentAvail)) { return false;} //若當前進程currentAvail大于該進程總資源量,返回false if(!db->p[db->ruler[i]].currentAvail.lower(db->sum)) { return false;} } return true;//該序列進程安全。返回true } bool exsitSafeList(Data *db)//判斷是否存在安全序列 { int i = 0; for(i = 0;i < db->pLength;i++)//設(shè)置邏輯尺的刻度值 { db->ruler[i] = i;} while(1) //該循環(huán)將檢測邏輯尺刻度值的全排列 { if(checkList(db)) //找到一個安全序列,返回true { return true;} db->clearProcess();//將所有進程的currentAvail清零 if(!next_permutation(db->ruler,db->ruler+db->pLength)) //所有排列完畢后退出生成排列庫函數(shù)的調(diào)用 { return false; } } return false;} int findSafeList(Data *db, int i=0)//尋找安全序列 { //請求值大于系統(tǒng)當前可用資源值,返回0 if(!db->ask.lower(db->available)) { return 0;} //請求值大于當前進程需求資源值,返回1 if(!db->ask.lower(db->p[i].claim_allocation)) { return 1;} Source s(db->p[i].allocation);//根據(jù)請求,分配資源值 db->available.sub(db->ask); db->p[i].allocation.add(db->ask); db->p[i].claim_allocation.sub(db->ask); if(!exsitSafeList(db))//判斷是否存在安全序列 { db->available.add(db->ask); //不存在安全序列,回滾,恢復(fù)分配前狀態(tài),并返回2 db->p[i].allocation.sub(db->ask); db->p[i].claim_allocation.add(db->ask); return 2; } db->ask.setSource(0,0,0);//找到安全序列,將請求資源置零,返回3 return 3;} };3.功能模塊設(shè)計 class Data//封裝所有數(shù)據(jù) class DataInit//封裝初始化數(shù)據(jù)函數(shù)類 class Display//封裝顯示方法 class FindSafeList//尋找安全序列 struct Process//進程屬性構(gòu)成 void main()//主函數(shù) 八、實驗運行結(jié)果: 輸入進程數(shù),及相關(guān)資源數(shù)量分配 選擇算法完成的操作:1 查看進程情況 請求分配 2.1分配失敗 2.2 分配成功 2.3 繼續(xù)分配失敗,退出 九、實驗心得: 通過此次實驗,我能夠更加深入的理解銀行家算法的執(zhí)行過程,也懂得用銀行家算法去防止發(fā)生死鎖,有效地解決了資源利用率低的問題,保證了系統(tǒng)的安全性。 當然在實驗過程中,我也遇到了一些困難,但是我通過及時請教同學(xué),查詢相關(guān)資料,及時解決了問題,但仍有不足之處,我將會在今后學(xué)習(xí)中更加努力。 附錄:源代碼(部分) #include class Source //資源的基本構(gòu)成以及功能 { private: public: int R1;//定義三類類資源 int R2;int R3; Source(int r1 = 0,int r2 = 0,int r3 = 0){ R1=r1;R2=r2;R3=r3;} Source(Source& s){ R1=s.R1;R2=s.R2;R3=s.R3;} void setSource(int r1 = 0,int r2 = 0,int r3 = 0)//設(shè)置各類資源 { R1=r1;R2=r2;R3=r3;} void add(Source s)//加法 { R1=R1+s.R1;R2=R2+s.R2;R3=R3+s.R3;} void sub(Source s)//減法 { R1=R1-s.R1;R2=R2-s.R2;R3=R3-s.R3;} bool lower(Source s)//比較 { if(R1 > s.R1)return false; if(R2 > s.R2)return false; if(R3 > s.R3)return false; return true;} }; struct Process//進程屬性構(gòu)成 { Source claim;//進程最大需求量 Source allocation;//進程占有量 Source claim_allocation;//進程需求量 Source currentAvail;//進程可獲得量 }; class Data//封裝所有數(shù)據(jù) { public: Process *p;//進程指針 Source sum;//總資源量 Source available;//可獲得量 Source ask;//請求量 int pLength;//進程個數(shù) int * ruler;//邏輯尺 void clearProcess()//進程currentAvail清零 { for(int i=0;i { p[i].currentAvail.setSource(0, 0, 0);} } }; class DataInit//封裝初始化數(shù)據(jù)函數(shù)類 { private: public: DataInit()//構(gòu)造函數(shù) { } void initLength(Data *db)//設(shè)置進程個數(shù) { int n; cout<<“輸入進程數(shù): ”; cin>>n; db->pLength = n; db->p = new Process[n]; if(!db->p) {cout<<“error!no enough memory space!”;return;} db->ruler = new int[n]; if(!db->ruler){cout<<“error!no enough memory space!”;return;} } void setAsk(Data *db)//設(shè)置請求資源量 { int r1,r2,r3;r1=0;r2=0;r3=0; db->ask.setSource(r1,r2,r3);} void initSum(Data *db)//設(shè)置總資源量 { int r1,r2,r3;cout<<“Available(R1,R2,R3): ”;cin>>r1>>r2>>r3;db->sum.setSource(r1,r2,r3);} void initAvail(Data *db)//設(shè)置可獲得量 { int r1,r2,r3;cout<<“輸入初始分配 Allocation:n”;cout<<“available[R1,R2,R3]:n ”; cin>>r1>>r2>>r3; db->available.setSource(r1,r2,r3);} void initProcess(Data *db)//設(shè)置各進程屬性值 { int r1,r2,r3;cout<<“輸入t0時分配 Allocation:n”;for(int i=0;i cout<<'p'< cin>>r1>>r2>>r3; db->p[i].allocation.setSource(r1,r2,r3); cout<<'p'< cin>>r1>>r2>>r3; db->p[i].claim.setSource(r1,r2,r3); r1=db->p[i].claim.R1-db->p[i].claim.R1;//設(shè)置進程p[i] 的 claim_allocation r2=db->p[i].claim.R2-db->p[i].claim.R2; r3=db->p[i].claim.R3-db->p[i].claim.R3; db->p[i].claim_allocation.setSource(r1, r2, r3); } } }; class Display//封裝顯示方法 { private: public: Display()//構(gòu)造函數(shù) { } void displaySource(Source s)//設(shè)置基本資源顯示方式 {cout< displayAvailable(Source s)//顯示可獲得資源量 {displaySource(s);} void displayProcess(Process *p,int length)//顯示進程基本信息 { for(int i=0;i { cout<<“ p”< displaySource(p[i].claim); cout<<“tt”; displaySource(p[i].allocation); cout< } cout< void displaySafeList(Data *db)//顯示安全序列 { for(int i=0;i { cout<<“ p”< ”; displaySource(db->p[db->ruler[i]].currentAvail); cout<<“ ”; displaySource(db->p[db->ruler[i]].claim); cout<<“ ”; displaySource(db->p[db->ruler[i]].allocation); cout<<“ ”; displaySource(db->p[db->ruler[i]].claim_allocation); cout<<“ true”; cout< } } void displayAskResult(Data *db,int n)//顯示請求資源結(jié)果 { if(n==0) {cout<<“不分配,請求量大于當前可獲得量!n”;return;} if(n==1) {cout<<“不分配,請求量大于當前可獲得量!n”;return;} if(n==2) {cout<<“不分配,找不到安全序列!n”;return;} if(n==3) { cout<<“存在安全序列:”; for(int i=0;i {cout< cout< char c='N'; cout<<“查看安全序列詳情?(Y/N)”; cin>>c; if(c=='Y'||c=='y') { cout<<“ 進程 currentavail claim allocation claim-allocation possiblen”; displaySafeList(db); } return; } } }; class FindSafeList//尋找安全序列 { private: public: FindSafeList()//構(gòu)造函數(shù) {} bool checkList(Data *db)//檢查一個序列安全性 { int i=0;//i用于循環(huán) db->p[db->ruler[i]].currentAvail.add(db->available);//將當前系統(tǒng)可用資源量 賦給該序列的第一個進程 if(!db->p[db->ruler[i]].claim_allocation.lower(db->p[db->ruler[i]].currentAvail))//若當前進程currentAvail小于該進程需求量(claim-allocation),返回false {return false;} for(i=1;i< db->pLength;i++) { //當前進程的可獲得資源量currentAvail獲得前一個進程的未釋放資源前可獲得資源量currentAvail db->p[db->ruler[i]].currentAvail.add(db->p[db->ruler[i-1]].currentAvail); //當前進程的可獲得資源量currentAvail獲得前一個進程的釋放的資源量 db->p[db->ruler[i]].currentAvail.add(db->p[db->ruler[i-1]].allocation); //若當前進程currentAvail小于該進程需求量(claim-allocation),返回false if(!db->p[db->ruler[i]].claim_allocation.lower(db->p[db->ruler[i]].currentAvail)) { return false;} //若當前進程currentAvail大于該進程總資源量,返回false if(!db->p[db->ruler[i]].currentAvail.lower(db->sum)) { return false;} } return true;//該序列進程安全。返回true } bool exsitSafeList(Data *db)//判斷是否存在安全序列 { int i = 0; for(i = 0;i < db->pLength;i++)//設(shè)置邏輯尺的刻度值 { db->ruler[i] = i;} while(1) //該循環(huán)將檢測邏輯尺刻度值的全排列 { if(checkList(db)) //找到一個安全序列,返回true { return true;} db->clearProcess();//將所有進程的currentAvail清零 if(!next_permutation(db->ruler,db->ruler+db->pLength)) //所有排列完畢后退出生成排列庫函數(shù)的調(diào)用 { return false; } } return false;} int findSafeList(Data *db, int i=0)//尋找安全序列 { //請求值大于系統(tǒng)當前可用資源值,返回0 if(!db->ask.lower(db->available)) { return 0;} //請求值大于當前進程需求資源值,返回1 if(!db->ask.lower(db->p[i].claim_allocation)) { return 1;} Source s(db->p[i].allocation);//根據(jù)請求,分配資源值 db->available.sub(db->ask); db->p[i].allocation.add(db->ask); db->p[i].claim_allocation.sub(db->ask); if(!exsitSafeList(db))//判斷是否存在安全序列 { db->available.add(db->ask); //不存在安全序列,回滾,恢復(fù)分配前狀態(tài),并返回2 db->p[i].allocation.sub(db->ask); db->p[i].claim_allocation.add(db->ask); return 2; } db->ask.setSource(0,0,0);//找到安全序列,將請求資源置零,返回3 return 3;} }; void main(){ Data *db;db=new Data;if(!db){ cout<<“error!no enough memory space!”;return;} DataInit dataInit;dataInit.initLength(db);//設(shè)置進程個數(shù) dataInit.initSum(db);//設(shè)置系統(tǒng)總資源量 dataInit.initAvail(db);//設(shè)置當前系統(tǒng)可獲得資源量 dataInit.initProcess(db);//設(shè)置t0時刻進程基本狀態(tài) Display display;FindSafeList findSafeList;int r1=0,r2=0,r3=0;int c;db->ask.setSource(r1,r2,r3);//設(shè)置請求資源為0,即無請求 c=findSafeList.findSafeList(db,0);//尋找安全序列,返回結(jié)果 if(c!=3){ cout<<“t0時刻的進程組不存在安全序列!n”;return;} int choice=1;int pi; while(choice){ cout<<“n 選擇操作:n 查看進程情況n 請求分配資源n 0 退出n ”; cin>>choice;switch(choice){ case 1: { } case 2: { } case 0: { default: { } } } cout<<“當前資源量available[R1,R2,R3]:n ”;display.displayAvailable(db->available);cout<第二篇:操作系統(tǒng)課程設(shè)計--用多線程同步方法解決睡眠理發(fā)師問題(Sleeping-Barber_Problem)
第三篇:操作系統(tǒng)課程設(shè)計生產(chǎn)者消費者
第四篇:生產(chǎn)者與消費者的問題-----操作系統(tǒng)課程設(shè)計
第五篇:操作系統(tǒng)課程設(shè)計實驗報告-用C++實現(xiàn)銀行家算法