欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)(五篇范文)

      時間:2019-05-14 11:29:49下載本文作者:會員上傳
      簡介:寫寫幫文庫小編為你整理了多篇相關(guān)的《讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)》,但愿對你工作學習有幫助,當然你在寫寫幫文庫還可以找到更多《讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)》。

      第一篇:讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)

      4.1實驗二:讀者寫者問題 4.1.1實驗要求

      在Windows 環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含n個線程。用這n個線程來表示n個讀者或?qū)懻?。每個線程按相應測試數(shù)據(jù)文件(后面有介紹)的要求進行讀寫操作。用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者-寫者問題。

      讀者-寫者問題的讀寫操作限制(包括讀者優(yōu)先和寫者優(yōu)先): 1)寫-寫互斥,即不能有兩個寫者同時進行寫操作。

      2)讀-寫互斥,即不能同時有一個線程在讀,而另一個線程在寫。3)讀-讀允許,即可以有一個或多個讀者在讀。

      讀者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一個讀者正在進行讀操作,則該讀者可直接開始讀操作。

      寫者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一寫者在等待訪問共享資源,則該讀者必須等到?jīng)]有寫者處于等待狀態(tài)才能開始讀操作。

      運行結(jié)果顯示要求:要求在每個線程創(chuàng)建、發(fā)出讀寫操作申請、開始讀寫操作和結(jié)果讀寫操作時分別顯示一行提示信息,以確定所有處理都遵守相應的讀寫操作限制。4.1.2測試數(shù)據(jù)文件格式

      測試數(shù)據(jù)文件包括n行測試數(shù)據(jù),分別描述創(chuàng)建的n個線程是讀者還是寫者,以及讀寫操作的開始時間和持續(xù)時間。每行測試數(shù)據(jù)包括四個字段,各個字段間用空格分隔。第一字段為一個正整數(shù),表示線程序號。第二字段表示相應線程角色,R表示讀者,W表示寫者。第三字段為一個正數(shù),表示讀寫操作的開始時間:線程創(chuàng)建后,延遲相應時間(單位為秒)后發(fā)出對共享資源的讀寫申請。第四字段為一個正數(shù),表示讀寫操作的持續(xù)時間。當線程讀寫申請成功后,開始對共享資源的讀寫操作,該操作持續(xù)相應時間后結(jié)束,并釋放共享資源。

      下面是一個測試數(shù)據(jù)文件的例子: 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 注意:

      在創(chuàng)建數(shù)據(jù)文件時,由于涉及到文件格式問題,最好在記事本中手工逐個鍵入數(shù)據(jù),而不要拷貝粘貼數(shù)據(jù),否則,本示例程序運行時可能會出現(xiàn)不可預知的錯誤。4.1.3實習分析

      可以將所有讀者和所有寫者分別存于一個讀者等待隊列和一個寫者等待隊列中,每當讀允許時,就從讀者隊列中釋放一個或多個讀者線程進行讀操作;每當寫允許時,就從寫者隊列中釋放一個寫者進行寫操作。

      1.讀者優(yōu)先

      讀者優(yōu)先指的是除非有寫者在寫文件,否則讀者不需要等待。所以可以用一個整型變量read-count記錄當前的讀者數(shù)目,用于確定 是否需要釋放正在等待的寫者線程(當read-count=0時,表明所有的讀者讀完,需要釋放寫者等待隊列中的一個寫者)。每一個讀者開始讀文件時,必須修改read-count變量。因此需要一個互斥對象mutex來實現(xiàn)對全局變量read-count修改時的互斥。

      另外,為了實現(xiàn)寫-寫互斥,需要增加一個臨界區(qū)對象write。當寫者發(fā)出寫請求時,必須申請臨界區(qū)對象的所有權(quán)。通過這種方法,也可以實現(xiàn)讀-寫互斥,當read-count=1時(即第一個讀者到來時),讀者線程也必須申請臨界區(qū)對象的所有權(quán)。當讀者擁有臨界區(qū)的所有權(quán)時,寫者阻塞在臨界區(qū)對象write上。當寫者擁有臨界區(qū)的所有權(quán)時,第一個讀者判斷完“read-count==1”后阻塞在write上,其余的讀者由于等待對read-count的判斷,阻塞在mutex上。

      2.寫者優(yōu)先

      寫者優(yōu)先與讀者優(yōu)先類似。不同之處在于一旦一個寫者到來,它應該盡快對文件進行寫操作,如果有一個寫者在等待,則新到來的讀者不允許進行讀操作。為此應當添加一個整型變量write-count,用于記錄正在等待的寫者數(shù)目,當write-count=0時,才可以釋放等待的讀者線程隊列。

      為了對全局變量write-count實現(xiàn)互斥,必須增加一個互斥對象mutex3。

      為了實現(xiàn)寫者優(yōu)先,應當添加一個臨界區(qū)對象read,當有寫者在寫文件或等待時,讀者必須阻塞在read上。

      讀者線程除了要對全局變量read-count實現(xiàn)操作上的互斥外,還必須有一個互斥對象對阻塞read這一過程實現(xiàn)互斥。這兩個互斥對象分別命名為mutex1和mutex2。4.1.4相關(guān)API函數(shù)說明

      1.CreateThread 函數(shù)功能:

      該函數(shù)創(chuàng)建一個在調(diào)用進程的地址空間中執(zhí)行的線程。函數(shù)原型:

      HANDLE CreateThread(LPSECURITY-ATTRIBUTES lpThreadAttributes, DWORD dwStackSize,LPTHREAD-START-TOUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LLPDWORD lpThreadId);參數(shù):

      ·lpThreadAttributes:指向一個SECURITY-ATTRIBUTES結(jié)構(gòu),該結(jié)構(gòu)決定了返回的句柄是否可被子進程繼承。若lpThreadAttributes為NULL,則句柄不能被繼承。在Windows NT中該結(jié)構(gòu)的lpSwcurityDescriptor成員定義了新進程的安全性描述符。若lpThreadAttributes為NULL,則線程獲得一個默認的安全性描述符?!wStackSize:定義原始堆棧提交時的大?。ò醋止?jié)計)。系統(tǒng)將該值舍入為最近的頁。若該值為0,或小于默認時提交的大小,默認情況是使用與調(diào)用線程同樣的大小。更多的信息,請看Thread Stack Size。

      ·lpStartAddress:指向一個LPTHREAD-START-TOUTINE類型的應用定義的函數(shù),該線程執(zhí)行此函數(shù)。該指針還表示遠程進程中線程的起始地址。該函數(shù)必須存在于遠程進程中。

      ·lpParameter:定義一個傳遞給該進程的32位值。

      ·dwCreationFlags:定義控制進程創(chuàng)建的附加標志。若定義CREATE-SUSPENDED標志,線程創(chuàng)建時處于掛起狀態(tài),并且直到ResumeThread函數(shù)調(diào)用時才能運行。若該值為0,則該線程在創(chuàng)建后立即執(zhí)行。

      ·lpThreadId:指向一個32位值,它接收該線程的標識符。返回值:

      若函數(shù)調(diào)用成功,返回值為新線程的句柄;若函數(shù)調(diào)用失敗,返回值為NULL。備注:

      新線程的句柄創(chuàng)建時設為THREAD-ALL-ACCESS訪問權(quán)限。若未提供安全性描述符,則該句柄可被任何要求一個線程對象句柄的函數(shù)所使用。若提供了安全性描述符,則以后使用該句柄時,將在授權(quán)訪問以前執(zhí)行訪問檢查。若訪問檢查被拒絕訪問,則請求進程不能使用該句柄獲得對該線程的訪問。線程從lpStartAddress參數(shù)定義的函數(shù)處開始執(zhí)行。若該函數(shù)返回,系統(tǒng)將默認地認為以調(diào)用ExitThread函數(shù)的方法終止該線程。使用GetExitCodeThread 函數(shù)來獲得線程的返回值。

      線程創(chuàng)建時擁有THREAD-PRIORITY-NORMAL優(yōu)先權(quán)。使用GetThreadPriority和SetThreadPriority函數(shù)可以獲得和設置線程的優(yōu)先權(quán)值。

      一個線程終止時,該線程對象被設為發(fā)信號狀態(tài),以滿足在該對象上等待的所有進程。一個線程對象始終存在于系統(tǒng)中,直到該線程終止,且它所有的句柄都已通過調(diào)用CloseHandle函數(shù)關(guān)閉。

      2.ExitThread 函數(shù)功能:

      該函數(shù)結(jié)束一個線程。函數(shù)原型:

      VOID ExitThread(DWORD dwExitcode); 參數(shù):

      ·dwExitcode:定義調(diào)用線程的退出代碼。使用GetExitcodeThread函數(shù)來檢測一個線程的退出代碼。返回值:無。備注:

      調(diào)用ExitThread函數(shù),是結(jié)束一個線程的較好的方法。調(diào)用該函數(shù)后(或者直接地調(diào)用,或者從一個線程過程返回),當前線程的堆棧取消分配,線程終止。若調(diào)用該函數(shù)時,該線程為進程的最后一個線程,則該線程的進程也被終止。

      線程對象的狀態(tài)變?yōu)榘l(fā)信號狀態(tài),以釋放所有正在等待該線程終止的其他線程。線程的終止狀態(tài)從STILL-ACTIVATE變?yōu)閐wExitcode參數(shù)的值。

      線程結(jié)合時不必從操作系統(tǒng)中移去該線程對象。當線程的最后一個句柄關(guān)閉時,該線程對象被刪除。

      3.SLEEP 函數(shù)功能:

      該函數(shù)對于指定的時間間隔掛起當前的執(zhí)行線程。函數(shù)原型:

      VOID SLEEP(DWORD dwMilliseconds); 參數(shù):

      ·dwMilliseconds:定義掛起執(zhí)行線程的時間,以毫秒(ms)為單位。取值為0時,該線程將如余下的時間片交給處于就緒狀態(tài)的同一優(yōu)先級的其他線程。若沒有處于就緒狀態(tài)的同一優(yōu)先級的其他線程,則函數(shù)立即返回,該線程繼續(xù)執(zhí)行。若取值為INFINITE則造成無限延遲。返回值:

      該函數(shù)沒有返回值。備注:

      一個線程可以在調(diào)用該函數(shù)時將睡眠時間設為0ms,以將剩余的時間片交出。4.CreateMutex 函數(shù)功能:

      該函數(shù)創(chuàng)建有名或者無名的互斥對象。函數(shù)原型:

      HANDLE CreateMutex(LPSECURITY-ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,LPCTSTR lpName);參數(shù):

      ·lpMutexAttributes:指向SECURITY-ATTRIBUTES結(jié)構(gòu)的指針,該結(jié)構(gòu)決定子進程是否能繼承返回句柄。如果lpMutexAttributes為NULL,那么句柄不能被繼承。

      在Windows NT中該結(jié)構(gòu)的lpSwcurityDescriptor成員指定新互斥對象的安全性描述符。若lpThreadAttributes為NULL,那么互斥對象獲得默認的安全性描述符?!InitialOwner:指定互斥對象的初始所屬身份。如果該值為TRUE,并且調(diào)用者創(chuàng)建互斥對象,那么調(diào)用線程獲得互斥對象所屬身份。否則,調(diào)用線程不能獲得互斥對象所屬身份。判斷調(diào)用者是否創(chuàng)建互斥對象請參閱返回值部分。

      ·lpName:指向以NULL結(jié)尾的字符串,該字符串指定了互斥對象名。該名字的長度大于MAX-PATH且可以包含除反斜線()路徑分隔符以外的任何字符。名字是區(qū)分大小寫的。

      如果lpName與已存在的有名互斥對象相匹配,那么該函數(shù)要求用MUTEX-ALL-ACCESS權(quán)限訪問已存在的對象。在這種情況下,由于參數(shù)bInitialOwner已被創(chuàng)建進程所設置,該參數(shù)被忽略。如果參數(shù)lpMutexAttributes不為NULL,它決定句柄是否解除繼承,但是其安全描述符成員被忽略。

      如果lpName為NULL,那么創(chuàng)建的互斥對象無名。

      如果lpName與已存在的事件、信號量、可等待定時器、作業(yè)或者文件映射對象的名字相匹配,那么函數(shù)調(diào)用失敗,并且GetLastError函數(shù)返回ERROR-INVALID-HANDLE,其原因是這些對象共享相同的名字空間。

      返回值:

      如果函數(shù)調(diào)用成功,返回值為互斥對象句柄;如果函數(shù)調(diào)用之前,有名互斥對象已存在,那么函數(shù)給已存在的對象返回一個句柄,并且函數(shù)GetLastError返回ERROR-ALREADY-EXISTS,否則,調(diào)用者創(chuàng)建互斥對象。

      如果函數(shù)調(diào)用失敗,則返回值為NULL。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      備注:

      由函數(shù)CreateMutex返回的句柄有MUTEX-ALL-ACCESS權(quán)限可以去訪問新的互斥對象,并且可用在請求互斥對象句柄的任何函數(shù)中。

      調(diào)用進程中的任何線程可以可以在調(diào)用等待函數(shù)時指定互斥對象句柄。當指定對象的狀態(tài)為信號態(tài)時,返回單對象等待函數(shù)。當任何一個或者所有的互斥對象都為信號態(tài)時,返回多對象等待函數(shù)指令。等待函數(shù)返回后,等待的線程被釋放,繼續(xù)向下執(zhí)行。

      當一個互斥對象不被任何線程擁有時,處于信號態(tài)。創(chuàng)建該對象的線程可以使用bInitialOwner標志來請求立即獲得對該互斥對象的所有權(quán)。否則,線程必須使用等待函數(shù)來請求所有權(quán)。當互斥對象處于信號態(tài),等待的線程獲得對該對象的所有權(quán)時,此互斥對象的狀態(tài)被設置為非信號態(tài),等待函數(shù)返回。任意時刻,僅有一個線程能擁有該互斥對象,線程可以使用ReleaseMutex函數(shù)來釋放對這個互斥對象的所有權(quán)。

      若線程已經(jīng)擁有了一個互斥對象,那么它可以重復調(diào)用等待函數(shù)而不會發(fā)生阻塞,一般情況下,用戶不會重復等待同一個互斥對象,這種機制防止了線程因等待它已經(jīng)擁有的互斥對象而發(fā)生死鎖。然而,線程必須為每一次等待調(diào)用一次ReleaseMutex函數(shù)來釋放該互斥對象。

      兩個或多個互斥進程可以調(diào)用CreateMutex來創(chuàng)建同名的互斥對象,第一個進程實際創(chuàng)建互斥對象,以后的進程打開已存在的互斥對象的句柄。這使得多個進程可以得到同一個互斥對象的句柄,從而減輕了用戶的負擔,使用戶不必判斷創(chuàng)建進程是否為第一個啟動的進程。使用這種技術(shù)時,應該把bInitialOwner標志設為FALSE;否則很難確定開始時哪一個進程擁有該互斥對象。

      由于多進程能夠擁有相同互斥對象的句柄,通過使用這個對象,可使多進程同步。以下為共享對象機制:

      ·如果CreateMutex中的lpMutexAttributes參數(shù)允許繼承,由CreateProcess函數(shù)創(chuàng)建的子進程可以繼承父進程的互斥對象句柄。

      ·一個進程可以在調(diào)用DuplicateHandle函數(shù)時指定互斥對象句柄來創(chuàng)建一個可以被其他進程使用的雙重句柄。一個進程在調(diào)用OpenMutex或CreateMutex函數(shù)時能指定互斥對象名。

      ·使用CloseHandle函數(shù)關(guān)閉句柄,進程時系統(tǒng)自動關(guān)閉句柄。當最后一個句柄被關(guān)閉時,互斥對象被銷毀。

      5.ReleaseMutex 函數(shù)功能:

      該函數(shù)放棄指定互斥對象的所有權(quán)。函數(shù)原型:

      BOOL ReleaseMutex(HANDLE hMutex); 參數(shù):

      ·hMutex:互斥對象句柄。為CreateMutex或OpenMutex函數(shù)的返回值。返回值:

      如果函數(shù)調(diào)用成功,那么返回值是非零值;如果函數(shù)調(diào)用失敗,那么返回值是零值。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      備注:

      如果調(diào)用線程不擁有互斥對象,ReleaseMutex函數(shù)失敗。一個線程通過調(diào)用等待函數(shù)擁有互斥對象。創(chuàng)建該互斥對象的線程也擁有互斥對象,而不需要調(diào)用等待函數(shù)。當互斥對象的所有者線程不再需要互斥對象時,它可以調(diào)用ReleaseMutex函數(shù)。

      當一個線程擁有一個互斥對象后,它可以用該互斥對象多次調(diào)用等待函數(shù)而不會阻塞。這防止一個線程等待一個它擁有的互斥對象時出現(xiàn)死鎖。不過,為了釋放所有權(quán),該線程必須為每一個等待操作調(diào)用一次ReleaseMutex函數(shù)。

      6.WaitForSingleObject 函數(shù)功能:

      當下列情況之一發(fā)生時該函數(shù)返回:(1)指定對象處于信號態(tài);(2)超時。函數(shù)原型:

      DWORD waitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);參數(shù):

      ·hHandle:等待對象句柄。若想了解指定句柄的對象類型列表,參閱下面?zhèn)渥⒉糠帧?/p>

      在Windows NT中,句柄必須有SYNCHRONIZE訪問權(quán)限。若想獲得更多的信息,請查看Standard Access Rights。

      ·dwMilliseconds:指定以毫秒為單位的超時間隔。如果超時,即使對象的狀態(tài)是非信號態(tài)的并且沒有完成,函數(shù)也返回。如果dwMilliseconds是0,函數(shù)測試對象的狀態(tài)并立即返回;如果dwMilliseconds是INFINITE,函數(shù)從不超時。返回值:

      如果函數(shù)調(diào)用成功,返回值表明引起函數(shù)返回的事件??赡苤等缦拢?/p>

      ·WAIT-ABANDONED:指定對象是互斥對象,在線程被終止前,線程沒有釋放互斥對象?;コ鈱ο蟮乃鶎訇P(guān)系被授予調(diào)用線程,并且該互斥對象被置為非信號態(tài)?!AIT-OBJECT-0:指定對象的狀態(tài)被置為信號態(tài)。

      ·WAIT-TIMEOUT:超時,并且對象的狀態(tài)為非信號態(tài)。

      如果函數(shù)調(diào)用失敗,返回值是WAIT-FAILED。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      備注:

      waitForSingleObjects函數(shù)決定等待條件是否被滿足。如果等待條件并沒有被滿足,調(diào)用線程進入一個高效的等待狀態(tài),當?shù)却凉M足條件時占用非常少的處理機時間。

      在運行前,一個等待函數(shù)修改同步對象類型的狀態(tài)。修改僅發(fā)生在引起函數(shù)返回的對象身上。例如,信號的計數(shù)減1。

      WaitForSingleObjects函數(shù)能等待的對象包括:Change notification(改變通告);Consoleinput(控制臺輸入);Event(事件);Job(作業(yè));Mutex(互斥對象);Process(進程);Semaphore(信號量);Thread(線程);Waitable timer(可等待定時器)。

      當使用等待函數(shù)或代碼直接或間接創(chuàng)建窗口時,一定要小心。如果一個線程創(chuàng)建了任何窗口,它必須處理進程消息。消息廣播被發(fā)送到系統(tǒng)的所有窗口。一個線程用沒有超時的等待函數(shù)也許會引起系統(tǒng)死鎖。間接創(chuàng)建窗口的兩個例子是DDE和COM CoInitialize。因此,如果用戶有一個創(chuàng)建窗口的線程,用MsgWaitForMultipleObjects或MsgWaitForMultipleObjectsEx函數(shù),而不要用SignalObjectAndWait函數(shù)。

      7.WaitForMultipleObjects 函數(shù)功能:

      WaitForMultipleObjects函數(shù)當下列條件之一滿足時返回:(1)任意一個或全部指定對象處于信號態(tài);(2)超時間隔以過。

      函數(shù)原型:

      DWORD WaitForMultipleObjects(DWORD nCount,CONST HANDLE *lpHandles, BOOL fWaitAll,DWORD dwMilliseconds);參數(shù):

      ·nCount:指定由lpHandles所指向的數(shù)組中的句柄對象數(shù)目MAXIMUM-WAIT-OBJECTS。

      ·lpHandles:指向?qū)ο缶浔鷶?shù)組的指針。該數(shù)組可以包含不同類型對象的句柄。在Windows NT中,句柄必須有SYNCHRONIZE訪問權(quán)限。若想獲得更多的信息,請查看Standard Access Rights。

      ·fWaitall:指定等待類型。如果為TRUE,當lpHandles指向的數(shù)組里的全部對象為信號態(tài)時,函數(shù)返回。如果為FALSE,當由lpHandles指向的數(shù)組里的任一對象為信號態(tài)時,函數(shù)返回。對于后者,返回值指出引起函數(shù)返回的對象。

      ·dwMilliseconds:指定以毫秒為單位的超時間隔。如果超時,即使bWaitAll參數(shù)指定的條件沒有滿足,函數(shù)也返回。如果dwMilliseconds是0,函數(shù)測試對象的狀態(tài)并立即返回;如果dwMilliseconds是INFINITE,函數(shù)從不超時。

      返回值:

      如果函數(shù)調(diào)用成功,返回值表明引起函數(shù)返回的事件??赡苤等缦拢?/p>

      ·WAIT-OBJECT-0到WAIT-OBJECT-0+nCount-1:如果bWaitAll為TRUE,那么返回值表明所有指定對象的狀態(tài)為信號態(tài)。如果bWaitAll為FALSE,那么返回值減去WAIT-OBJECT-0表明引起函數(shù)返回的對象的pHandles數(shù)組索引。如果多于一個對象變?yōu)樾盘枒B(tài),則返回的是數(shù)組索引最小的信號態(tài)對象索引。

      ·WAIT-ABANDONED-0到·WAIT-ABANDONED-0+ nCount-1:如果bWaitAll為TRUE,那么返回值表明所有指定對象的狀態(tài)為信號態(tài),并且至少一個對象是已放棄的互斥對象。如果bWaitAll為FALSE,那么返回值減去WAIT-OBJECT-0表明引起函數(shù)返回的放棄互斥對象的pHandles數(shù)組索引。

      ·WAIT-TIMEOUT:超時并且由參數(shù)bWaitAll指定的條件沒有滿足。

      如果函數(shù)調(diào)用失敗,返回值是WAIT-FAILED。若想獲得更多錯誤信息,請調(diào)用GetLastError函數(shù)。

      8.CreateSemapore 函數(shù)功能:

      該函數(shù)是創(chuàng)建一個有名或者無名信號對象。函數(shù)原型:

      HANDLE CreateSwmaphore(LPSECURITY-ATTRIBUTES lpAttributes,LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);參數(shù):

      ·lpAttributes:安全屬性。如果是NULL就表示要使用默認屬性?!InitialCount:Semapore的初值。必須大于或等于0,并且小于或等于MaximumCount?!MaximumCount:Semapore的最大值。這也就是在同一時間內(nèi)能夠鎖住Semapore之線程的最多個數(shù)。

      ·lpName:Semapore的名稱(一個字符串)。任何線程(或進程)都可以根據(jù)這一名稱引用到這個Semaphore。這個值可以是NULL,意思是產(chǎn)生一個沒有名字的Semaphore。

      返回值:

      如果成功就傳回一個handle,否則傳回NULL。不論哪一種情況,GetLastError都會傳回一個合理的結(jié)果。如果指定的Semaphore名稱已經(jīng)存在,則該函數(shù)還是成功的,GetLastError會傳回ERROR_ALREADY_EXISTS。

      9.ReleaseSemaphore 函數(shù)功能:

      該函數(shù)將指定信號對象的計數(shù)增加一個指定的數(shù)量。函數(shù)原型:

      BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount,LPLONG lpPreviousCount);參數(shù):

      ·hSemaphore:Semaphore的handle。

      ·lReleaseCount:Semaphore現(xiàn)值的增額。該值不可以是負值或0?!pPreviousCount:借此返回Semaphore原來的值。返回值:

      如果成功,則返回TRUE。否則返回FALSE。失敗時可調(diào)用GetLastError獲得原因。備注:

      無論ReleaseSemaphore對于Semaphore所造成的當前值怎樣增加,都絕對不會超過CreateSemaphore時所指定的ImaximumCount。

      請記住,lpPreviousCount所傳回來的是一個瞬間值。你不可以把lReleaseCount加上* lpPreviousCount,就當做是Semaphore的當前值,因為其他線程可能已經(jīng)改變了Semaphore的值。

      與mutex不同的是,調(diào)用ReleaseSemaphore的那個線程,并不一定就是調(diào)用WaitXxx 的那個線程。任何線程都可以在任何時候調(diào)用ReleaseSemaphore,解除被任何線程鎖定的Semaphore。10.InitializeCriticalSection 函數(shù)功能:

      該函數(shù)初始化臨界區(qū)對象。函數(shù)原型:

      VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 參數(shù):

      ·lpCriticalSection:指向臨界區(qū)對象的指針。備注:

      單進程的所有線程可以使用互斥同步機制的臨界區(qū)對象。但是,不能保證線程獲得臨界區(qū)所有權(quán)的順序,系統(tǒng)將對所有線程公平處理。

      進程負責分配臨界區(qū)對象使用的存儲空間,這可以通過聲明CRITICAL_SECTION類型的變量來完成。在使用臨界區(qū)之前,該進程的一些線程必須使用InitializeCriticalSection或InitializeCriticalSectionAndSectiom函數(shù)來初始化該臨界區(qū)對象。

      11.EnterCriticalSection 函數(shù)功能:該函數(shù)是等待指定臨界區(qū)對象的所有權(quán)。當調(diào)用線程被賦予所有權(quán)時,該函數(shù)返回。

      函數(shù)原型:

      VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 參數(shù):

      ·lpCriticalSection:指向臨界區(qū)對象的指針。12.LeaveCriticalSection 函數(shù)功能:該函數(shù)釋放指定臨界區(qū)對象的所有權(quán)。函數(shù)原型:

      VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 參數(shù):

      ·lpCriticalSection:指向臨界區(qū)對象的指針。4.1.5參考源代碼

      下面的程序已經(jīng)在Windows 2000/XP上實現(xiàn)。用VC6.0創(chuàng)建源文件,將輸入文件命名為thread.dat并放在與源文件相同的文件夾內(nèi),編譯運行即可(本節(jié)中的參考源代碼僅供參考)。

      #include “windows.h” #include #include #include #include #include #include

      #define READER 'R'

      // 讀者 #define WRITER 'W'

      // 寫者

      #define INTE_PER_SEC 1000

      // 每秒時鐘中斷數(shù)目。#define MAX_THREAD_NUM 64

      // 最大線程數(shù)目 #define MAX_FILE_NUM 32

      // 最大數(shù)據(jù)文件數(shù)目 #define MAX_STR_LEN 32

      // 字符串長度

      int readcount=0;

      // 讀者數(shù)目 int writecount=0;

      // 寫者數(shù)目

      CRITICAL_SECTION RP_Write;

      //臨界區(qū) CRITICAL_SECTION cs_Write;CRITICAL_SECTION cs_Read;struct ThreadInfo { int

      serial;

      // 線程序號

      char entity;

      //線程類別(判斷讀者線程還是寫者線程)double delay;double persist;};

      /////////////////////////////////////////////////////////////////////////// // 讀者優(yōu)先--讀者線程 //p:讀者線程信息

      void RP_ReaderThread(void* p){

      //互斥變量

      HANDLE h_Mutex;h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,“mutex_for_readcount”);

      DWORD wait_for_mutex;

      //等待互斥變量所有權(quán) DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 讀文件持續(xù)時間 int m_serial;

      //線程序號 //從參數(shù)中獲得信息

      m_serial=((ThreadInfo*)(p))->serial;m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);Sleep(m_delay);

      //延遲等待

      printf(“Reader thread %d sents the reading require.n”,m_serial);

      // 等待互斥信號,保證對readcount的訪問、修改互斥 wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//讀者數(shù)目增加 readcount++;if(readcount==1){

      //第一個讀者,等待資源

      EnterCriticalSection(&RP_Write);} ReleaseMutex(h_Mutex);

      //釋放互斥信號

      //讀文件

      printf(“Reader thread %d begins to read file.n”,m_serial);Sleep(m_persist);

      // 退出線程

      printf(“Reader thread %d finished reading file.n”,m_serial);//等待互斥信號,保證對readcount的訪問、修改互斥 wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//讀者數(shù)目減少 readcount--;if(readcount==0){

      //如果所有讀者讀完,喚醒寫者

      LeaveCriticalSection(&RP_Write);} ReleaseMutex(h_Mutex);

      //釋放互斥信號 }

      /////////////////////////////////////////////////////////////////////////// // 讀者優(yōu)先--寫者線程 //p:寫者線程信息

      void RP_WriterThread(void* p){ DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 寫文件持續(xù)時間 int m_serial;

      //線程序號 //從參數(shù)中獲得信息

      m_serial=((ThreadInfo*)(p))->serial;m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);Sleep(m_delay);

      //延遲等待

      printf(“Writer thread %d sents the writing require.n”,m_serial);// 等待資源

      EnterCriticalSection(&RP_Write);

      //寫文件 printf(“Writer thread %d begins to Write to the file.n”,m_serial);Sleep(m_persist);

      // 退出線程

      printf(“Writer thread %d finished Writing to the file.n”,m_serial);//釋放資源

      LeaveCriticalSection(&RP_Write);}

      /////////////////////////////////////////////////////////////////////////// // 讀者優(yōu)先處理函數(shù) //file:文件名

      void ReaderPriority(char* file){ DWORD n_thread=0;

      //線程數(shù)目 DWORD thread_ID;

      //線程ID DWORD wait_for_all;

      //等待所有線程結(jié)束 //互斥對象

      HANDLE h_Mutex;h_Mutex=CreateMutex(NULL,FALSE,“mutex_for_readcount”);

      //線程對象的數(shù)組

      HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];

      readcount=0;

      // 初始化 readcount

      InitializeCriticalSection(&RP_Write);

      //初始化臨界區(qū) ifstream inFile;inFile.open(file);

      //打開文件 printf(“Reader Priority:nn”);while(inFile){

      //讀入每一個讀者、寫者的信息

      inFile>>thread_info[n_thread].serial;

      inFile>>thread_info[n_thread].entity;

      inFile>>thread_info[n_thread].delay;

      inFile>>thread_info[n_thread++].persist;

      inFile.get();} for(int i=0;i<(int)(n_thread);i++){

      if(thread_info[i].entity==READER || thread_info[i].entity=='R')

      {

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_ReaderThread),&thread_info[i],0,&thread_ID);//創(chuàng)建讀者線程

      } else{

      //創(chuàng)建寫者線程

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),&thread_info[i],0,&thread_ID);

      } }

      //等待所有線程結(jié)束

      wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);printf(“All reader and writer have finished operating.n”);}

      /////////////////////////////////////////////////////////////////////////// // 寫者優(yōu)先--讀者線程 //p:讀者線程信息

      void WP_ReaderThread(void* p){

      //互斥變量

      HANDLE h_Mutex1;h_Mutex1=OpenMutex(MUTEX_ALL_ACCESS,FALSE,“mutex1”);HANDLE h_Mutex2;h_Mutex2=OpenMutex(MUTEX_ALL_ACCESS,FALSE,“mutex2”);

      DWORD wait_for_mutex1;

      //等待互斥變量所有權(quán) DWORD wait_for_mutex2;DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 讀文件持續(xù)時間 int m_serial;

      //線程序號 //從參數(shù)中獲得信息

      m_serial=((ThreadInfo*)(p))->serial;m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);Sleep(m_delay);

      //延遲等待

      printf(“Reader thread %d sents the reading require.n”,m_serial);wait_for_mutex1= WaitForSingleObject(h_Mutex1,-1);//進入讀者臨界區(qū)

      EnterCriticalSection(&cs_Read);// 阻塞互斥對象mutex2,保證對readcount的訪問、修改互斥 wait_for_mutex2= WaitForSingleObject(h_Mutex2,-1);//修改讀者數(shù)目 readcount++;if(readcount==1){

      //如果是第一個讀者,等待寫者寫完

      EnterCriticalSection(&cs_Write);} ReleaseMutex(h_Mutex2);

      //釋放互斥信號mutex2 // 讓其他讀者進入臨界區(qū)

      LeaveCriticalSection(&cs_Write);ReleaseMutex(h_Mutex1);//讀文件

      printf(“Reader thread %d begins to read file.n”,m_serial);Sleep(m_persist);// 退出線程

      printf(“Reader thread %d finished reading file.n”,m_serial);// 阻塞互斥對象mutex2,保證對readcount的訪問、修改互斥 wait_for_mutex2= WaitForSingleObject(h_Mutex2,-1);readcount--;if(readcount==0){

      // 最后一個讀者,喚醒寫者

      LeaveCriticalSection(&cs_Write);} ReleaseMutex(h_Mutex2);

      //釋放互斥信號 } /////////////////////////////////////////////////////////////////////////// // 寫者優(yōu)先--寫者線程 //p:寫者線程信息

      void WP_WriterThread(void* p){ DWORD m_delay;

      // 延遲時間

      DWORD m_persist;

      // 寫文件持續(xù)時間 int m_serial;

      //線程序號 DWORD wait_for_mutex3;//互斥對象

      HANDLE h_Mutex3;h_Mutex3= OpenMutex(MUTEX_ALL_ACCESS,FALSE,“mutex3”);

      //從參數(shù)中獲得信息

      m_serial=((ThreadInfo*)(p))->serial;m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);Sleep(m_delay);

      //延遲等待 printf(“Writer thread %d sents the writing require.n”,m_serial);

      // 阻塞互斥對象mutex3,保證對writecount的訪問、修改互斥 wait_for_mutex3= WaitForSingleObject(h_Mutex3,-1);writecount++;

      //修改讀者數(shù)目 if(writecount==1){

      //第一個寫者,等待讀者讀完

      EnterCriticalSection(&cs_Read);} ReleaseMutex(h_Mutex3);

      //進入寫者臨界區(qū)

      EnterCriticalSection(&cs_Write);//寫文件

      printf(“Writer thread %d begins to Write to the file.n”,m_serial);Sleep(m_persist);

      // 退出線程

      printf(“Writer thread %d finishing Writing to the file.n”,m_serial);

      //離開臨界區(qū)

      LeaveCriticalSection(&cs_Write);

      // 阻塞互斥對象mutex3,保證對writecount的訪問、修改互斥 wait_for_mutex3= WaitForSingleObject(h_Mutex3,-1);writecount--;

      //修改讀者數(shù)目 if(writecount==0){

      //寫者寫完,讀者可以讀

      LeaveCriticalSection(&cs_Read);} ReleaseMutex(h_Mutex3);}

      /////////////////////////////////////////////////////////////////////////// // 寫者優(yōu)先處理函數(shù) //file:文件名

      void WriterPriority(char* file){ DWORD n_thread=0;

      //線程數(shù)目 DWORD thread_ID;

      //線程ID DWORD wait_for_all;

      //等待所有線程結(jié)束

      //互斥對象

      HANDLE h_Mutex1;h_Mutex1=CreateMutex(NULL,FALSE,“mutex1”);HANDLE h_Mutex2;h_Mutex2=CreateMutex(NULL,FALSE,“mutex2”);HANDLE h_Mutex3;h_Mutex3=CreateMutex(NULL,FALSE,“mutex3”);

      //線程對象

      HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];

      readcount=0;

      // 初始化 readcount writecount=0;

      // 初始化writecount InitializeCriticalSection(&cs_Write);

      //初始化臨界區(qū) InitializeCriticalSection(&cs_Read);ifstream inFile;inFile.open(file);

      //打開文件 printf(“Writer Priority:nn”);while(inFile){

      //讀入每一個讀者、寫者的信息

      inFile>>thread_info[n_thread].serial;

      inFile>>thread_info[n_thread].entity;

      inFile>>thread_info[n_thread].delay;

      inFile>>thread_info[n_thread++].persist;

      inFile.get();} for(int i=0;i<(int)(n_thread);i++){

      if(thread_info[i].entity==READER || thread_info[i].entity=='R')

      {

      //創(chuàng)建讀者線程

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),&thread_info[i],0,&thread_ID);

      } else{

      //創(chuàng)建寫者線程

      h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_WriterThread),&thread_info[i],0,&thread_ID);

      } }

      //等待所有線程結(jié)束

      wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);printf(“All reader and writer have finished operating.n”);} /////////////////////////////////////////////////////////////////////////////// //主函數(shù)

      int main(int argc,char* argv[]){ char ch;

      while(true){

      //打印提示信息

      printf(“************************************************n”);

      printf(“

      1:Reader Priorityn”);

      printf(“

      2:Writer Priorityn”);

      printf(“

      3:Exit Priorityn”);

      printf(“************************************************n”);

      printf(“Enter your choice(1,2 or 3): ”);

      //如果輸入信息不正確,繼續(xù)輸入

      do{

      ch=(char)_getch();

      }while(ch!= '1' &&ch!= '2' && ch!= '3');

      system(“cls”);

      //選擇3,返回

      if(ch=='3')

      return 0;

      //選擇1,讀者優(yōu)先

      else if(ch=='1')

      ReaderPriority(“thread.dat”);

      //選擇2,寫者優(yōu)先

      else if(ch=='2')

      WriterPriority(“thread.dat”);

      //結(jié)束

      printf(“nPress Any Key To Continue: ”);

      _getch();

      system(“cls”);} return 0;}

      說明:

      在Win32 API中,互斥對象Mutex與P、V中的互斥信號量有類似的地方,但也有不同:在P、V操作中的互斥信號量可以有一個任意大小的初值,但互斥對象Mutex沒有,它可以被看成是初值為1的互斥信號量。而且一個線程在取得Mutex的所有權(quán)之后,即使不調(diào)用ReleaseMutex函數(shù),在線程結(jié)束時,線程也會自動釋放Mutex的所有權(quán)。

      臨界區(qū)對象CriticalSection則與P、V操作中初值為1的互斥信號量語意相同。它在線程結(jié)束時會將CriticalSection的所有權(quán)傳遞給它的同類型線程。這樣就可以滿足在一個線程中申請所有權(quán),在另一個線程釋放所有權(quán)的要求。在讀者優(yōu)先中的write互斥信號量以及寫者優(yōu)先中的read和write互斥信號量就應該用CriticalSection實現(xiàn)而不應該用Mutex。

      用WaitForSingleSignal函數(shù)可以獲得一個Mutex的所有權(quán),類似于P操作,而ReleaseMutex函數(shù)可以釋放一個Mutex的所有權(quán),類似于V操作。

      用EnterCriticalSection函數(shù)可以進入一個CriticalSection,類似于P操作,而LeaveCriticalSection函數(shù)離開一個CriticalSection,類似于V操作。

      備注:

      ReaderPriority和WritePriority函數(shù)最后都有

      wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);是因為主函數(shù)要等待所有的線程都結(jié)束之后才退出。因為不知道有多少線程,所以源文件最初有:

      #define MAX_THREAD_NUM 64 //最大線程數(shù)目

      即線程最多不能超過MAX_THREAD_NUM個。線程對象的數(shù)組大小為MAX_THREAD_NUM。如果創(chuàng)建的線程沒有那么多,空間會有浪費,但是可以達到犧牲空間來節(jié)省時間的目的。

      有的書上還有其他的處理方法。一種是在主函數(shù)的最后加上Sleep(1000),即通過主函數(shù)睡眠的方法等待其他線程結(jié)束,這當然不是一種很好的方法,因為睡眠等待的時間沒法控制。另一種方法是增加循環(huán)變量threadCount(線程的個數(shù)),每個線程結(jié)束的就會執(zhí)行語句

      threadCount--;主函數(shù)的最后測試:

      while(threadcount>0);但是這種方式會讓主函數(shù)循環(huán)等待,浪費了CPU資源。

      相比之下,考慮到運行效率,還是實例中給出的方法比較好寫些。

      第二篇:操作系統(tǒng)讀者寫者實驗報告

      目錄

      一 設計概述 ……………………………………………………2

      二 設計目的與內(nèi)容 ……………………………………………3

      三 設計分析 ……………………………………………………4

      四 程序?qū)崿F(xiàn) ……………………………………………………5

      五 程序調(diào)試 ……………………………………………………6

      六 結(jié)果分析和討論 ……………………………………………6

      七 心得體會 ……………………………………………………7

      八 源代碼 ………………………………………………………7

      一 設計概述

      所謂讀者寫者問題,是指保證一個writer進程必須與其他進程互斥地訪問共享對象的同步問題。

      讀者寫者問題可以這樣的描述,有一群寫者和一群讀者,寫者在寫同一本書,讀者也在讀這本書,多個讀者可以同時讀這本書,但是,只能有一個寫者在寫書,并且,讀者必寫者優(yōu)先,也就是說,讀者和寫者同時提出請求時,讀者優(yōu)先。當讀者提出請求時需要有一個互斥操作,另外,需要有一個信號量S來當前是否可操作。

      信號量機制是支持多道程序的并發(fā)操作系統(tǒng)設計中解決資源共享時進程間的同步與互斥的重要機制,而讀者寫者問題則是這一機制的一個經(jīng)典范例。

      與記錄型信號量解決讀者—寫者問題不同,信號量機制它增加了一個限制,即最多允許RN個讀者同時讀。為此,又引入了一個信號量L,并賦予初值為RN,通過執(zhí)行wait(L,1,1)操作,來控制讀者的數(shù)目,每當有一個讀者進入時,就要執(zhí)行wait(L,1,1)操作,使L的值減1。當有RN個讀者進入讀后,L便減為0,第RN+1 個讀者要進入讀時,必然會因wait(L,1,1)操作失敗而堵塞。對利用信號量來解決讀者—寫者問題的描述如下: Var RN integer;L,mx:semaphore: =RN,1; Begin Parbegin Reader :begin Repeat Swait(L,1,1);Swait(mx,1,0);.Perform reader operation;Ssignal(L,1);Until false;End Writer :begin Repeat Swait(mx ,1,1,l,RN,0);Perform writer operation;Ssignal(mx,1);Until false;End Parend End 其中,Swait(mx,1,0)語句起著開關(guān)作用,只要無Writer進程進入些,mx=1,reader進程就都可以進入讀。但是要一旦有Writer進程進入寫時,其MX=0,則任何reader進程就都無法進入讀。Swait(mx ,1,1,l,RN,0)語句表示僅當既無Write進程在寫(mx=1),又無reader進程在讀(L=RN)時,writer進程才能進入臨界區(qū)寫。

      本設計方案就是通過利用記錄型信號量對讀者寫者問題的解決過程進行模擬演示,形象地闡述記錄型信號量機制的工作原理。

      二 設計目的與內(nèi)容

      一 實驗目的

      l.用信號量來實現(xiàn)讀者寫者問題。

      2.理解和運用信號量、PV原語、進程間的同步互斥關(guān)系等基本知識。

      二、二 實驗內(nèi)容

      讀者寫者問題的定義如下:有一個許多進程共享的數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)可以是一個文件或者主存的一塊空間;有一些只讀取這個數(shù)據(jù)區(qū)的進程(Reader)和一些只往數(shù)據(jù)區(qū)寫數(shù)據(jù)的進程(Writer),此外還需要滿足以下條件:

      (1)任意多個讀進程可以同時讀這個文件;(2)一次只有一個寫進程可以往文件中寫;

      (3)如果一個寫進程正在進行操作,禁止任何讀進程度文件。我們需要分兩種情況實現(xiàn)該問題:

      讀優(yōu)先:要求指一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。

      寫優(yōu)先:一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作后才開始讀操作。

      三設計分析

      在Windows 7 環(huán)境下,創(chuàng)建一個包含n 個線程的控制臺進程。用這n 個線程來表示n個讀者或?qū)懻?。每個線程按相應測試數(shù)據(jù)文件的要求,進行讀寫操作。請用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者-寫者問題。

      讀者-寫者問題的讀寫操作限制:

      讀者-寫者的讀寫限制(包括讀者優(yōu)先和寫者優(yōu)先)1)寫-寫互斥,即不能有兩個寫者同時進行寫操作

      2)讀-寫互斥,即不能同時有一個讀者在讀,同時卻有一個寫者在寫 3)讀讀允許,即可以有2個以上的讀者同時讀

      將所有的讀者和所有的寫者分別放進兩個等待隊列中,當讀允許時就讓讀者隊列釋放一個或多個讀者,當寫允許時,釋放第一個寫者操作。讀者寫者問題的定義如下:有一個許多進程共享的數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)可以是一個文件或者主存的一塊空間;有一些只讀取這個數(shù)據(jù)區(qū)的進程(Reader)和一些只往數(shù)據(jù)區(qū)寫數(shù)據(jù)的進程(Writer),此外還需要滿足以下條件:1)任意多個讀進程可以同時讀這個文件;2)一次只有一個寫進程可以往文件中寫;3)如果一個寫進程正在進行操作,禁止任何讀進程度文件。我們需要分兩種情況實現(xiàn)該問題:

      讀優(yōu)先:要求指一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。寫優(yōu)先:一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作后才開始讀操作。

      四 程序?qū)崿F(xiàn)

      程序由兩部分組成:

      1。讀者-寫者模塊:包括系統(tǒng)調(diào)用接口,讀者-寫者活動描述主程序。系統(tǒng)接口主要功能是通過管道向父進程發(fā)送系統(tǒng)調(diào)用命令,并讀取父進程送來的返回值。

      讀者-寫者活動程序根據(jù)臨界資源的共享,互斥原則編制,具體見源程序。2。主控模塊:主控模塊實現(xiàn)系統(tǒng)初始化系統(tǒng)調(diào)用命令接收與解釋執(zhí)行,系統(tǒng)調(diào)用功能的實現(xiàn)(包括信號量機制),及讀者-寫者活動過程記錄與顯示。

      初始化系統(tǒng)環(huán)境 建立通信管道

      啟動讀者-寫者進程 接收系統(tǒng)調(diào)用命令 解釋執(zhí)行

      系統(tǒng)初始化模塊 管道建立模塊 進程啟動模塊 命令解釋模塊 Wait()Signal()Wakeup()Block()

      五 程序調(diào)試

      測試數(shù)據(jù)文件格式: 測試數(shù)據(jù)文件包括n 行測試數(shù)據(jù),分別描述創(chuàng)建的n 個線程是讀者還是寫者,以及讀寫操作的開始時間和持續(xù)時間。每行測試數(shù)據(jù)包括四個字段,各字段間用空格分隔。第一字段為一個正整數(shù),表示線程序號。第二字段表示相應線程角色,R 表示讀者是,W 表示寫者。第三字段為一個正數(shù),表示讀寫操作的開始時間。線程創(chuàng)建后,延時相應時間(單位為秒)后發(fā)出對共享資源的讀寫申請。第四字段為一個正數(shù),表示讀寫操作的持續(xù)時間。當線程讀寫申請成功后,開始對共享資源的讀寫操作,該操作持續(xù)相應時間后結(jié)束,并釋放共享資源。

      六 結(jié)果分析和討論

      在讀者寫者同時在隊列中等待申請資時,讀者優(yōu)先調(diào)用資源。而且如果一個讀者申請進行讀操作時已有另一讀者正在進行讀操作,則該讀者可直接開始讀操作,即讀讀允許。

      進程1是R操作,在時間3時進入隊列,運行時間是5,在它進入時沒有進程占用資源,它既占用資源;知道它釋放資源,等候的進程有3,4,5;

      進程2是W操作,在時間16時進入隊列,運行時間是5,在它進入時進程4占用資源,它等待資源,當4釋放時占用資源;

      進程3是R操作,在時間5時進入隊列,運行時間是2,在它進入時進程1占用資源,它等待資源,當進程1釋放資源后,由于讀者優(yōu)先,進程3,5同時調(diào) 運資源;

      進程4是R操作,在時間6時進入隊列,運行時間是5,在它進入時進程1占用資源,它等待資源,當進程1釋放資源后,由于讀者優(yōu)先,進程3,5占用資源,它依然等待,直到進程3,5都結(jié)束;

      進程5是W操作,在時間4時進入隊列,運行時間是3, 在它進入時進程1占用資源,它等待資源,當進程1釋放資源后,由于讀者優(yōu)先,進程3,5同時調(diào)運資源;

      七 心得體會

      這一次課程設計,讓我體會很深刻。讀者-寫者問題經(jīng)典的線程同步問題的一個模型。經(jīng)過讀者寫者問題的編寫,我對同步機構(gòu)應用有了深入的了解。懂得了運用信號量實現(xiàn)進程間的互斥。實現(xiàn)了不讓共享資源同時修改。用信號量上的原語操作使臨界段問題的解決比較簡單明了了。讀者寫者問題的編寫,花的時間很多,也學到很多東西。了解支持多道程序的并發(fā)操作系統(tǒng)設計中解決資源共享時進程間的同步與互斥的信號量機制。幾天的試驗,雖然難度有點大,但只要自己花時間去學習,還是會攻克困難的。

      總之,每一次課程設計不僅是我們學習的好機會,而且是我們鍛煉實際動手能力的平臺,雖然有難度的東西總會讓人很抵觸,比如在課設過程中有很多郁悶的時候,一個小小的錯誤一不小心就花去了自己一上午的時間,所以在這個過程中能夠磨練人的意志與耐心,最后感謝老師的指導與監(jiān)督。

      八 源代碼

      #include #include #include #include #include #include #define MAX_PERSON 100 #define READER 0 //讀者 #define WRITER 1 //寫者 #define END-1 #define R READER #define W WRITER typedef struct _Person { HANDLE m_hThread;//定義處理線程的句柄 int m_nType;//進程類型(讀寫)int m_nStartTime;//開始時間 int m_nWorkTime;//運行時間 int m_nID;//進程號 }Person;Person g_Persons[MAX_PERSON];int g_NumPerson = 0;long g_CurrentTime= 0;//基本時間片數(shù) int g_PersonLists[] = {//進程隊列 1, R, 3, 5, 2, W, 4, 5, 3, R, 5, 2, 4, R, 6, 5, 5, W, 5.1, 3, END,};int g_NumOfReading = 0;int g_NumOfWriteRequest = 0;//申請寫進程的個數(shù) HANDLE g_hReadSemaphore;//讀者信號 HANDLE g_hWriteSemaphore;//寫者信號 bool finished = false;//所有的讀完成 //bool wfinished = false;//所有的寫完成 void CreatePersonList(int *pPersonList);bool CreateReader(int StartTime,int WorkTime,int ID);bool CreateWriter(int StartTime,int WorkTime,int ID);DWORD WINAPI ReaderProc(LPVOID lpParam);DWORD WINAPI WriterProc(LPVOID lpParam);int main(){ g_hReadSemaphore = CreateSemaphore(NULL,1,100,NULL);//創(chuàng)建信號燈,當前可用的資源數(shù)為1,最大為100 g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL);//創(chuàng)建信號燈,當前可用的資源數(shù)為1,最大為100 CreatePersonList(g_PersonLists);// Create All the reader and writers printf(“Created all the reader and writern...n”);g_CurrentTime = 0;while(true){ g_CurrentTime++;Sleep(300);// 300 ms printf(“CurrentTime = %dn”,g_CurrentTime);if(finished)return 0;} // return 0;} void CreatePersonList(int *pPersonLists){ int i=0;int *pList = pPersonLists;bool Ret;while(pList[0]!= END){ switch(pList[1]){ case R: Ret = CreateReader(pList[2],pList[3],pList[0]);//351,w452,523,654 break;case W: Ret = CreateWriter(pList[2],pList[3],pList[0]);break;} if(!Ret)printf(“Create Person %d is wrongn”,pList[0]);pList += 4;// move to next person list } } DWORD WINAPI ReaderProc(LPVOID lpParam)//讀過程 { Person *pPerson =(Person*)lpParam;// wait for the start time while(g_CurrentTime!= pPerson->m_nStartTime){ } printf(“Reader %d is Requesting...n”,pPerson->m_nID);printf(“nn************************************************n”);// wait for the write request WaitForSingleObject(g_hReadSemaphore,INFINITE);if(g_NumOfReading ==0){ WaitForSingleObject(g_hWriteSemaphore,INFINITE);} g_NumOfReading++;ReleaseSemaphore(g_hReadSemaphore,1,NULL);pPerson->m_nStartTime = g_CurrentTime;printf(“Reader %d is Reading the Shared Buffer...n”,pPerson->m_nID);printf(“nn************************************************n”);while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime){} printf(“Reader %d is Exit...n”,pPerson->m_nID);printf(“nn************************************************n”);WaitForSingleObject(g_hReadSemaphore,INFINITE);g_NumOfReading--;if(g_NumOfReading == 0){ReleaseSemaphore(g_hWriteSemaphore,1,NULL);//此時沒有讀者,可以寫 } ReleaseSemaphore(g_hReadSemaphore,1,NULL);if(pPerson->m_nID == 4)finished = true;//所有的讀寫完成 ExitThread(0);return 0;} DWORD WINAPI WriterProc(LPVOID lpParam){ Person *pPerson =(Person*)lpParam;// wait for the start time while(g_CurrentTime!= pPerson->m_nStartTime){} printf(“Writer %d is Requesting...n”,pPerson->m_nID);printf(“nn************************************************n”);WaitForSingleObject(g_hWriteSemaphore,INFINITE);// modify the writer's real start time pPerson->m_nStartTime = g_CurrentTime;printf(“Writer %d is Writting the Shared Buffer...n”,pPerson->m_nID);while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime){} printf(“Writer %d is Exit...n”,pPerson->m_nID);printf(“nn************************************************n”);//g_NumOfWriteRequest--;ReleaseSemaphore(g_hWriteSemaphore,1,NULL);if(pPerson->m_nID == 4)finished = true;//所有的讀寫完成 ExitThread(0);return 0;} bool CreateReader(int StartTime,int WorkTime,int ID){ DWORD dwThreadID;if(g_NumPerson >= MAX_PERSON)return false;Person *pPerson = &g_Persons[g_NumPerson];pPerson->m_nID = ID;pPerson->m_nStartTime = StartTime;pPerson->m_nWorkTime = WorkTime;pPerson->m_nType = READER;g_NumPerson++;// Create an New Thread pPerson->m_hThread= CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);if(pPerson->m_hThread == NULL)return false;return true;} bool CreateWriter(int StartTime,int WorkTime,int ID){ DWORD dwThreadID;if(g_NumPerson >= MAX_PERSON)return false;Person *pPerson = &g_Persons[g_NumPerson];pPerson->m_nID = ID;pPerson->m_nStartTime = StartTime;pPerson->m_nWorkTime = WorkTime;pPerson->m_nType = WRITER;g_NumPerson++;// Create an New Thread pPerson->m_hThread= CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID);if(pPerson->m_hThread == NULL)return false;return true;}

      第三篇:操作系統(tǒng)課程設計報告——讀者寫者問題

      操作系統(tǒng)課程設計

      題:讀者寫者問題 姓

      名:赫前進 班

      級:1020552 學

      號102055211 指導教師:葉瑤 提交時間:2012/12/30

      (一)實驗目的

      1.進一步理解 “臨界資源” 的概念;

      2.把握在多個進程并發(fā)執(zhí)行過程中對臨界資源訪問時的必要約束條件; 3.理解操作系統(tǒng)原理中 “互斥” 和 “同步” 的涵義。

      (二)實驗內(nèi)容

      利用程序設計語言編程,模擬并發(fā)執(zhí)行進程的同步與互斥(要求:進程數(shù)目不少于 3 個)。

      (三)、程序分析

      讀者寫者問題的定義如下:有一個許多進程共享的數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)可以是一個文件或者主存的一塊空間;有一些只讀取這個數(shù)據(jù)區(qū)的進程(Reader)和一些只往數(shù)據(jù)區(qū)寫數(shù)據(jù)的進程(Writer),此外還需要滿足以下條件:(1)任意多個讀進程可以同時讀這個文件;(2)一次只有一個寫進程可以往文件中寫;

      (3)如果一個寫進程正在進行操作,禁止任何讀進程度文件。

      實驗要求用信號量來實現(xiàn)讀者寫者問題的調(diào)度算法。實驗提供了signal類,該類通過P()、V()兩個方法實現(xiàn)了P、V原語的功能。實驗的任務是修改Creat_Writer()添加寫者進程,Creat_Reader()創(chuàng)建讀者進程。Reader_goon()讀者進程運行函數(shù)。讀優(yōu)先:要求指一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。

      讀者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一讀者正在進行讀操作,則該讀者可直接開始讀操作。

      寫優(yōu)先:一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作后才開始讀操作。

      寫者優(yōu)先的附加限制:如果一個讀者申請進行讀操作時已有另一寫者在等待訪問共享資源,則該讀者必須等到?jīng)]有寫者處于等待狀態(tài)后才能開始讀操作。

      在Windows 7 環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含 n 個線程。用這 n 個線程來表示 n 個讀者或?qū)懻?。每個線程按相應測試數(shù)據(jù)文件(格式見下)的要求進行讀寫操作。用信號量機制分別實現(xiàn)讀者優(yōu)先和寫者優(yōu)先的讀者/寫者問題。運行結(jié)果顯示要求:要求在每個線程創(chuàng)建、發(fā)出讀寫操作申請、開始讀寫操作和結(jié)束讀寫操作時分別顯示一行提示信息,以確定所有處理都遵守相應的讀寫操作限制。

      測試數(shù)據(jù)文件包括 n 行測試數(shù)據(jù),分別描述創(chuàng)建的 n 個線程是讀者還是寫者,以及讀寫操作的開始時間和持續(xù)時間。每行測試數(shù)據(jù)包括4個字段,各個字段間用空格分隔。

      ?

      第一個字段為一個正整數(shù),表示線程序號

      ?

      第二個字段表示相應線程角色,R 表示讀者,W 表示寫者

      ?

      第三個字段為一個正數(shù),表示讀/寫操作的開始時間:線程創(chuàng)建后,延遲相應時間(單位為秒)后發(fā)出對共享資源的讀/寫請求

      ?

      第四個字段為一正數(shù),表示讀/寫操作的持續(xù)時間:線程讀寫請求成功后,開始對共享資源的讀/寫操作,該操作持續(xù)相應時間后結(jié)束,并釋放共享資源 例如: 1 R 3 5 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 讀者寫者問題是操作系統(tǒng)中經(jīng)典的互斥問題:一塊數(shù)據(jù)被多個讀者和寫者的訪問,需要考慮讀寫互斥、寫寫互斥(可以同時由多個讀者讀?。>唧w的又可以分為讀者優(yōu)先和寫者優(yōu)先兩類。讀者優(yōu)先算法:

      當新的讀者到來的時候,若當前正有讀者在進行讀操作,則該讀者無需等待前面的寫操作完成,直接進行讀操作。設置兩個互斥信號量:

      rwmutex 用于寫者與其他讀者/寫者互斥的訪問共享數(shù)據(jù) rmutex 用于讀者互斥的訪問讀者計數(shù)器readcount var rwmutex, rmutex : semaphore := 1,1 ; int readcount = 0;cobegin

      readeri begin // i=1,2,?.P(rmutex);

      Readcount++;

      If(readcount == 1)P(rwmutex);

      V(rmutex);

      讀數(shù)據(jù);

      P(rmutex);

      Readcount--;

      If(readcount == 0)V(rwmutex);

      V(rmutex);

      End

      Writerj begin // j = 1,2,?.P(rwmutex);

      寫更新;

      V(rwmutex);

      End Coend 寫者優(yōu)先: 條件:

      1)多個讀者可以同時進行讀

      2)寫者必須互斥(只允許一個寫者寫,也不能讀者寫者同時進行)

      3)寫者優(yōu)先于讀者(一旦有寫者,則后續(xù)讀者必須等待,喚醒時優(yōu)先考慮寫者)設置三個互斥信號量:

      rwmutex 用于寫者與其他讀者/寫者互斥的訪問共享數(shù)據(jù) rmutex 用于讀者互斥的訪問讀者計數(shù)器readcount nrmutex 用于寫者等待已進入讀者退出,所有讀者退出前互斥寫操作 var rwmutex, rmutex,nrmutex : semaphore := 1,1,1 ; int readcount = 0;cobegin

      readeri begin // i=1,2,?.P(rwmutex);

      P(rmutex);

      Readcount++;

      If(readcount == 1)P(nrmutex);//有讀者進入,互斥寫操作

      V(rmutex);

      V(rwmutex);// 及時釋放讀寫互斥信號量,允許其它讀、寫進程申請資源

      讀數(shù)據(jù);

      P(rmutex);

      Readcount--;

      If(readcount == 0)V(nrmutex);//所有讀者退出,允許寫更新

      V(rmutex);

      End

      Writerj begin // j = 1,2,?.P(rwmutex);// 互斥后續(xù)其它讀者、寫者

      P(nrmutex);//如有讀者正在讀,等待所有讀者讀完

      寫更新;

      V(nrmutex);//允許后續(xù)新的第一個讀者進入后互斥寫操作

      V(rwmutex);//允許后續(xù)新讀者及其它寫者

      End Coend //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*---------函數(shù)聲明---------*/ void Creat_Writer();

      //添加一個寫者 void Del_Writer();

      //刪除一個寫者 void Creat_Reader();

      //添加一個讀者

      void Reader_goon();

      //讀者進程運行函數(shù) void R_Wakeup();

      //喚醒等待讀者 void Del_Reader();

      //刪除一個讀者 void Show();

      //顯示運行狀態(tài)

      /*===============

      class

      signal

      ===============*/ class signal //信號量對象.{ private: int value;int queue;

      //用int型數(shù)據(jù)模擬等待隊列.public: signal();signal(int n);int P();//檢查臨界資源 int V();//釋放臨界資源 int Get_Value();int Get_Queue();};//////////////////////////////////////////////////////////////////// #include

      #include #include #include using namespace std;const int MaxThread=20;

      struct ThreadInfo

      {

      int num;

      char type;

      double start;

      double time;

      }thread_info[MaxThread];

      HANDLE hX;

      HANDLE hWsem;

      HANDLE thread[MaxThread];int readcount;double totaltime;

      void WRITEUNIT(int iProcess){

      printf(“Thread %d begins to write.n”,iProcess);

      Sleep((DWORD)(thread_info[iProcess-1].time*1000));

      printf(“End of thread %d for writing.n”,iProcess);}

      void READUNIT(int iProcess){

      printf(“Thread %d begins to read.n”,iProcess);

      Sleep((DWORD)(thread_info[iProcess-1].time*1000));

      printf(“End of thread %d for reading.n”,iProcess);}

      DWORD

      WINAPI

      reader(LPVOID

      lpVoid){

      int iProcess

      =

      *(int*)lpVoid;

      Sleep((DWORD)(thread_info[iProcess-1].start*1000));

      DWORD wait_for=WaitForSingleObject(hX,INFINITE);

      printf(“Thread %d requres reading.n”,iProcess);

      readcount++;

      if(readcount==1)WaitForSingleObject(hWsem,INFINITE);

      ReleaseMutex(hX);

      READUNIT(iProcess);

      wait_for=WaitForSingleObject(hX,INFINITE);

      readcount--;

      if(readcount==0)

      ReleaseSemaphore(hWsem,1,0);

      ReleaseMutex(hX);

      return iProcess;}

      DWORD

      WINAPI

      writer(LPVOID

      lpVoid){

      int iProcess

      =

      *(int*)lpVoid;

      Sleep((DWORD)(thread_info[iProcess-1].start*1000));

      printf(“Thread %d requres writing.n”,iProcess);

      DWORD wait_for=WaitForSingleObject(hWsem,INFINITE);

      WRITEUNIT(iProcess);

      ReleaseSemaphore(hWsem,1,0);

      return iProcess;}

      int main(){

      int threadNum;

      int threadcount;

      ifstream file;

      hX=CreateMutex(NULL, FALSE, NULL);

      hWsem=CreateSemaphore(NULL,1,1,NULL);

      //???

      readcount=0;

      threadcount=0;

      totaltime=0;

      file.open(“thread.dat”,ios::in);

      if(file==0)

      {

      printf(“File Open Error.n”);

      return 0;

      }

      while(file>>threadNum)

      {

      thread_info[threadNum-1].num=threadNum;

      file>>thread_info[threadNum-1].type;

      file>>thread_info[threadNum-1].start;

      file>>thread_info[threadNum-1].time;

      totaltime+=thread_info[threadNum-1].time;

      switch(thread_info[threadNum-1].type)

      {

      case 'W':

      printf(“Creating Thread %d writing.n”,thread_info[threadNum-1].num);

      thread[threadNum-1]

      =

      CreateThread(NULL, &thread_info[threadNum-1].num,0,0);

      break;

      case 'R':

      printf(“Creating Thread %d reading.n”,thread_info[threadNum-1].num);

      thread[threadNum-1]

      =

      CreateThread(NULL, &thread_info[threadNum-1].num,0,0);

      break;

      }

      threadcount++;

      }

      file.close();

      Sleep((DWORD)(totaltime*1000));

      return 1;} ////////////////////////////////////////////////////////////////////////////////// semaphore fmutex = 1 , rdcntmutex = 1;// fmutex--> access to file;rdcntmutex--> access to readcount int readcount = 0;void reader(){

      while(1)

      for 0,writer, for 0,reader,{

      P(rdcntmutex);

      if(readcount==0)

      P(fmutex);

      readcount = readcount + 1;

      V(rdcntmutex);

      // Do read operation

      P(rdcntmutex);

      readcount = readcount1;

      if(readcount==0)

      V(fmutex);

      V(rdcntmutex);

      } } void writer(){

      while(1)

      {

      P(wtcntmutex);

      if(writecount==0)

      P(queue);

      writecount = writecount + 1;

      V(wtcntmutex);

      P(fmutex);

      // Do write operation

      V(fmutex);

      P(wtcntmutex);

      writecount = writecount-1;

      if(writecount==0)

      V(queue);

      V(wtcntmutex);

      } }

      第四篇:操作系統(tǒng)實驗報告

      實驗二

      進程調(diào)度

      1.目的和要求

      通過這次實驗,理解進程調(diào)度的過程,進一步掌握進程狀態(tài)的轉(zhuǎn)變、進程調(diào)度的策略,進一步體會多道程序并發(fā)執(zhí)行的特點,并分析具體的調(diào)度算法的特點,掌握對系統(tǒng)性能的評價方法。

      2.實驗內(nèi)容

      閱讀教材《計算機操作系統(tǒng)》第二章和第三章,掌握進程管理及調(diào)度相關(guān)概念和原理。

      編寫程序模擬實現(xiàn)進程的輪轉(zhuǎn)法調(diào)度過程,模擬程序只對PCB進行相應的調(diào)度模擬操作,不需要實際程序。假設初始狀態(tài)為:有n個進程處于就緒狀態(tài),有m個進程處于阻塞狀態(tài)。采用輪轉(zhuǎn)法進程調(diào)度算法進行調(diào)度(調(diào)度過程中,假設處于執(zhí)行狀態(tài)的進程不會阻塞),且每過t個時間片系統(tǒng)釋放資源,喚醒處于阻塞隊列隊首的進程。

      程序要求如下:

      1)輸出系統(tǒng)中進程的調(diào)度次序; 2)計算CPU利用率。

      3.實驗環(huán)境

      Windows操作系統(tǒng)、VC++6.0 C語言

      4設計思想:

      (1)

      程序中進程可用PCB表示,其類型描述如下:

      struct PCB_type

      {

      int pid;

      //進程名 int

      state;

      //進程狀態(tài)

      2——表示“執(zhí)行”狀態(tài)

      1——表示“就緒”狀態(tài)

      0——表示“阻塞”狀態(tài)

      int cpu_time;//運行需要的CPU時間(需運行的時間片個數(shù))

      } 用PCB來模擬進程;

      (2)設置兩個隊列,將處于“就緒”狀態(tài)的進程PCB掛在隊列ready中;將處于“阻塞”狀態(tài)的進程PCB掛在隊列blocked中。隊列類型描述如下:

      struct QueueNode{

      struct PCB_type

      PCB;

      Struct QueueNode *next;} 并設全程量:

      struct QueueNode *ready_head=NULL,//ready隊列隊首指針

      *ready_tail=NULL , //ready隊列隊尾指針

      *blocked_head=NULL,//blocked隊列隊首指針 *blocked_tail=NULL;//blocked隊列隊尾指針(3)設計子程序:

      start_state();

      讀入假設的數(shù)據(jù),設置系統(tǒng)初始狀態(tài),即初始化就緒隊列和阻塞隊列。

      dispath();

      模擬調(diào)度,當就緒隊列的隊首進程運行一個時間片后,放到就緒隊列末尾,每次都是隊首進程進行調(diào)度,一個進程運行結(jié)束就從就緒隊列中刪除,當?shù)絫個時間片后,喚醒阻塞隊列隊首進程。

      calculate();

      就緒進程運行一次,usecpu加1,當就緒隊列為空時unusecpu加1,CPU利用率為use_cpu/(use_cpu+unuse_cpu)。

      5源代碼:

      #include #include

      struct PCB_type {

      int pid;

      //進程名

      int

      state;

      //進程狀態(tài)

      //2--表示“執(zhí)行”狀態(tài)

      //1--表示“就緒”狀態(tài)

      //0--表示“阻塞”狀態(tài)

      int cpu_time;//運行需要的CPU時間(需運行的時間片個數(shù))};struct QueueNode{

      struct PCB_type

      PCB;

      struct QueueNode *next;};struct QueueNode *ready_head=NULL,//ready隊列隊首指針

      *ready_tail=NULL,//ready隊列隊尾指針

      *block_head=NULL,//blocked隊列隊首指針

      *block_tail=NULL;

      //blocked隊列隊尾指針

      int use_cpu,unuse_cpu;

      void start_state()//讀入假設的數(shù)據(jù),設置系統(tǒng)初始狀態(tài) {

      int n,m;

      int i;

      struct QueueNode *p,*q;

      printf(“輸入就緒節(jié)點個數(shù)n:”);

      scanf(“%d”,&n);

      printf(“輸入阻塞節(jié)點個數(shù)m:”);

      scanf(“%d”,&m);

      p=(struct QueueNode *)malloc(sizeof(struct QueueNode));

      p->next =NULL;

      ready_head=ready_tail=p;

      for(i=0;i

      {

      p=(struct QueueNode *)malloc(sizeof(struct QueueNode));

      p->next =NULL;

      p->PCB.state=1;

      printf(“輸入就緒進程%d的pid和cpu_time:”,i+1);

      scanf(“%d%d”,&p->PCB.pid,&p->PCB.cpu_time);

      ready_tail->next=p;

      ready_tail=p;

      }

      q=(struct QueueNode *)malloc(sizeof(struct QueueNode));

      q->next =NULL;

      block_head=block_tail=q;

      for(i=0;i

      {

      q=(struct QueueNode *)malloc(sizeof(struct QueueNode));

      q->next=NULL;

      q->PCB.state=0;

      printf(“輸入阻塞進程%d的pid和cpu_time:”,i+1);

      scanf(“%d%d”,&q->PCB.pid,&q->PCB.cpu_time);

      block_tail->next=q;

      block_tail=q;

      }

      printf(“n處于就緒狀態(tài)的進程有:n”);

      p=ready_head->next;

      i=1;

      while(p)

      {printf(“進程%d的pid和cpu_time:%5d%5d%5dn“,i,p->PCB.pid,p->PCB.state,p->PCB.cpu_time);

      p=p->next;

      i++;

      } } void dispath()

      //模擬調(diào)度 {

      int x=0,t;

      use_cpu=0;

      unuse_cpu=0;

      printf(”輸入t:“);

      scanf(”%d“,&t);

      printf(”開始調(diào)度n“);

      while(ready_head!=ready_tail||block_head!=block_tail)

      {

      struct QueueNode *p,*q;

      if(ready_head!=ready_tail)

      {

      p=ready_head->next;

      ready_head->next=p->next;

      p->next=NULL;

      if(ready_head->next==NULL)

      {

      ready_tail=ready_head;

      }

      p->PCB.state=2;

      printf(”進程%d調(diào)度t“,p->PCB.pid);

      state和

      use_cpu++;

      x++;

      p->PCB.cpu_time--;

      if(p->PCB.cpu_time)

      {

      ready_tail->next=p;

      ready_tail=p;

      }

      else

      {

      printf(”進程%d完成t“,p->PCB.pid);

      free(p);

      }

      }

      else

      {

      unuse_cpu++;

      x++;

      printf(”空閑一個時間片t“);

      }

      if(x==t&&block_head!=block_tail)

      {

      q=block_head->next;

      block_head->next=q->next;

      q->next=NULL;

      if(block_head->next==NULL)

      {

      block_tail=block_head;

      }

      ready_tail->next=q;

      ready_tail=q;

      x=0;

      }

      } } void calculate()

      //計算CPU利用率 { printf(”ncpu的利用率%.2fn“,(float)use_cpu/(use_cpu+unuse_cpu));

      } void main(){start_state();

      dispath();

      calculate();} 6運行結(jié)果:

      7實驗總結(jié):

      實驗幫我復習了數(shù)據(jù)結(jié)構(gòu)和C語言,且鞏固課本知識,知道了如何定義結(jié)構(gòu)體,如何在鏈接隊列中增刪節(jié)點。模擬進程調(diào)度幫我們鞏固了進程三狀態(tài)之間的變遷。懂得調(diào)式的重要性??傊?,我們明白了理論聯(lián)系實際。多看書,多上機。

      實驗三

      可變分區(qū)存儲管理

      1.目的和要求

      通過這次實驗,加深對內(nèi)存管理的認識,進一步掌握內(nèi)存的分配、回收算法的思想。

      2.實驗內(nèi)容

      閱讀教材《計算機操作系統(tǒng)》第四章,掌握存儲器管理相關(guān)概念和原理。編寫程序模擬實現(xiàn)內(nèi)存的動態(tài)分區(qū)法存儲管理。內(nèi)存空閑區(qū)使用自由鏈管理,采用最壞適應算法從自由鏈中尋找空閑區(qū)進行分配,內(nèi)存回收時假定不做與相鄰空閑區(qū)的合并。

      假定系統(tǒng)的內(nèi)存共640K,初始狀態(tài)為操作系統(tǒng)本身占用64K。在t1時間之后,有作業(yè)A、B、C、D分別請求8K、16K、64K、124K的內(nèi)存空間;在t2時間之后,作業(yè)C完成;在t3時間之后,作業(yè)E請求50K的內(nèi)存空間;在t4時間之后,作業(yè)D完成。要求編程序分別輸出t1、t2、t3、t4時刻內(nèi)存的空閑區(qū)的狀態(tài)。

      3.實驗環(huán)境

      Windows操作系統(tǒng)、VC++6.0 C語言

      4.設計思想

      模擬內(nèi)存分配和回收,要設置兩個鏈隊列,一個空閑區(qū)鏈和一個占用區(qū)鏈,空閑區(qū)鏈節(jié)點有起始地址,大小和指向下一節(jié)點的指針等數(shù)據(jù)域,占用區(qū)鏈節(jié)點有起始地址,大小,作業(yè)名和指向下一節(jié)點的指針等數(shù)據(jù)域,本實驗用最壞適應算法,每次作業(yè)申請內(nèi)存都是從空閑鏈隊頭節(jié)點分配,如果相等,就刪除空閑頭結(jié)點,如果小于申請的,就不分配,否則就劃分內(nèi)存給作業(yè),剩下的內(nèi)存大小,重新插入空閑鏈隊,按從大到小,接著把作業(yè)占用的內(nèi)存放到占用區(qū)鏈節(jié)點的末尾。每次作業(yè)運行完,就要回收其占用的內(nèi)存大小,把作業(yè)節(jié)點按從大到小插入到空閑鏈隊中。5.源代碼:

      #include #include struct freelinkNode{ int len;int address;

      struct freelinkNode *next;};struct busylinkNode{ char name;

      int len;int address;struct busylinkNode *next;};struct freelinkNode *free_head=NULL;

      //自由鏈隊列(帶頭結(jié)點)隊首指針

      struct busylinkNode *busy_head=NULL;

      //占用區(qū)隊列隊(帶頭結(jié)點)首指針

      struct busylinkNode *busy_tail=NULL;

      //占用區(qū)隊列隊尾指針 void start(void)/* 設置系統(tǒng)初始狀態(tài)*/ { struct freelinkNode *p;

      struct busylinkNode *q;

      free_head=(struct freelinkNode*)malloc(sizeof(struct freelinkNode));

      free_head->next=NULL;// 創(chuàng)建自由鏈頭結(jié)點

      busy_head=busy_tail=(struct busylinkNode*)malloc(sizeof(struct busylinkNode));

      busy_head->next=NULL;// 創(chuàng)建占用鏈頭結(jié)點

      p=(struct freelinkNode *)malloc(sizeof(struct freelinkNode));

      p->address=64;

      p->len=640-64;//OS占用了64K

      p->next=NULL;

      free_head->next=p;

      q=(struct busylinkNode *)malloc(sizeof(struct busylinkNode));

      q->name='S';/* S表示操作系統(tǒng)占用

      */

      q->len=64;q->address=0;q->next=NULL;

      busy_head->next=q;busy_tail=q;} void requireMemo(char name, int require)/*模擬內(nèi)存分配*/ { freelinkNode *w,*u,*v;busylinkNode *p;if(free_head->next->len>=require){

      p=(struct busylinkNode*)malloc(sizeof(struct busylinkNode));

      p->name=name;

      p->address=free_head->next->address;

      p->len=require;

      p->next=NULL;

      busy_tail->next=p;

      busy_tail=p;} else

      printf(”Can't allocate“);

      w=free_head->next;

      free_head->next=w->next;

      if(w->len==require)

      {

      free(w);} else {

      w->address=w->address+require;

      w->len=w->len-require;}

      u=free_head;

      v=free_head->next;

      while((v!=NULL)&&(v->len>w->len)){

      u=v;

      v=v->next;}

      u->next=w;

      w->next=v;} void freeMemo(char name)/* 模擬內(nèi)存回收*/ { int len;

      int address;busylinkNode *q,*p;freelinkNode *w,*u,*v;q=busy_head;

      p=busy_head->next;

      while((p!=NULL)&&(p->name!=name))

      {

      q=p;

      p=p->next;}

      if(p==NULL){

      printf(”%c is not exist“,name);} else

      {

      if(p==busy_tail)

      {

      busy_tail=q;

      }

      else

      {

      q->next=p->next;

      len=p->len;

      address=p->address;

      free(p);

      w=(struct freelinkNode*)malloc(sizeof(struct freelinkNode));

      w->len=len;

      w->address=address;

      u=free_head;

      v=free_head->next;

      while((v!=NULL)&&(v->len>len))

      { u=v;v=v->next;

      }

      u->next=w;

      w->next=v;

      } } } void past(int time)/* 模擬系統(tǒng)過了time 時間*/ { printf(”過了時間%d后:n“,time);} void printlink()/* 輸出內(nèi)存空閑情況(自由鏈的結(jié)點)*/ {

      freelinkNode *p;

      printf(”內(nèi)存的空閑情況為:n“);

      p=(struct freelinkNode *)malloc(sizeof(struct freelinkNode));

      p=free_head->next;

      while(p!=NULL)

      {

      printf(”內(nèi)存的起始地址和內(nèi)存的大小%5dt%5d:n",p->address,p->len);

      p=p->next;

      } }

      void main(){

      int t1=1,t2=2,t3=3,t4=4;

      start();

      past(t1);

      requireMemo('A',8);

      requireMemo('B',16);

      requireMemo('C',64);

      requireMemo('D',124);

      printlink();

      past(t2);

      freeMemo('C');

      printlink();

      past(t3);

      requireMemo('E',50);

      printlink();

      past(t4);

      freeMemo('D');

      printlink();} 6.運行結(jié)果:

      7.實驗總結(jié):

      鞏固編程能力,和調(diào)式能力,復習課本知識,明白理論聯(lián)系實際的重要性,動手能力非常重要,多看書,多獨立思考,品味痛苦的過程,享受成功的喜悅。

      操作系統(tǒng)實驗報告

      院系:數(shù)計學院

      班級:大類6班 學號:100511624 姓名:明章輝

      指導教師:徐軍利

      第五篇:操作系統(tǒng)實驗報告

      許昌學院

      《操作系統(tǒng)》實驗報告書

      學號:姓名:閆金科班級:成績:

      5006140057

      14物聯(lián)網(wǎng)工程 2016年02月實驗一 Linux的安裝與配置

      一、實驗目的

      1.熟悉Linux系統(tǒng)的基本概念,比如Linux發(fā)行版、宏內(nèi)核、微內(nèi)核等。2.掌握Linux系統(tǒng)的安裝和配置過程,初步掌握Linux系統(tǒng)的啟動和退出方法。3.熟悉Linux系統(tǒng)的文件系統(tǒng)結(jié)構(gòu),了解Linux常用文件夾的作用。

      二、實驗內(nèi)容

      1.從網(wǎng)絡上下載VMware軟件和兩個不同Linux發(fā)行版鏡像文件。2.安裝VMware虛擬機軟件。

      3.在VMware中利用第一個鏡像文件完成第一個Linux的安裝,期間完成網(wǎng)絡信息、用戶信息、文件系統(tǒng)和硬盤分區(qū)等配置。

      4.在VMware中利用第二個鏡像文件完成第二個Linux的安裝,并通過LILO或者GRUB解決兩個操作系統(tǒng)選擇啟動的問題。

      5.啟動Linux系統(tǒng),打開文件瀏覽器查看Linux系統(tǒng)的文件結(jié)構(gòu),并列舉出Linux常用目錄的作用。

      三、實驗過程及結(jié)果

      1、啟動VMware,點擊新建Linux虛擬機,如圖所示:

      2、點擊下一步,選擇經(jīng)典型,點擊下一步在選擇客戶機頁面選擇Linux,版本選擇Red Hat Enterprise Linux 5,如圖所示:

      3、點擊下一步創(chuàng)建虛擬機名稱以及所要安裝的位置,如圖所示:

      4、點擊下一步,磁盤容量填一個合適大小,此處選擇默認值大小10GB,如圖所示:

      5、點擊完成,點擊編輯虛擬機設置,選擇硬件選項中的CD-ROM(IDE...)選項,在右側(cè)連接中選擇“使用ISO鏡像(I)”選項,點擊“瀏覽”,找到Linux的鏡像文件,如圖所示:

      6點擊確定按鈕后,點擊啟動虛擬機按鈕,來到Linux的安裝界面,如圖所示:

      7、到此頁面之后,等待自動檢測安裝,如圖所示:

      8、等到出現(xiàn)如圖所示頁面后點擊“skip”按鈕,跳過檢測,直接進入安裝設置界面,如圖所示:

      9、安裝設計界面如圖所示:

      10、點擊Next按鈕進入設置語言界面,設置語言為“簡體中文”,如圖所示:

      11、點擊Nest按鈕進入系統(tǒng)鍵盤設置按鈕,設置系統(tǒng)鍵盤為“美國英語式”,如圖所示:

      12、點擊下一步按鈕,彈出“安裝號碼”對話框,選擇跳過輸入安裝號碼,如圖所示:

      13、按照提示,一直點擊下一步按鈕,如圖所示:

      14、到設置最后一步,點擊下一步按鈕進入開始安裝Red Hat Enterprise Linux Sever界面,如圖所示:

      15、安裝完成后,進入歡迎界面,按照提示點擊前進按鈕知道進入Linux桌面,如圖所示:

      16、安裝成功的Linux系統(tǒng)桌面如圖所示,桌面包含五個圖標,分別為:計算機、jk’s Home、回收站、RHEL/5.3 i386DVD。

      四、實驗總結(jié)

      通過安裝虛擬機等操作讓我認識到Linux這系統(tǒng)一些基本特點,本次試驗學會了安裝虛擬機并且使用虛擬機安裝操作系統(tǒng),掌握了紅帽Linux系統(tǒng)的安裝和配置過程,以及對鏡像ISO文件的使用,有別于我們機器上使用的系統(tǒng),通過虛擬機這個軟件還可以在已有系統(tǒng)的基礎(chǔ)上使用其他操作系統(tǒng)。安裝過程中一定要注意選擇版本的時候要選擇Red Hat Enterprise Linux 5版本,否則安裝不能成功。自己動手成功的安裝了Linux系統(tǒng),自己對Linux的學習產(chǎn)生更大的興趣。

      實驗二 Linux操作系統(tǒng)的運行模式

      一、實驗目的

      1.熟悉Linux系統(tǒng)終端工作環(huán)境的使用,了解Linux命令的格式,使用學會利用常用的Linux命令來完成系統(tǒng)的管理和維護。

      2.了解X-Windows的特點,熟悉Linux圖形用戶接口的使用,掌握GNOME桌面環(huán)境的基本操作。

      3.了解和掌握在Linux環(huán)境下安裝軟件包的方法,如QQ for Linux等用軟件的安裝方法。

      二、實驗內(nèi)容

      1.啟動Linux系統(tǒng)打開虛擬終端界面,使用Linux的在線幫助指令man或help獲得ls、uname、date、cal、mkdir、cp等Linux命令的幫助手冊,了解這些命令的具體使用方法。同時,也可以通過執(zhí)行“命令名 –help”來顯示該命令的幫助信息,如“l(fā)s –help”,試用這些命令。

      2.通過uname命令的執(zhí)行,查看并給出相關(guān)系統(tǒng)信息:操作系統(tǒng)的名稱、系統(tǒng)域名、系統(tǒng)CPU名稱等。

      3.在主目錄下創(chuàng)建一個名為myetc的子目錄,將/etc目錄下與網(wǎng)絡相關(guān)的文件和子目錄拷貝到該目錄,并將這些文件的執(zhí)行權(quán)限設置為可執(zhí)行。

      4.在主目錄/home下創(chuàng)建目錄program、music 和temp,然后在program下建立目錄java和C,列出完成該過程的所有命令。

      5.在圖形界面環(huán)境中,查看GNOME桌面的面板和桌面,設置GNOME,包括屏幕保護程序、更改背景和指定關(guān)聯(lián)程序等。6.實現(xiàn)對光盤的加載和訪問,然后卸載。

      三、實驗過程及結(jié)果

      1、打開終端,輸入 【ls –help】來查看【ls】指令的使用方法,同理查看uname、date、cal、mkdir、cp的使用方法。

      2、在終端中輸入【uname –a】顯示操作系統(tǒng)名系統(tǒng)cpu名和系統(tǒng)域名

      3、重啟系統(tǒng),用【root】用戶名進入系統(tǒng),以獲得權(quán)限。在終端中輸入【mkdir myetc】,在主目錄下創(chuàng)建【myrtc】的目錄,【ls】查看是否創(chuàng)建。輸入【cd..】返回至【/】文件,輸入【cp –r etc root/myetc】講etc中內(nèi)容復制到myetc中,進入myetc文件【ls】查看。輸入

      【chmod u+x etc】賦予文件可執(zhí)行的權(quán)限,輸入【ll】查看。

      4、在home下,輸入【mkdir {program,music,temp}】,可在home下創(chuàng)立這三個目錄,輸入【ls】查看。在program下輸入【mkdir{java,C}】,可創(chuàng)立java和C兩個目錄,【ls】查看。

      5、在桌面上方選擇【系統(tǒng)】-【首選項】,即可設置屏幕保護程序和更改背景和指定關(guān)聯(lián)程序

      5、在桌面上可見看到有CD光盤,雙擊瀏覽,右鍵【彈出】即卸載。

      四、實驗總結(jié)和體會

      Linux的指令系統(tǒng)是學習Linux操作系統(tǒng)很重要的一部分,指令系統(tǒng)相當于在Windows操作系統(tǒng)下的doc,可以省去圖形化界面。通過這次的實驗讓我了解了Linux的強大功能,了解到Linux有許多方便快捷的設置基本配置的方法,這使我更喜歡上Linux的使用。在使用指令的過程中,有時候?qū)ξ募牟僮餍枰欢ǖ臋?quán)限,這時需要在登陸時用戶名使用【root】,而不是我們在安裝時使用的用戶名,這樣就獲得了管理員權(quán)限,可以對一些系統(tǒng)文件進行操作。

      實驗三 Linux應用軟件與系統(tǒng)管理

      一、實驗目的

      1.了解OpenOffice.Org集成辦公軟件,掌握利用OpenOffice.Org的套件來完成文檔和圖片的處理。

      2.了解Linux網(wǎng)絡管理的知識,熟悉Linux網(wǎng)絡配置的方法,掌握在Linux環(huán)境下配置Web服務器和ftp服務的方法。

      二、實驗內(nèi)容

      1.配置Linux系統(tǒng)的網(wǎng)絡環(huán)境,安裝FTP和Web服務器,并配置相關(guān)的屬性,利用FTP實現(xiàn)WINDOWS和Linux之間的數(shù)據(jù)交換。

      2.利用FTP程序上傳自己的照片到FTP服務器,利用OpenOffice的文字處理工具OpenOffice Writer制作一份表格形式的個人簡歷。個人簡歷中至少包含學號、姓名、性別、專業(yè)、照片和學習經(jīng)歷等內(nèi)容,并保存為網(wǎng)頁格式(html格式)。3.將個人簡歷網(wǎng)頁設置為WEB服務器的首頁,然后在客戶端利用瀏覽器訪問WEB服務器,查看效果。

      4.通過讀取proc文件系統(tǒng),獲取系統(tǒng)各種信息(如主機名、系統(tǒng)啟動時間、運行時間、版本號、所有進程信息、CPU使用率等),并以比較容易的方式顯示。

      三、實驗過程及結(jié)果

      1.配置網(wǎng)絡環(huán)境:在(服務.cmd).里面進行以下操作:在服務里選擇3按回車

      完成后,可在本地連接看到VMware已連接上網(wǎng)絡

      在虛擬機設置中設置以太網(wǎng)網(wǎng)絡連接方式為

      網(wǎng)關(guān)地址填虛擬機的網(wǎng)管,IP地址設為虛擬機的一個子網(wǎng):

      四、總結(jié):

      在linux系統(tǒng)下,make是我們經(jīng)常用到的編譯命令,所以關(guān)于make代碼和他的操作指令一定要記清楚。所以,熟練掌握了make和makefile工具之后,源碼安裝軟件就變的像windows下安裝軟件一樣簡單。

      實驗四 進程控制與管理

      一、實驗目的

      1.掌握GCC編譯器的用法,學會利用GCC編輯器來編輯C語言程序,學會利用GDB調(diào)試器來調(diào)試C語言程序。

      2.理解進程和程序的區(qū)別和聯(lián)系,3.掌握在Linux環(huán)境下觀察進程運行情況和CPU工作情況的命令。4.了解fork()系統(tǒng)調(diào)用,掌握利用fork()創(chuàng)建進程的方法。

      5.了解Linux系統(tǒng)其他與進程相關(guān)的系統(tǒng)調(diào)用,如exec、wait和exit等。6.了解Linux常用的進程通信機制。

      二、實驗內(nèi)容

      1.利用Linux的進程管理命令ps、top來監(jiān)視和跟蹤進程,體會進程和程序的關(guān)系。2.利用Linux的文字編輯器編寫文件復制的C語言程序,并用gcc編譯該程序,然后運行該程序。

      3.編寫一段程序,使用系統(tǒng)調(diào)用fork()創(chuàng)建兩個子進程。當此程序運行時,在系統(tǒng)中有一個父進程和兩個子進程活動。讓每一個進程在屏幕上顯示一個字符:父進程顯示'a',子進程分別顯示字符'b'和字符'c'。試觀察記錄屏幕上的顯示結(jié)果,并分析原因。

      4.修改上述程序,每一個進程循環(huán)顯示一句話。子進程顯示'daughter ?'及'son ??',父進程顯示 'parent ??',觀察結(jié)果,分析原因。5.用fork()創(chuàng)建一個進程,再調(diào)用exec()用新的程序替換該子進程的內(nèi)容。

      三、實驗過程及結(jié)果

      1、利用Linux的進程管理命令ps、top來監(jiān)視和跟蹤進程,體會進程和程序的關(guān)系。<1>從用戶身份切換到ROOT身份

      <2>輸入命令 ps 查看進程

      <2>輸入命令 top 跟蹤進程

      2、利用Linux的文字編輯器編寫一個計算機100個自然數(shù)和的C語言程序,并用gcc編譯該程序,然后運行該程序。

      <1>創(chuàng)建一個.C文件 并進入進行編輯

      <2>用GCC 進行編譯,再查看文件,發(fā)現(xiàn)產(chǎn)生執(zhí)行文件 a.out

      <3>執(zhí)行這個可執(zhí)行文件得到結(jié)果5050

      1、編寫一段程序,使用系統(tǒng)調(diào)用fork()創(chuàng)建兩個子進程。當此程序運行時,在系統(tǒng)中有一個父進程和兩個子進程活動。讓每一個進程在屏幕上顯示一個字符:父進程顯示'a',子進程分別顯示字符'b'和字符'c'。試觀察記錄屏幕上的顯示結(jié)果,并分析原因。

      <1>穿件一個.C文件 并進行編寫程序代碼

      <2>反復執(zhí)行2次該程序

      <3>可以看出兩次執(zhí)行的結(jié)果 a b c 出現(xiàn)的順序不同,原因是,3個進程的輸出次序是隨機的,并不會按規(guī)定的順序出現(xiàn),所以會出現(xiàn)上述結(jié)果。

      4、修改上述程序,每一個進程循環(huán)顯示一句話。子進程顯示'daughter ?'及'son ??',父進程顯示 'parent ??',觀察結(jié)果,分析原因。<1>重新修改代碼

      <3>執(zhí)行這段程序

      <4>原分析:

      因和之前一樣,可以看出執(zhí)行的結(jié)果 3個單詞出現(xiàn)的順序不同,原因是,3個進程的輸出次序是隨機的,并不會按規(guī)定的順序出現(xiàn),所以會出現(xiàn)上述結(jié)果。

      5、用fork()創(chuàng)建一個進程,再調(diào)用exec()用新的程序替換該子進程的內(nèi)容。<1>

      編寫代碼

      <2> 執(zhí)行的結(jié)果

      結(jié)果表明 execl 替代了son的內(nèi)容

      四、實驗總結(jié)和體會

      這個實驗考察的是進程之間存在很多可能性以及對編輯器的使用。本次實驗學習了在linux環(huán)境下用gcc編譯器運行c語言程序,在linux環(huán)境下編寫程序用到了vi編輯器,知道了該編輯器也需要各種命令來操作。編寫C語言程序時用到了fork()函數(shù),再調(diào)用execl()用新的程序替換該子進程的內(nèi)容。

      實驗五 進程調(diào)度模擬程序的設計與實現(xiàn)

      一、實驗目的

      1.了解進程調(diào)度的概念,掌握常用進程調(diào)度算法的原理。2.掌握Linux程序設計編輯、編譯和調(diào)試的技巧。

      二、實驗內(nèi)容

      1.編寫程序?qū)崿F(xiàn)進程調(diào)度調(diào)度算法先來先服務、優(yōu)先級高優(yōu)先和時間片輪轉(zhuǎn)調(diào)度算法。(編程語言不限)

      2.輸入數(shù)據(jù),輸出運行結(jié)果。

      三、實驗過程及結(jié)果

      1先來先服務

      #i nclude float t,d;

      struct { int id;

      float ArriveTime;float RequestTime;float StartTime;float EndTime;float RunTime;float DQRunTime;int Status;}arrayTask[4];GetTask(){ int i;float a;

      for(i=0;i<4;i++){arrayTask[i].id=i+1;printf(“input the number”);

      printf(“input the the ArriveTime of arrayTask[%d]:”,i);scanf(“%f”,&a);

      arrayTask[i].ArriveTime=a;

      printf(“input the RequestTime of arrayTask[%d]:”,i);scanf(“%f”,&a);

      arrayTask[i].RequestTime=a;arrayTask[i].StartTime=0;arrayTask[i].EndTime=0;arrayTask[i].RunTime=0;arrayTask[i].Status=0;

      } }

      int fcfs()

      {

      int i,j,w=0;

      for(i=0;i<4;i++)

      {

      if(arrayTask[i].Status==0)

      {

      t=arrayTask[i].ArriveTime;

      w=1;

      }

      if(w==1)

      break;

      }

      for(i=0;i<4;i++)

      {

      if(arrayTask[i].ArriveTime

      t=arrayTask[i].ArriveTime;

      }

      for(i=0;i<4;i++)

      {

      if(arrayTask[i].ArriveTime==t)

      return i;

      }

      }

      int sjf(){

      int i,x=0,a=0,b=0;float g;

      for(i=0;i<4;i++){

      if(arrayTask[i].Status==1){g=arrayTask[i].EndTime;x=1;} }

      if(x==0){

      t=arrayTask[0].ArriveTime;

      for(i=0;i<4;i++){

      if(arrayTask[i].ArriveTime

      t=arrayTask[i].ArriveTime;a=i;} }

      return a;} else {

      for(i=0;i<4;i++){ if(arrayTask[i].EndTime>g)g=arrayTask[i].EndTime;}

      for(i=0;i<4;i++){ if(arrayTask[i].Status==0&& arrayTask[i].ArriveTime<=g){ t=arrayTask[i].RequestTime;a=i;b=1;} /*判斷有沒有進程在前個進程完成前到達*/ }

      if(b!=0)/*有進程到達則按SJF*/ { for(i=0;i<4;i++){

      if(arrayTask[i].Status==0&&arrayTask[i].ArriveTime<=g&&arrayTask[i].RequestTime

      return a;} else{ /*否則按FCFS*/ for(i=0;i<4;i++)

      {if(arrayTask[i].Status==0)t=arrayTask[i].ArriveTime;}

      for(i=0;i<4;i++){

      if(arrayTask[i].Status==0&&arrayTask[i].ArriveTime

      return a;} } }

      new(int s)/*定義執(zhí)行進程后相關(guān)數(shù)據(jù)的修改*/ { int i,g=0;for(i=0;i<4;i++){

      if(arrayTask[i].Status==0)continue;else { g=1;break;} }

      if(g==0)/*當處理的是第一個未執(zhí)行的進程時執(zhí)行*/ {

      arrayTask[s].StartTime=arrayTask[s].ArriveTime;

      arrayTask[s].EndTime=arrayTask[s].RequestTime+arrayTask[s].ArriveTime;arrayTask[s].RunTime=arrayTask[s].RequestTime;arrayTask[s].Status=1;g=2;}

      if(g==1)/*當處理的不是第一個未執(zhí)行的進程時執(zhí)行*/ {

      arrayTask[s].Status=1;for(i=0;i<4;i++){

      if(arrayTask[i].Status==1)d=arrayTask[i].EndTime;}

      for(i=0;i<4;i++)/*查找最后執(zhí)行的進程的完成時間*/ {

      if(arrayTask[i].EndTime>d&&arrayTask[i].Status==1)d=arrayTask[i].EndTime;}

      if(arrayTask[s].ArriveTime

      arrayTask[s].StartTime=arrayTask[s].ArriveTime;

      arrayTask[s].EndTime=arrayTask[s].StartTime+arrayTask[s].RequestTime;arrayTask[s].RunTime=arrayTask[s].EndTime-arrayTask[s].ArriveTime;}

      arrayTask[s].DQRunTime=arrayTask[s].RunTime/arrayTask[s].RequestTime;}

      Printresult(int j)/*定義打印函數(shù)*/ {

      printf(“%dt”,arrayTask[j].id);

      printf(“%5.2ft”,arrayTask[j].ArriveTime);printf(“%5.2ft”,arrayTask[j].RequestTime);printf(“%5.2ft”,arrayTask[j].StartTime);printf(“%5.2ft”,arrayTask[j].EndTime);printf(“%5.2ft”,arrayTask[j].RunTime);printf(“%5.2fn”,arrayTask[j].DQRunTime);} main(){

      int i,b,k,a,c=0;int d[4];clrscr();

      printf(“t F.FCFS n”);printf(“t S.SFJ n”);printf(“t Q.EXIT n”);for(i=0;;i++){ if(c)break;

      printf(“please input the number a:n”);scanf(“%d”,&a);switch(a){

      case Q: c=1;break;

      case F:printf(“please input the different-ArriveTime of arrayTasksn”);GetTask();

      printf(“*****************************the result of fcfsn”);printf(“NumbertArrivetServertStarttFinishtTurnovetTake power turnover timen”);

      for(b=0;b<4;b++)/*調(diào)用兩個函數(shù)改變結(jié)構(gòu)體數(shù)的值*/ {

      k=fcfs();d[b]=k;new(k);}

      for(b=0;b<4;b++)

      Printresult(d[b]);/*調(diào)用打印函數(shù)打出結(jié)果*/ continue;

      case S: printf(“please input the different-RequestTime of array

      Tasksn”);GetTask();

      printf(“******************************the result of sjfn”);printf(“NumbertArrivetRequesttStarttEndtRuntDQRun timen”);for(b=0;b<4;b++){ k=sjf();d[b]=k;new(k);}

      for(b=0;b<4;b++)Printresult(d[b]);continue;

      default:printf(“the number Error.please input another number!n”);} } }

      四、實驗總結(jié)和體會

      通過做本實驗,讓我對進程或作業(yè)先來先服務、高優(yōu)先權(quán)、按時間片輪轉(zhuǎn)調(diào)度算法以及進程調(diào)度的概念和算法,有了更深入的認識!理解進程的狀態(tài)及變化,動態(tài)顯示每個進程的當前狀態(tài)及進程的調(diào)度情況。進程調(diào)度是處理機管理的核心內(nèi)容。優(yōu)先級高優(yōu)先是根據(jù)作業(yè)的優(yōu)先級,總是選擇優(yōu)先級最高者進入隊列。輪轉(zhuǎn)調(diào)度算法是調(diào)度程序每次把CPU分配給就緒隊列首進程/線程使用規(guī)定的時間間隔,就緒隊列中都路保留巡行一個時間片。

      下載讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)(五篇范文)word格式文檔
      下載讀者-寫者 操作系統(tǒng)實驗報告 計算機操作系統(tǒng)(五篇范文).doc
      將本文檔下載到自己電腦,方便修改和收藏,請勿使用迅雷等下載。
      點此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔相關(guān)法律責任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進行舉報,并提供相關(guān)證據(jù),工作人員會在5個工作日內(nèi)聯(lián)系你,一經(jīng)查實,本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦

        操作系統(tǒng)第一次實驗報告(大全)

        操作 系統(tǒng) 實驗報告 實驗名稱:線程 控制實驗 計算機科學與技術(shù)學院 目錄 一、實驗目的和要求 2 二、實驗內(nèi)容 2 三、實驗步驟 2 四、實驗結(jié)果與分析 3 1.單線程 3 2.單線程(睡......

        嵌入式操作系統(tǒng)實驗報告

        實驗一 嵌入式開發(fā)環(huán)境的建立 一、實驗目的 通過此實驗系統(tǒng),讀者可以了解嵌入式實時操作系統(tǒng) uC/OS-II 的內(nèi)核機制和運行原理。本實驗系統(tǒng)展示了 uC/OS-II 各方面的管理功能,......

        操作系統(tǒng)實驗報告[五篇材料]

        計算機學院實驗報告 課 程實驗名稱 專 業(yè)班 級學 號學生姓名 操作系統(tǒng) 進程的控制 計算機操作系統(tǒng) 131110196 鄒明鎮(zhèn) 嘉應學院計算機學院 1305 一、實驗目的 熟悉......

        linux操作系統(tǒng)實驗報告

        Linux實驗報告一 一、實驗步驟及內(nèi)容 1.虛擬機軟件的安裝 (1)先準備虛擬機安裝包。 (2)更改安裝路徑: "D: VMwareVMware Workstationvmware.exe" (3)輸入序列號:ctrl+v, 在安裝過......

        操作系統(tǒng)專題實驗報告樣式

        操作系統(tǒng)專題實驗報告班級: 學號: 姓名:2014 年月日目錄 1內(nèi)核編譯與系統(tǒng)調(diào)用...................... 3 1.1實驗目的 .............................. 3 1.2實驗內(nèi)容 ...............

        操作系統(tǒng)實驗報告一

        實驗報告一 一、實驗目的 通過本實驗,掌握Linux的基本操作以及Linux的文本編輯,對Linux有一個基本的了解。 二、實驗任務 1、 Linux的基本操作 1) 在圖形交互方式下實現(xiàn)對用戶......

        讀者寫者實驗報告

        操作系統(tǒng)原理 實驗報告 實驗名稱: 姓 名:學 號:班 級:指導老師: 操作系統(tǒng) XXX xxxxxxxxxx xxx xxx 一、實驗內(nèi)容 在Windows2000環(huán)境下,創(chuàng)建一個控制臺進程,此進程包含n個線程......

        計算機操作系統(tǒng)教案

        計算機操作系統(tǒng)教案 學院名稱:河北政法職業(yè)學院 系部名稱: 計算機系 課程名稱: 計算機操作系統(tǒng) 任課教師: 張敏麗 授課題目:操作系統(tǒng)緒論一 授課序號:1 授課班級:司法信息2003級......