操作系統(tǒng)實驗進程的同步heu_第1頁
操作系統(tǒng)實驗進程的同步heu_第2頁
操作系統(tǒng)實驗進程的同步heu_第3頁
操作系統(tǒng)實驗進程的同步heu_第4頁
操作系統(tǒng)實驗進程的同步heu_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、操作系統(tǒng)實 驗 報 告課程名稱操作系統(tǒng)實驗課程編號0906553實驗項目名稱進程的同步學(xué)號年級姓名專業(yè)學(xué)生所在學(xué)院指導(dǎo)教師實驗室名稱地點 哈爾濱工程大學(xué)計算機科學(xué)與技術(shù)學(xué)院第六講 進程的同步一、實驗概述1. 實驗名稱進程的同步2. 實驗?zāi)康模?)使用 EOS 的信號量編程解決生產(chǎn)者消費者問題,理解進程同步的意義。(2)調(diào)試跟蹤 EOS 的信號量的工作過程,理解進程同步的原理。(3)修改 EOS 的信號量算法,使之支持等待超時喚醒功能(有限等待),加深理解進程同步的原理。3. 實驗類型驗證型實驗,設(shè)計性實驗4. 實驗內(nèi)容(1)準備實驗(2)使用 EOS 的信號量解決生產(chǎn)者消費者問題(3)調(diào)試 E

2、OS 信號量的工作過程1)創(chuàng)建信號量 2)等待釋放信號量 3)等待信號量(不阻塞) 4)釋放信號量(不喚醒) 5) 等待信號量(阻塞) 6) 釋放信號量(喚醒)(4)修改 EOS 的信號量算法 二、實驗環(huán)境操作系統(tǒng)集成實驗環(huán)境OS Lab三、實驗過程1. 設(shè)計思路和流程圖2. 算法實現(xiàn)3. 需要解決的問題及解答(1). P143生產(chǎn)者在生產(chǎn)了13號產(chǎn)品后本來要繼續(xù)生產(chǎn)14號產(chǎn)品,可此時生產(chǎn)者為什么必須等待消費者消費了4號產(chǎn)品后,才能生產(chǎn)14號產(chǎn)品呢?生產(chǎn)者和消費者是怎樣使用同步對象來實現(xiàn)該同步過程的呢?答:此時生產(chǎn)了0-13號14個產(chǎn)品,消費了0-3號4個產(chǎn)品,緩沖區(qū)都占滿了。只有緩沖區(qū)有空閑

3、生產(chǎn)者才能生產(chǎn)東西,有權(quán)向里面放東西。所以它必須等到消費者,取走產(chǎn)品,有空閑緩沖區(qū)時,才繼續(xù)生產(chǎn)14號產(chǎn)品。(2). P145-3.4 修改EOS的信號量算法(只看一次消費1個產(chǎn)品的,一次消費2個產(chǎn)品的可以寫到實驗報告中)答:見三,四部分(3). 思考在ps/semaphore.c文件內(nèi)的PsWaitForSemaphore和PsReleaseSemaphore函數(shù)中,為什么要使用原子操作? 答:原子操作要求一旦開始就要運行到結(jié)束,不能有中斷。在執(zhí)行等待信號量和釋放信號量的時候,不允許cpu響應(yīng)外部中斷,所以使用原子操作。(4). 繪制ps/semaphore.c文件內(nèi)PsWaitForSem

4、aphore和PsReleaseSemaphore函數(shù)的流程圖。原子操作前關(guān)中斷PsWaitForSemaphore開始原子操作P操作NWait操作的信號量大于0Y執(zhí)行P操作P操作結(jié)束Ps Release Semaphore原子操作前關(guān)中斷開始原子操作V操作NP和V操作的信號量之和大于緩沖隊列長度Y記錄當前信號量的值返回“信號數(shù)目量超出范圍”釋放信號量信號量值+1NP操作控制的信號量不大于0N被阻塞進程量小于要釋放的信號量Y喚醒等待進程Y喚醒隊列中進程N等待隊列為空Y返回“喚醒成功”結(jié)束4. 主要數(shù)據(jù)結(jié)構(gòu)、實現(xiàn)代碼及其說明1)修改PsWaitForSemaphore函數(shù)if (Semaphor

5、e->Count>0)Semaphore->Count-;flag=STATUS_SUCCESS;/如果信號量大于零,說明尚有資源,可以為線程分配else flag=PspWait(&Semaphore->WaitListHead, Milliseconds);KeEnableInterrupts(IntState); / 原子操作完成,恢復(fù)中斷。return flag;/否則,說明資源數(shù)量不夠,不能再為線程分配資源,因此要使線程等待2)修改PsReleaseSemaphore函數(shù)if (Semaphore->Count + ReleaseCount &g

6、t; Semaphore->MaximumCount) Status = STATUS_SEMAPHORE_LIMIT_EXCEEDED; else / 記錄當前的信號量的值。/if (NULL != PreviousCount) *PreviousCount = Semaphore->Count;int mm=Semaphore->Count;/ 目前僅實現(xiàn)了標準記錄型信號量,每執(zhí)行一次信號量的釋放操作/ 只能使信號量的值增加 1。/while (!ListIsEmpty(&Semaphore->WaitListHead)&&(ReleaseC

7、ount)PspWakeThread(&Semaphore->WaitListHead, STATUS_SUCCESS);PspThreadSchedule();ReleaseCount-;Semaphore->Count=mm+ReleaseCount;/ 可能有線程被喚醒,執(zhí)行線程調(diào)度。/Status = STATUS_SUCCESS;5. 源程序并附上注釋#include "psp.h"VOIDPsInitializeSemaphore(IN PSEMAPHORE Semaphore,IN LONG InitialCount,IN LONG Max

8、imumCount)/*+功能描述:初始化信號量結(jié)構(gòu)體。參數(shù):Semaphore - 要初始化的信號量結(jié)構(gòu)體指針。InitialCount - 信號量的初始值,不能小于 0 且不能大于 MaximumCount。MaximumCount - 信號量的最大值,必須大于 0。返回值:無。-*/ASSERT(InitialCount >= 0 && InitialCount <= MaximumCount && MaximumCount > 0);Semaphore->Count = InitialCount;Semaphore->Max

9、imumCount = MaximumCount;ListInitializeHead(&Semaphore->WaitListHead);STATUSPsWaitForSemaphore(IN PSEMAPHORE Semaphore,IN INT Milliseconds,IN STATUS i)/*+功能描述:信號量的 Wait 操作(P 操作)。參數(shù):Semaphore - Wait 操作的信號量對象。Milliseconds - 等待超時上限,單位毫秒。返回值:STATUS_SUCCESS。當你修改信號量使之支持超時喚醒功能后,如果等待超時,應(yīng)該返回 STATUS_TI

10、MEOUT。-*/BOOL IntState;ASSERT(KeGetIntNesting() = 0); / 中斷環(huán)境下不能調(diào)用此函數(shù)。IntState = KeEnableInterrupts(FALSE); / 開始原子操作,禁止中斷。/ 目前僅實現(xiàn)了標準記錄型信號量,不支持超時喚醒功能,所以 PspWait 函數(shù)/ 的第二個參數(shù)的值只能是 INFINITE。/if(Semaphore->Count > 0) Semaphore->Count-; i=STATUS_SUCCESS; else i=PspWait(&Semaphore->WaitListHe

11、ad,Milliseconds ); KeEnableInterrupts(IntState); / 原子操作完成,恢復(fù)中斷。 return i;STATUSPsReleaseSemaphore(IN PSEMAPHORE Semaphore,IN LONG ReleaseCount,OUT PLONG PreviousCount)/*+功能描述:信號量的 Signal 操作(V 操作)。參數(shù):Semaphore - Wait 操作的信號量對象。ReleaseCount - 信號量計數(shù)增加的數(shù)量。當前只能為 1。當你修改信號量使之支持超時喚醒功能后,此參數(shù)的值能夠大于等于 1。Previous

12、Count - 返回信號量計數(shù)在增加之前的值。返回值:如果成功釋放信號量,返回 STATUS_SUCCESS。-*/STATUS Status;BOOL IntState;IntState = KeEnableInterrupts(FALSE); / 開始原子操作,禁止中斷。if (Semaphore->Count + ReleaseCount > Semaphore->MaximumCount) Status = STATUS_SEMAPHORE_LIMIT_EXCEEDED; else / 記錄當前的信號量的值。/if (NULL != PreviousCount) *P

13、reviousCount = Semaphore->Count; INT j=Semaphore->Count;/ 目前僅實現(xiàn)了標準記錄型信號量,每執(zhí)行一次信號量的釋放操作/ 只能使信號量的值增加 1。/while(!ListIsEmpty(&Semaphore->WaitListHead)&&(ReleaseCount) PspWakeThread(&Semaphore->WaitListHead, STATUS_SUCCESS); PspThreadSchedule(); ReleaseCount-; Semaphore->Co

14、unt=j+ReleaseCount;Status = STATUS_SUCCESS;KeEnableInterrupts(IntState); / 原子操作完成,恢復(fù)中斷。return Status;POBJECT_TYPE PspSemaphoreType = NULL;/ 用于初始化 semaphore 結(jié)構(gòu)體的參數(shù)結(jié)構(gòu)體。/typedef struct _SEM_CREATE_PARAMLONG InitialCount;LONG MaximumCount;SEM_CREATE_PARAM, *PSEM_CREATE_PARAM;/ semaphore 對象的構(gòu)造函數(shù),在創(chuàng)建新 sem

15、aphore 對象時被調(diào)用。/VOIDPspOnCreateSemaphoreObject(IN PVOID SemaphoreObject,IN ULONG_PTR CreateParam)PsInitializeSemaphore( (PSEMAPHORE)SemaphoreObject, (PSEM_CREATE_PARAM)CreateParam)->InitialCount, (PSEM_CREATE_PARAM)CreateParam)->MaximumCount );/ semaphore 對象類型的初始化函數(shù)。/VOIDPspCreateSemaphoreObjec

16、tType(VOID)STATUS Status;OBJECT_TYPE_INITIALIZER Initializer;Initializer.Create = PspOnCreateSemaphoreObject;Initializer.Delete = NULL;Initializer.Wait = (OB_WAIT_METHOD)PsWaitForSemaphore;Initializer.Read = NULL;Initializer.Write = NULL;Status = ObCreateObjectType("SEMAPHORE", &Initia

17、lizer, &PspSemaphoreType);if (!EOS_SUCCESS(Status) KeBugCheck("Failed to create semaphore object type!"); / semaphore 對象的構(gòu)造函數(shù)。/STATUSPsCreateSemaphoreObject(IN LONG InitialCount,IN LONG MaximumCount,IN PSTR Name,OUT PHANDLE SemaphoreHandle)STATUS Status;PVOID SemaphoreObject;SEM_CREATE

18、_PARAM CreateParam;if(InitialCount < 0 | MaximumCount <= 0 | InitialCount > MaximumCount)return STATUS_INVALID_PARAMETER;/ 創(chuàng)建信號量對象。/CreateParam.InitialCount = InitialCount;CreateParam.MaximumCount = MaximumCount;Status = ObCreateObject( PspSemaphoreType, Name, sizeof(SEMAPHORE), (ULONG_PTR)

19、&CreateParam, &SemaphoreObject);if (!EOS_SUCCESS(Status) return Status;Status = ObCreateHandle(SemaphoreObject, SemaphoreHandle);if (!EOS_SUCCESS(Status) ObDerefObject(SemaphoreObject);return Status;/ semaphore 對象的 signal 操作函數(shù)。/STATUSPsReleaseSemaphoreObject(IN HANDLE Handle,IN LONG ReleaseC

20、ount,IN PLONG PreviousCount)STATUS Status;PSEMAPHORE Semaphore;if (ReleaseCount < 1) return STATUS_INVALID_PARAMETER;/ 由 semaphore 句柄得到 semaphore 對象的指針。Status = ObRefObjectByHandle(Handle, PspSemaphoreType, (PVOID*)&Semaphore);if (EOS_SUCCESS(Status) Status = PsReleaseSemaphore(Semaphore, Rel

21、easeCount, PreviousCount);ObDerefObject(Semaphore);return Status;6. 程序運行時的初值和運行結(jié)果(1)準備實驗1)啟動 OS Lab。 2)新建一個 EOS Kernel 項目。 3)生成 EOS Kernel 項目,從而在該項目文件夾中生成 SDK 文件夾。 4)新建一個 EOS 應(yīng)用程序項目。 5)使用在第 3 步生成的 SDK 文件夾覆蓋 EOS 應(yīng)用程序項目文件夾中的 SDK 文件夾。 (2)使用 EOS 的信號量解決生產(chǎn)者消費者問題1)使用 pc.c 文件中的源代碼,替換之前創(chuàng)建的 EOS 應(yīng)用程序項目中 EOSApp

22、.c 文件內(nèi)的源代碼。 2)按 F7 生成修改后的 EOS 應(yīng)用程序項目。 3)按 F5 啟動調(diào)試。OS Lab 會首先彈出一個調(diào)試異常對話框。 4)在調(diào)試異常對話框中選擇“否”,繼續(xù)執(zhí)行。 5)立即激活虛擬機窗口查看生產(chǎn)者消費者同步執(zhí)行的過程。 6)待應(yīng)用程序執(zhí)行完畢后,結(jié)束此次調(diào)試。 (3)調(diào)試 EOS 信號量的工作過程1)創(chuàng)建信號量按 F5 啟動調(diào)試 EOS 應(yīng)用項目。OS Lab 會首先彈出一個調(diào)試異常對話框。在調(diào)試異常對話框中選擇“是”,調(diào)試會中斷。在 main 函數(shù)中創(chuàng)建 Empty 信號量的代碼行(第 77 行) EmptySemaphoreHandle = CreateSema

23、phore(BUFFER_SIZE, BUFFER_SIZE, NULL); 添加一個斷點。按 F5 繼續(xù)調(diào)試,到此斷點處中斷。按 F11 調(diào) 試進入 CreateSemaphore 函數(shù)。 可以看 到此 API 函 數(shù)只是 調(diào)用了 EOS 內(nèi)核中 的PsCreateSemaphoreObject 函數(shù)來創(chuàng)建信號量對象。按 F11 調(diào)試進入 semaphore.c 文件中的 PsCreateSemaphoreObject 函數(shù)。在此函數(shù)中,會在 EOS內(nèi)核管理的內(nèi)存中創(chuàng)建一個信號量對象(分配一塊內(nèi)存),而初始化信號量對象中各個成員的操作是在 PsInitializeSemaphore 函數(shù)中完

24、成的。在 semaphore.c 文件的頂部查找到 PsInitializeSemaphore 函數(shù)的定義(第 19 行),在此函數(shù)的第一行(第 39 行)代碼處添加一個斷點。 按 F5 繼續(xù)調(diào)試,到斷點處中斷。觀察 PsInitializeSemaphore 函數(shù)中用來初始化信號量結(jié)構(gòu)體成員的值,應(yīng)該和傳入 CreateSemaphore 函數(shù)的參數(shù)值是一致的。 按 F10 單步調(diào)試 PsInitializeSemaphore 函數(shù)執(zhí)行的過程,查看信號量結(jié)構(gòu)體被初始化的過程。打開“調(diào)用堆?!贝翱?,查看函數(shù)的調(diào)用層次。 2)等待信號量(不阻塞)刪除所有的斷點(防止有些斷點影響后面的調(diào)試)。 在

25、 eosapp.c 文件的 Producer 函數(shù)中,等待 Empty 信號量的代碼行(第 144 行) WaitForSingleObject(EmptySemaphoreHandle, INFINITE); 添加一個斷點。 按 F5 繼續(xù)調(diào)試,到斷點處中斷。 WaitForSingleObject 函數(shù)最終會調(diào)用內(nèi)核中的 PsWaitForSemaphore 函數(shù)完成等待操作。所以,在 semaphore.c 文件中 PsWaitForSemaphore 函數(shù)的第一行(第 68 行)添加一個斷點。 按 F5 繼續(xù)調(diào)試,到斷點處中斷。 按 F10 單步調(diào)試,直到完成 PsWaitForSem

26、aphore 函數(shù)中的所有操作??梢钥吹酱舜螆?zhí)行并沒有進行等待,只是將 Empty 信號量的計數(shù)減少了 1(由 10 變?yōu)榱?9)就返回了。 3)釋放信號量(不喚醒)刪除所有的斷點(防止有些斷點影響后面的調(diào)試)。 在 eosapp.c 文件的 Producer 函數(shù)中,釋放 Full 信號量的代碼行(第 152 行) ReleaseSemaphore(FullSemaphoreHandle, 1, NULL); 添加一個斷點。 按 F5 繼續(xù)調(diào)試,到斷點處中斷。 按 F11 調(diào)試進入 ReleaseSemaphore 函數(shù)。 繼續(xù)按 F11 調(diào)試進入 PsReleaseSemaphoreObj

27、ect 函數(shù)。 先使用 F10 單步調(diào)試,當黃色箭頭指向第 269 行時使用 F11 單步調(diào)試,進入 PsReleaseSemaphore函數(shù)。 按 F10 單步調(diào)試,直到完成 PsReleaseSemaphore 函數(shù)中的所有操作。可以看到此次執(zhí)行沒有喚醒其它線程(因為此時沒有線程在 Full 信號量上被阻塞),只是將 Full 信號量的計數(shù)增加了 1(由 0 變?yōu)榱?1)。 4)等待信號量(阻塞)結(jié)束之前的調(diào)試。 刪除所有的斷點。 按 F5 重新啟動調(diào)試。OS Lab 會首先彈出一個調(diào)試異常對話框。 在調(diào)試異常對話框中選擇“是”,調(diào)試會中斷。 在 semaphore.c 文件中的 PsWa

28、itForSemaphore 函數(shù)的 PspWait(&Semaphore->WaitListHead, INFINITE); 代碼行(第 78 行)添加一個斷點。 按 F5 繼續(xù)調(diào)試,并立即激活虛擬機窗口查看輸出。開始時生產(chǎn)者、消費者都不會被信號量阻塞,同步執(zhí)行一段時間后才在斷點處中斷。 中斷后,查看“調(diào)用堆?!贝翱?,有 Producer 函數(shù)對應(yīng)的堆棧幀,說明此次調(diào)用是從生產(chǎn)者線程函數(shù)進入的。 在“調(diào)用堆?!贝翱谥须p擊 Producer 函數(shù)所在的堆棧幀,綠色箭頭指向等待 Empty 信號量的代碼行,查看 Producer 函數(shù)中變量 i 的值為 14,表示生產(chǎn)者線程正在嘗試

29、生產(chǎn) 14 號產(chǎn)品。 在“ 調(diào)用堆 ?!?窗口中 雙擊 PsWaitForSemaphore 函數(shù)的 堆棧 幀,查 看 Empty 信號 量計 數(shù)(Semaphore->Count)的值為-1,所以會調(diào)用 PspWait 函數(shù)將生產(chǎn)者線程放入 Empty 信號量的等待隊列中進行等待(讓出 CPU)。 激活虛擬機窗口查看輸出的結(jié)果。生產(chǎn)了從 0 到 13 的 14 個產(chǎn)品,但是只消費了從 0 到 3 的 4 個產(chǎn)品,所以緩沖池中的 10 個緩沖區(qū)就都被占用了,這與之前調(diào)試的結(jié)果是一致的。 5)釋放信號量(喚醒)刪除所有斷點。 在 eosapp.c 文件的 Consumer 函數(shù)中,釋放 E

30、mpty 信號量的代碼行(第 180 行) ReleaseSemaphore(EmptySemaphoreHandle, 1, NULL); 添加一個斷點。 按 F5 繼續(xù)調(diào)試,到斷點處中斷。 查看 Consumer 函數(shù)中變量 i 的值為 4,說明已經(jīng)消費了 4 號產(chǎn)品。 按照 3.3.2.2 中的方法使用 F10 和 F11 調(diào)試進入 PsReleaseSemaphore 函數(shù)。 查看 PsReleaseSemaphore 函數(shù)中 Empty 信號量計數(shù)(Semaphore->Count)的值為-1,和生產(chǎn)者線程被阻塞時的值是一致的。 按 F10 單步調(diào)試 PsReleaseSema

31、phore 函數(shù),直到在代碼行(第 132 行) PspWakeThread(&Semaphore->WaitListHead, STATUS_SUCCESS); 處中斷。此時 Empty 信號量計數(shù)的值已經(jīng)由-1 增加為了 0,需要調(diào)用 PspWakeThread 函數(shù)喚醒阻塞在 Empty 信號量等待隊列中的生產(chǎn)者線程(放入就緒隊列中),然后調(diào)用 PspSchedule 函數(shù)執(zhí)行調(diào)度,這樣生產(chǎn)者線程就得以繼續(xù)執(zhí)行。6)驗證生產(chǎn)者線程被喚醒后,是從之前被阻塞時的狀態(tài)繼續(xù)執(zhí)行的: 在 semaphore.c 文件中 PsWaitForSemaphore 函數(shù)的最后一行(第 83 行)代碼處添加一個斷點。 按 F5 繼續(xù)調(diào)試,在斷點處中斷。 查看 PsWaitForSemaphore 函數(shù)中 Empty 信號量計數(shù)(Semaphore->Count)的值為 0,和生產(chǎn)者線程被喚醒時的值是一致的。 在“調(diào)用堆棧”窗口中可以看到是由 Producer 函數(shù)進入的。激活 Producer 函數(shù)的堆棧幀,查看Producer 函數(shù)中變量 i 的值為 14,表明

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論