WINDOW操作系統(tǒng)課程設(shè)計實驗報告_第1頁
WINDOW操作系統(tǒng)課程設(shè)計實驗報告_第2頁
WINDOW操作系統(tǒng)課程設(shè)計實驗報告_第3頁
WINDOW操作系統(tǒng)課程設(shè)計實驗報告_第4頁
WINDOW操作系統(tǒng)課程設(shè)計實驗報告_第5頁
已閱讀5頁,還剩164頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

操作系統(tǒng)課程設(shè)計實驗報告目錄實驗一 3一、 實驗題目 3二、 實驗?zāi)康?3三、 總體設(shè)計 3四、 詳細設(shè)計 6五、 實驗結(jié)果與分析 10六、 小結(jié)與心得體會 14實驗二 15一、 實驗題目 15二、 實驗?zāi)康?15三、 總體設(shè)計 15四、 詳細設(shè)計 16五、 實驗結(jié)果與分析 19六、 小結(jié)與心得體會 20實驗三 21一、 實驗題目 21二、 實驗?zāi)康?21三、 總體設(shè)計 21四、 詳細設(shè)計 21五、 實驗結(jié)果與分析 26六、 小結(jié)與心得體會 28實驗四 29一、 實驗題目 29二、 實驗?zāi)康?29三、 總體設(shè)計 29四、 詳細設(shè)計 29五、 實驗結(jié)果與分析 34六、 小結(jié)與心得體會 35實驗五 36一、 實驗題目 36二、 實驗?zāi)康?36三、 總體設(shè)計 36四、 詳細設(shè)計 41五、 實驗結(jié)果與分析 44六、 小結(jié)與心得體會 53實驗六 54一、 實驗題目 54二、 實驗?zāi)康?54三、 總體設(shè)計 54四、 詳細設(shè)計 54五、 實驗結(jié)果與分析 61六、 小結(jié)與心得體會 62實驗七 63一、 實驗題目 63二、 實驗?zāi)康?63三、 總體設(shè)計 63四、 詳細設(shè)計 68五、 實驗結(jié)果與分析 70六、 小結(jié)與心得體會 71實驗八 72一、 實驗題目 72二、 實驗?zāi)康?72三、 總體設(shè)計 72四、 詳細設(shè)計 76五、 實驗結(jié)果與分析 79六、 小結(jié)與心得體會 80

實驗一實驗題目實驗一Windows進程管理實驗?zāi)康膶W(xué)會使用VC編寫基本的Win32ConsolApplication(控制臺應(yīng)用程序)。通過創(chuàng)建進程、觀察正在運行的進程和終止進程的程序設(shè)計和調(diào)試操作,進一步熟悉操作系統(tǒng)的進程概念,理解Windows進程的“一生”。通過閱讀和分析實驗程序,學(xué)習(xí)創(chuàng)建進程、觀察進程、終止進程以及父子進程同步的基本程序設(shè)計方法??傮w設(shè)計背景知識Windows所創(chuàng)建的每個進程都從調(diào)用CreateProcess()API函數(shù)開始,該函數(shù)的任務(wù)是在對象管理器子系統(tǒng)內(nèi)初始化進程對象。每一進程都以調(diào)用ExitProcess()或TerminateProcess()API函數(shù)終止。通常應(yīng)用程序的框架負(fù)責(zé)調(diào)用ExitProcess()函數(shù)。對于C++運行庫來說,這一調(diào)用發(fā)生在應(yīng)用程序的main()函數(shù)返回之后。創(chuàng)建進程CreateProcess()調(diào)用的核心參數(shù)是可執(zhí)行文件運行時的文件名及其命令行。表1-1詳細地列出了每個參數(shù)的類型和名稱。可以指定第一個參數(shù),即應(yīng)用程序的名稱,其中包括相對于當(dāng)前進程的當(dāng)前目錄的全路徑或者利用搜索方法找到的路徑;lpCommandLine參數(shù)允許調(diào)用者向新應(yīng)用程序發(fā)送數(shù)據(jù);接下來的三個參數(shù)與進程和它的主線程以及返回的指向該對象的句柄的安全性有關(guān)。然后是標(biāo)志參數(shù),用以在dwCreationFlags參數(shù)中指明系統(tǒng)應(yīng)該給予新進程什么行為。經(jīng)常使用的標(biāo)志是CREATE_SUSPNDED,告訴主線程立刻暫停。當(dāng)準(zhǔn)備好時,應(yīng)該使用ResumeThread()API來啟動進程。另一個常用的標(biāo)志是CREATE_NEW_CONSOLE,告訴新進程啟動自己的控制臺窗口,而不是利用父窗口。這一參數(shù)還允許設(shè)置進程的優(yōu)先級,用以向系統(tǒng)指明,相對于系統(tǒng)中所有其他的活動進程來說,給此進程多少CPU時間。接著是CreateProcess()函數(shù)調(diào)用所需要的三個通常使用缺省值的參數(shù)。第一個參數(shù)是lpEnvironment參數(shù),指明為新進程提供的環(huán)境;第二個參數(shù)是lpCurrentDirectory,可用于向主創(chuàng)進程發(fā)送與缺省目錄不同的新進程使用的特殊的當(dāng)前目錄;第三個參數(shù)是STARTUPINFO數(shù)據(jù)結(jié)構(gòu)所必需的,用于在必要時指明新應(yīng)用程序的主窗口的外觀。CreateProcess()的最后一個參數(shù)是用于新進程對象及其主線程的句柄和ID的返回值緩沖區(qū)。以PROCESS_INFORMATION結(jié)構(gòu)中返回的句柄調(diào)用CloseHandle()API函數(shù)是重要的,因為如果不將這些句柄關(guān)閉的話,有可能危及主創(chuàng)進程終止之前的任何未釋放的資源。正在運行的進程如果一個進程擁有至少一個執(zhí)行線程,則為正在系統(tǒng)中運行的進程。通常,這種進程使用主線程來指示它的存在。當(dāng)主線程結(jié)束時,調(diào)用ExitProcess()API函數(shù),通知系統(tǒng)終止它所擁有的所有正在運行、準(zhǔn)備運行或正在掛起的其他線程。當(dāng)進程正在運行時,可以查看它的許多特性,其中少數(shù)特性也允許加以修改。首先可查看的進程特性是系統(tǒng)進程標(biāo)識符(PID),可利用GetCurrentProcessId()API函數(shù)來查看,與GetCurrentProcess()相似,對該函數(shù)的調(diào)用不能失敗,但返回的PID在整個系統(tǒng)中都可使用。其他的可顯示當(dāng)前進程信息的API函數(shù)還有GetStartupInfo()和GetProcessShutdownParameters(),可給出進程存活期內(nèi)的配置詳情。通常,一個進程需要它的運行期環(huán)境的信息。例如API函數(shù)GetModuleFileName()和GetCommandLine(),可以給出用在CreateProcess()中的參數(shù)以啟動應(yīng)用程序。在創(chuàng)建應(yīng)用程序時可使用的另一個API函數(shù)是IsDebuggerPresent()。可利用API函數(shù)GetGuiResources()來查看進程的GUI資源。此函數(shù)既可返回指定進程中的打開的GUI對象的數(shù)目,也可返回指定進程中打開的USER對象的數(shù)目。進程的其他性能信息可通過GetProcessIoCounters()、GetProcessPriorityBoost()、GetProcessTimes()和GetProcessWorkingSetSize()API得到。以上這幾個API函數(shù)都只需要具有PROCESS_QUERY_INFORMATION訪問權(quán)限的指向所感興趣進程的句柄。另一個可用于進程信息查詢的API函數(shù)是GetProcessVersion()。此函數(shù)只需感興趣進程的PID(進程標(biāo)識號)。這一API函數(shù)與GetVersionEx()的共同作用,可確定運行進程的系統(tǒng)的版本號。終止進程所有進程都是以調(diào)用ExitProcess()或者TerminateProcess()函數(shù)結(jié)束的。但最好使用前者而不要使用后者,因為進程是在完成了它的所有的關(guān)閉“職責(zé)”之后以正常的終止方式來調(diào)用前者的。而外部進程通常調(diào)用后者即突然終止進程的進行,由于關(guān)閉時的途徑不太正常,有可能引起錯誤的行為。TerminateProcess()API函數(shù)只要打開帶有PROCESS_TERMINATE訪問權(quán)的進程對象,就可以終止進程,并向系統(tǒng)返回指定的代碼。這是一種“野蠻”的終止進程的方式,但是有時卻是需要的。如果開發(fā)人員確實有機會來設(shè)計“謀殺”(終止別的進程的進程)和“受害”進程(被終止的進程)時,應(yīng)該創(chuàng)建一個進程間通訊的內(nèi)核對象——如一個互斥程序——這樣一來,“受害”進程只在等待或周期性地測試它是否應(yīng)該終止。進程同步Windows提供的常用對象可分成三類:核心應(yīng)用服務(wù)、線程同步和線程間通訊。其中,開發(fā)人員可以使用線程同步對象來協(xié)調(diào)線程和進程的工作,以使其共享信息并執(zhí)行任務(wù)。此類對象包括互鎖數(shù)據(jù)、臨界段、事件、互斥體和信號等。多線程編程中關(guān)鍵的一步是保護所有的共享資源,工具主要有互鎖函數(shù)、臨界段和互斥體等;另一個實質(zhì)性部分是協(xié)調(diào)線程使其完成應(yīng)用程序的任務(wù),為此,可利用內(nèi)核中的事件對象和信號。在進程內(nèi)或進程間實現(xiàn)線程同步的最方便的方法是使用事件對象,這一組內(nèi)核對象允許一個線程對其受信狀態(tài)進行直接控制。而互斥體則是另一個可命名且安全的內(nèi)核對象,其主要目的是引導(dǎo)對共享資源的訪問。擁有單一訪問資源的線程創(chuàng)建互斥體,所有想要訪問該資源的線程應(yīng)該在實際執(zhí)行操作之前獲得互斥體,而在訪問結(jié)束時立即釋放互斥體,以允許下一個等待線程獲得互斥體,然后接著進行下去。與事件對象類似,互斥體容易創(chuàng)建、打開、使用并清除。利用CreateMutex()API可創(chuàng)建互斥體,創(chuàng)建時還可以指定一個初始的擁有權(quán)標(biāo)志,通過使用這個標(biāo)志,只有當(dāng)線程完成了資源的所有的初始化工作時,才允許創(chuàng)建線程釋放互斥體。為了獲得互斥體,首先,想要訪問調(diào)用的線程可使用OpenMutex()API來獲得指向?qū)ο蟮木浔?;然后,線程將這個句柄提供給一個等待函數(shù)。當(dāng)內(nèi)核將互斥體對象發(fā)送給等待線程時,就表明該線程獲得了互斥體的擁有權(quán)。當(dāng)線程獲得擁有權(quán)時,線程控制了對共享資源的訪問——必須設(shè)法盡快地放棄互斥體。放棄共享資源時需要在該對象上調(diào)用ReleaseMute()API。然后系統(tǒng)負(fù)責(zé)將互斥體擁有權(quán)傳遞給下一個等待著的線程(由到達時間決定順序)。編寫基本的Win32ConsolApplication步驟1:登錄進入Windows系統(tǒng),啟動VC++6.0。步驟2:在“FILE”菜單中單擊“NEW”子菜單,在“projects”選項卡中選擇“Win32ConsolApplication”,然后在“Projectname”處輸入工程名,在“Location”處輸入工程目錄。創(chuàng)建一個新的控制臺應(yīng)用程序工程。步驟3:在“FILE”菜單中單擊“NEW”子菜單,在“Files”選項卡中選擇“C++SourceFile”,然后在“File”處輸入C/C++源程序的文件名。步驟4:將清單1-1所示的程序清單復(fù)制到新創(chuàng)建的C/C++源程序中。編譯成可執(zhí)行文件。步驟5:在“開始”菜單中單擊“程序”-“附件”-“命令提示符”命令,進入Windows“命令提示符”窗口,然后進入工程目錄中的debug子目錄,執(zhí)行編譯好的可執(zhí)行程序,列出運行結(jié)果(如果運行不成功,則可能的原因是什么?)創(chuàng)建進程本實驗顯示了創(chuàng)建子進程的基本框架。該程序只是再一次地啟動自身,顯示它的系統(tǒng)進程ID和它在進程列表中的位置。步驟1:創(chuàng)建一個“Win32ConsolApplication”工程,然后拷貝清單1-2中的程序,編譯成可執(zhí)行文件。步驟2:在“命令提示符”窗口運行步驟1中生成的可執(zhí)行文件,列出運行結(jié)果。按下ctrl+alt+del,調(diào)用windows的任務(wù)管理器,記錄進程相關(guān)的行為屬性。步驟3:在“命令提示符”窗口加入?yún)?shù)重新運行生成的可執(zhí)行文件,列出運行結(jié)果。按下ctrl+alt+del,調(diào)用windows的任務(wù)管理器,記錄進程相關(guān)的行為屬性。步驟4:修改清單1-2中的程序,將nClone的定義和初始化方法按程序注釋中的修改方法進行修改,編譯成可執(zhí)行文件(執(zhí)行前請先保存已經(jīng)完成的工作)。再按步驟2中的方式運行,看看結(jié)果會有什么不一樣。列出行結(jié)果。從中你可以得出什么結(jié)論?說明nClone的作用。變量的定義和初始化方法(位置)對程序的執(zhí)行結(jié)果有影響嗎?為什么?父子進程的簡單通信及終止進程步驟1:創(chuàng)建一個“Win32ConsolApplication”工程,然后拷貝清單1-3中的程序,編譯成可執(zhí)行文件。步驟2:在VC的工具欄單擊“ExecuteProgram”(執(zhí)行程序)按鈕,或者按Ctrl+F5鍵,或者在“命令提示符”窗口運行步驟1中生成的可執(zhí)行文件,列出運行結(jié)果。步驟3:按源程序中注釋中的提示,修改源程序1-3,編譯執(zhí)行(執(zhí)行前請先保存已經(jīng)完成的工作),列出運行結(jié)果。在程序中加入跟蹤語句,或調(diào)試運行程序,同時參考MSDN中的幫助文件CreateProcess()的使用方法,理解父子進程如何傳遞參數(shù)。給出程序執(zhí)行過程的大概描述。步驟4:按源程序中注釋中的提示,修改源程序1-3,編譯執(zhí)行,列出運行結(jié)果。步驟5:參考MSDN中的幫助文件CreateMutex()、OpenMutex()、ReleaseMutex()和WaitForSingleObject()的使用方法,理解父子進程如何利用互斥體進行同步的。給出父子進程同步過程的一個大概描述。詳細設(shè)計關(guān)鍵代碼清單1-1一個簡單的Windows控制臺應(yīng)用程序//hello項目#include"stdafx.h"#include<iostream>voidmain(){std::cout<<"Hello,Win32ConsolApplication"<<std::endl;}清單1-2創(chuàng)建子進程#define_CRT_SECURE_NO_WARNINGS#include"stdafx.h"#include<windows.h>#include<iostream>#include<stdio.h>//創(chuàng)建傳遞過來的進程的克隆過程并賦于其ID值voidStartClone(intnCloneID){//提取用于當(dāng)前可執(zhí)行文件的文件名TCHARszFilename[MAX_PATH];GetModuleFileName(NULL,szFilename,MAX_PATH);//格式化用于子進程的命令行并通知其EXE文件名和克隆IDTCHARszCmdLine[MAX_PATH];sprintf_s(szCmdLine,"\"%s\"%d",szFilename,nCloneID);//用于子進程的STARTUPINFO結(jié)構(gòu)STARTUPINFOsi;ZeroMemory(&si,sizeof(si));si.cb=sizeof(si);//必須是本結(jié)構(gòu)的大小//返回的用于子進程的進程信息PROCESS_INFORMATIONpi;//利用同樣的可執(zhí)行文件和命令行創(chuàng)建進程,并賦于其子進程的性質(zhì)BOOLbCreateOK=::CreateProcess(szFilename,//產(chǎn)生這個EXE的應(yīng)用程序的名稱szCmdLine,//告訴其行為像一個子進程的標(biāo)志NULL,//缺省的進程安全性NULL,//缺省的線程安全性FALSE,//不繼承句柄CREATE_NEW_CONSOLE,//使用新的控制臺NULL,//新的環(huán)境NULL,//當(dāng)前目錄&si,//啟動信息&pi);//返回的進程信息//對子進程釋放引用if(bCreateOK){CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}}intmain(intargc,char*argv[]){//確定派生出幾個進程,及派生進程在進程列表中的位置intnClone=0;//修改語句:intnClone;//第一次修改:nClone=0;if(argc>1){//從第二個參數(shù)中提取克隆ID::sscanf_s(argv[1],"%d",&nClone);}//第二次修改:nClone=0;//顯示進程位置std::cout<<"ProcessID:"<<::GetCurrentProcessId()<<",CloneID:"<<nClone<<std::endl;//檢查是否有創(chuàng)建子進程的需要constintc_nCloneMax=5;if(nClone<c_nCloneMax){//發(fā)送新進程的命令行和克隆號StartClone(++nClone);}//等待響應(yīng)鍵盤輸入結(jié)束進程getchar();return0;}清單1-3父子進程的簡單通信及終止進程的示例程序#include"stdafx.h"#include<windows.h>#include<iostream>#include<stdio.h>staticLPCTSTRg_szMutexName="w2kdg.ProcTerm.mutex.Suicide";//創(chuàng)建當(dāng)前進程的克隆進程的簡單方法voidStartClone(){//提取當(dāng)前可執(zhí)行文件的文件名TCHARszFilename[MAX_PATH];GetModuleFileName(NULL,szFilename,MAX_PATH);//格式化用于子進程的命令行,字符串“child”將作為形參傳遞給子進程的main函數(shù)TCHARszCmdLine[MAX_PATH];//實驗1-3步驟3:將下句中的字符串child改為別的字符串,重新編譯執(zhí)行,執(zhí)行前請先保存已經(jīng)完成的工作sprintf_s(szCmdLine,"\"%s\"child",szFilename);//子進程的啟動信息結(jié)構(gòu)STARTUPINFOsi;ZeroMemory(&si,sizeof(si));si.cb=sizeof(si);//應(yīng)當(dāng)是此結(jié)構(gòu)的大小//返回的用于子進程的進程信息PROCESS_INFORMATIONpi;//用同樣的可執(zhí)行文件名和命令行創(chuàng)建進程,并指明它是一個子進程BOOLbCreateOK=CreateProcess(szFilename,//產(chǎn)生的應(yīng)用程序的名稱(本EXE文件)szCmdLine,//告訴我們這是一個子進程的標(biāo)志NULL,//用于進程的缺省的安全性NULL,//用于線程的缺省安全性FALSE,//不繼承句柄CREATE_NEW_CONSOLE,//創(chuàng)建新窗口NULL,//新環(huán)境NULL,//當(dāng)前目錄&si,//啟動信息結(jié)構(gòu)&pi);//返回的進程信息//釋放指向子進程的引用if(bCreateOK){CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}}voidParent(){//創(chuàng)建“自殺”互斥程序體HANDLEhMutexSuicide=CreateMutex(NULL,//缺省的安全性TRUE,//最初擁有的g_szMutexName);//互斥體名稱if(hMutexSuicide!=NULL){//創(chuàng)建子進程std::cout<<"Creatingthechildprocess."<<std::endl;StartClone();//指令子進程“殺”掉自身std::cout<<"Tellingthechildprocesstoquit."<<std::endl;//等待父進程的鍵盤響應(yīng)getchar();//釋放互斥體的所有權(quán),這個信號會發(fā)送給子進程的WaitForSingleObject過程ReleaseMutex(hMutexSuicide);//std::cout<<"222"<<std::endl;//消除句柄CloseHandle(hMutexSuicide);}}voidChild(){//打開“自殺”互斥體HANDLEhMutexSuicide=OpenMutex(SYNCHRONIZE,//打開用于同步FALSE,//不需要向下傳遞g_szMutexName);//名稱//std::cout<<"111"<<std::endl;if(hMutexSuicide!=NULL){//報告我們正在等待指令std::cout<<"Childwaitingforsuicideinstructions."<<std::endl;//子進程進入阻塞狀態(tài),等待父進程通過互斥體發(fā)來的信號//WaitForSingleObject(hMutexSuicide,INFINITE);WaitForSingleObject(hMutexSuicide,0);//實驗1-3步驟4:將上句改為WaitForSingleObject(hMutexSuicide,0),重新編譯執(zhí)行//準(zhǔn)備好終止,清除句柄std::cout<<"Childquiting."<<std::endl;CloseHandle(hMutexSuicide);}}intmain(intargc,char*argv[]){//決定其行為是父進程還是子進程if(argc>1&&::strcmp(argv[1],"child")==0){Sleep(1000);Child();}else{Sleep(1000);Parent();}return0;}實驗結(jié)果與分析編寫基本的Win32ConsolApplication步驟5:運行不成功可能的原因有:雙引號是全角符號,需改成半角符號。創(chuàng)建進程步驟2:步驟3:步驟4:nClone初始化的地方不同,程序執(zhí)行的次數(shù)也不同,在判斷有無命令行參數(shù)之前初始化的話程序只執(zhí)行規(guī)定的最多的次數(shù);之后初始化的話就會無限創(chuàng)建新進程。由此得出變量的定義和初始化方法(位置)對程序的執(zhí)行結(jié)果有影響,因為中間多了一個判斷命令行參數(shù)的代碼段,這一段代碼會更改nClone的值。父子進程的簡單通信及終止進程步驟2:步驟3:程序判斷有無命令行參數(shù)以及參數(shù)是不是child是的話就開啟子進程,否則就開啟父進程。父進程在執(zhí)行克隆的時候給自身加上一把鎖從而保證自身是線程安全的函數(shù),同時在CreateProcess的第二個參數(shù)傳入child參數(shù),保證下次執(zhí)行的是子進程,如此循環(huán),使得父子進程能夠并發(fā)進行,實現(xiàn)父子進程的通信。步驟4:步驟5: CreateMutex作用是找出當(dāng)前系統(tǒng)是否已經(jīng)存在指定進程的實例,如果沒有則創(chuàng)建一個互斥體;OpenMutex函數(shù)為現(xiàn)有的一個已命名互斥體對象創(chuàng)建一個新句柄;ReleaseMutex是一種線性指令,具有釋放線程擁有的互斥體的控制權(quán);WaitForSingleObject函數(shù)用來檢測hHandle事件的信號狀態(tài)。由父進程創(chuàng)建一把鎖后,子進程不用創(chuàng)建鎖,用的時候只需要打開就行,保證同一個時間段只能有父進程或者子進程在運行。小結(jié)與心得體會變量的定義和初始化的位置很重要,因此在進行程序設(shè)計的時候需要設(shè)置好變量的位置,否則會出現(xiàn)意想不到的問題。

實驗二實驗題目實驗二Linux進程管理實驗?zāi)康耐ㄟ^進程的創(chuàng)建、撤銷和運行加深對進程概念和進程并發(fā)執(zhí)行的理解,明確進程和程序之間的區(qū)別??傮w設(shè)計進程的創(chuàng)建任務(wù)要求:編寫一段程序,使用系統(tǒng)調(diào)用fork()創(chuàng)建兩個子進程。當(dāng)此程序運行時,在系統(tǒng)中有一個父進程和兩個子進程活動。讓每一個進程在屏幕上顯示一個字符:父進程顯示字符“a”;兩子進程分別顯示字符“b”和字符“c”。試觀察記錄20次運行該程序在屏幕上的顯示結(jié)果,并分析原因。步驟1:使用vi或gedit新建一個forkdemo.c程序,然后拷貝清單2-1中的程序,使用cc或者gcc編譯成可執(zhí)行文件forkdemo。例如,可以使用gcc–oforkdemoforkdemo.c完成編譯。步驟2:在命令行輸入./fork_demo運行該程序。步驟3:觀察記錄20次運行該程序在屏幕上的顯示結(jié)果,并分析。子進程執(zhí)行新任務(wù)任務(wù)要求:編寫一段程序,使用系統(tǒng)調(diào)用fork()創(chuàng)建一個子進程。子進程通過系統(tǒng)調(diào)用exec更換自己原有的執(zhí)行代碼,轉(zhuǎn)去執(zhí)行Linux命令/bin/ls(顯示當(dāng)前目錄的列表),然后調(diào)用exit()函數(shù)結(jié)束。父進程則調(diào)用waitpid()等待子進程結(jié)束,并在子進程結(jié)束后顯示子進程的標(biāo)識符,然后正常結(jié)束。步驟1:使用vi或gedit新建一個exec_demo.c程序,然后拷貝清單2-2中的程序(該程序的執(zhí)行如圖2-1所示),使用cc或者gcc編譯成可執(zhí)行文件exec_demo。例如,可以使用gcc–oexec_demoexec_demo.c完成編譯。步驟2:在命令行輸入./exec_demo運行該程序。步驟3:觀察該程序在屏幕上的顯示結(jié)果,并分析。實現(xiàn)一個簡單的shell(命令行解釋器)(此任務(wù)有一點難度,可選做)。你的shell類似于sh,bash,csh等,必須支持以下內(nèi)部命令:cd<目錄>更改當(dāng)前的工作目錄到另一個<目錄>。如果<目錄>未指定,輸出當(dāng)前工作目錄。如果<目錄>不存在,應(yīng)當(dāng)有適當(dāng)?shù)腻e誤信息提示。這個命令應(yīng)該也能改變PWD的環(huán)境變量。environ列出所有環(huán)境變量字符串的設(shè)置(類似于Unix系統(tǒng)下的env命令)。echo<內(nèi)容>顯示echo后的內(nèi)容且換行help簡短概要的輸出你的shell的使用方法和基本功能。jobs輸出shell當(dāng)前的一系列子進程,必須提供子進程的命名和PID號。quit,exit,bye退出shell。提示:shell的主體就是反復(fù)下面的循環(huán)過程while(1){接收用戶輸入的命令行;解析命令行;if(用戶命令為內(nèi)部命令)直接處理;elseif(用戶命令為外部命令)創(chuàng)建子進程執(zhí)行命令;//參考清單2-2else提示錯誤的命令;}詳細設(shè)計關(guān)鍵代碼清單2-1創(chuàng)建進程intmain(){intx;while((x=fork())==-1);if(x==0)printf("a");elseprintf("b");printf("c");}清單2-2子進程執(zhí)行新任務(wù)#include<sys/types.h>#include<stdio.h>#include<unistd.h>intmain(){pid_tpid;/*forkachildprocess*/pid=fork();if(pid<0){/*erroroccurred*/fprintf(stderr,"ForkFailed");return1;}elseif(pid==0){/*子進程*/execlp("/bin/ls","ls",NULL);}else{/*父進程*//*父進程將一直等到,直到子進程運行完畢*/wait(NULL);printf("ChildComplete");}return0;}//myshell#include<iostream>#include<cstdlib>#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<fcntl.h>#include<errno.h>#include<pwd.h>#include<signal.h>#include<sys/wait.h>#include<sys/types.h>#include<sys/stat.h>#include<memory.h>usingnamespacestd;constintmax_hostname_length=256;constintmax_pathname_length=512;charpro_prints[max_hostname_length];voidpro_print(){structpasswd*pwd;charhost_name[max_hostname_length];charpath_name[max_pathname_length];intlength;char*p=getcwd(path_name,40);//char*dir=NULL;//獲取當(dāng)前工作目錄的名字//dir=(char*)get_current_dir_name();//printf("dir:%s\n",dir);char*twd=NULL;twd=getwd(path_name);pwd=getpwuid(getuid());if(gethostname(host_name,sizeof(host_name))==0)sprintf(pro_prints,"[MyShell-tyx]%s@%s%s:",pwd->pw_name,host_name,path_name);elsesprintf(pro_prints,"[MyShell-tyx]%s@unknown%s:",pwd->pw_name,path_name);//cout<<"pleaseinputyourcommand:";cout<<pro_prints;}constintcommand_length=512;charcom[command_length];charpro_argv[command_length];charaft_argv[command_length];voidget_command(){memset(com,0,command_length);intlen=0;intch;ch=getchar();while(len<command_length&&ch!='\n'){com[len++]=ch;ch=getchar();}if(len==command_length){cout<<"commandistoolong!!!"<<endl;exit(0);}}voidanaly_command(){//保留,用來備用后續(xù)添加完善shell}intcommand_in(){//cout<<com<<endl;if(strcmp(com,"exit")==0||strcmp(com,"quit")==0||strcmp(com,"bye")==0){exit(0);}elseif(strcmp(com,"help")==0){cout<<"cd改變當(dāng)前目錄,如果不加參數(shù)則顯示當(dāng)前目錄。"<<endl;cout<<"environ輸出打印當(dāng)前的環(huán)境變量"<<endl;cout<<"echo在shell中打印echo之后的字符串"<<endl;cout<<"help顯示幫助信息"<<endl;cout<<"jobs顯示當(dāng)前進程的所有子進程"<<endl;cout<<"quit,exit,bye退出當(dāng)前shell"<<endl;cout<<""<<endl;}elseif(strcmp(com,"environ")==0){execlp("env","env",(char*)0);}elseif(strcmp(com,"jobs")==0){execlp("jobs","jobs","-l",(char*)0);}elseif(strcmp(com,"cd")==0){//execlp("/bin/ls","ls",(char*)0);cout<<getcwd(NULL,NULL)<<endl;}else{char*p;char*tmp;p=strtok_r(com,"",&tmp);if(strcmp(p,"echo")==0){//cout<<com<<endl;p=strtok_r(NULL,"",&tmp);cout<<p<<endl;}elseif(strcmp(p,"cd")==0){p=strtok_r(NULL,"",&tmp);chdir(p);//cout<<com<<endl;//cout<<p<<endl;cout<<getcwd(NULL,NULL)<<endl;}}}intmain(intargc,char**argv){while(true){pro_print();get_command();//analy_command();if(command_in()){continue;}}return0;}實驗結(jié)果與分析進程的創(chuàng)建步驟3:20次每一次的結(jié)果都是一樣的,原因是因為在2.6.32之后的內(nèi)核都是優(yōu)先執(zhí)行父進程再執(zhí)行子進程,因此每次結(jié)果都是一樣。子進程執(zhí)行新任務(wù)步驟3:這個的分析和上一個的差不多,因為在2.6.32之后的內(nèi)核都是優(yōu)先執(zhí)行父進程再執(zhí)行子進程,因此父進程首先進入等待狀態(tài),等待子進程執(zhí)行完成之后再做自己的事。實現(xiàn)一個簡單的shell(命令行解釋器)(此任務(wù)有一點難度,可選做)。小結(jié)與心得體會弄清楚父子進程的執(zhí)行順序很重要,這個需要關(guān)注內(nèi)核的調(diào)度函數(shù),因此,多看內(nèi)核函數(shù)總不是一件很吃虧的事,能夠讓我們更好地熟悉和使用一系列Linux函數(shù),并且能夠保持較高的高效性。

實驗三實驗題目實驗三互斥與同步實驗?zāi)康幕仡櫜僮飨到y(tǒng)進程、線程的有關(guān)概念,加深對Windows線程的理解。了解互斥體對象,利用互斥與同步操作編寫生產(chǎn)者-消費者問題的并發(fā)程序,加深對P(即semWait)、V(即semSignal)原語以及利用P、V原語進行進程間同步與互斥操作的理解??傮w設(shè)計生產(chǎn)者消費者問題步驟1:創(chuàng)建一個“Win32ConsolApplication”工程,然后拷貝清單3-1中的程序,編譯成可執(zhí)行文件。步驟2:在“命令提示符”窗口運行步驟1中生成的可執(zhí)行文件,列出運行結(jié)果。步驟3:仔細閱讀源程序,找出創(chuàng)建線程的WINDOWSAPI函數(shù),回答下列問題:線程的第一個執(zhí)行函數(shù)是什么(從哪里開始執(zhí)行)?它位于創(chuàng)建線程的API函數(shù)的第幾個參數(shù)中?步驟4:修改清單3-1中的程序,調(diào)整生產(chǎn)者線程和消費者線程的個數(shù),使得消費者數(shù)目大與生產(chǎn)者,看看結(jié)果有何不同。察看運行結(jié)果,從中你可以得出什么結(jié)論?步驟5:修改清單3-1中的程序,按程序注釋中的說明修改信號量EmptySemaphore的初始化方法,看看結(jié)果有何不同。步驟6:根據(jù)步驟4的結(jié)果,并查看MSDN,回答下列問題:CreateMutex中有幾個參數(shù),各代表什么含義。CreateSemaphore中有幾個參數(shù),各代表什么含義,信號量的初值在第幾個參數(shù)中。程序中P、V原語所對應(yīng)的實際WindowsAPI函數(shù)是什么,寫出這幾條語句。CreateMutex能用CreateSemaphore替代嗎?嘗試修改程序3-1,將信號量Mutex完全用CreateSemaphore及相關(guān)函數(shù)實現(xiàn)。寫出要修改的語句。讀者寫者問題(選做)根據(jù)實驗(1)中所熟悉的P、V原語對應(yīng)的實際WindowsAPI函數(shù),并參考教材中讀者、寫者問題的算法原理,嘗試?yán)肳indowsAPI函數(shù)實現(xiàn)第一類讀者寫者問題(讀者優(yōu)先)。詳細設(shè)計關(guān)鍵代碼清單3-1生產(chǎn)者消費者問題#include<windows.h>#include<iostream>constunsignedshortSIZE_OF_BUFFER=2;//緩沖區(qū)長度unsignedshortProductID=0;//產(chǎn)品號unsignedshortConsumeID=0;//將被消耗的產(chǎn)品號unsignedshortin=0;//產(chǎn)品進緩沖區(qū)時的緩沖區(qū)下標(biāo)unsignedshortout=0;//產(chǎn)品出緩沖區(qū)時的緩沖區(qū)下標(biāo)intbuffer[SIZE_OF_BUFFER];//緩沖區(qū)是個循環(huán)隊列boolp_ccontinue=true;//控制程序結(jié)束HANDLEMutex;//用于線程間的互斥HANDLEFullSemaphore;//當(dāng)緩沖區(qū)滿時迫使生產(chǎn)者等待HANDLEEmptySemaphore;//當(dāng)緩沖區(qū)空時迫使消費者等待DWORDWINAPIProducer(LPVOID);//生產(chǎn)者線程DWORDWINAPIConsumer(LPVOID);//消費者線程intmain(){//創(chuàng)建各個互斥信號//注意,互斥信號量和同步信號量的定義方法不同,互斥信號量調(diào)用的是CreateMutex函數(shù),同步信號量調(diào)用的是CreateSemaphore函數(shù),函數(shù)的返回值都是句柄。Mutex=CreateMutex(NULL,FALSE,NULL);EmptySemaphore=CreateSemaphore(NULL,SIZE_OF_BUFFER,SIZE_OF_BUFFER,NULL);//將上句做如下修改,看看結(jié)果會怎樣//EmptySemaphore=CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);FullSemaphore=CreateSemaphore(NULL,0,SIZE_OF_BUFFER,NULL);//調(diào)整下面的數(shù)值,可以發(fā)現(xiàn),當(dāng)生產(chǎn)者個數(shù)多于消費者個數(shù)時,//生產(chǎn)速度快,生產(chǎn)者經(jīng)常等待消費者;反之,消費者經(jīng)常等待constunsignedshortPRODUCERS_COUNT=3;//生產(chǎn)者的個數(shù)constunsignedshortCONSUMERS_COUNT=1;//消費者的個數(shù)//總的線程數(shù)constunsignedshortTHREADS_COUNT=PRODUCERS_COUNT+CONSUMERS_COUNT;HANDLEhThreads[THREADS_COUNT];//各線程的handleDWORDproducerID[PRODUCERS_COUNT];//生產(chǎn)者線程的標(biāo)識符DWORDconsumerID[CONSUMERS_COUNT];//消費者線程的標(biāo)識符//創(chuàng)建生產(chǎn)者線程for(inti=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if(hThreads[i]==NULL)return-1;}//創(chuàng)建消費者線程for(i=0;i<CONSUMERS_COUNT;++i){hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);if(hThreads[i]==NULL)return-1;}while(p_ccontinue){if(getchar()){//按回車后終止程序運行p_ccontinue=false;}}return0;}//生產(chǎn)一個產(chǎn)品。簡單模擬了一下,僅輸出新產(chǎn)品的ID號voidProduce(){std::cout<<std::endl<<"Producing"<<++ProductID<<"...";std::cout<<"Succeed"<<std::endl;}//把新生產(chǎn)的產(chǎn)品放入緩沖區(qū)voidAppend(){std::cerr<<"Appendingaproduct...";buffer[in]=ProductID;in=(in+1)%SIZE_OF_BUFFER;std::cerr<<"Succeed"<<std::endl;//輸出緩沖區(qū)當(dāng)前的狀態(tài)for(inti=0;i<SIZE_OF_BUFFER;++i){std::cout<<i<<":"<<buffer[i];if(i==in)std::cout<<"<--生產(chǎn)";if(i==out)std::cout<<"<--消費";std::cout<<std::endl;}}//從緩沖區(qū)中取出一個產(chǎn)品voidTake(){std::cerr<<"Takingaproduct...";ConsumeID=buffer[out];buffer[out]=0;out=(out+1)%SIZE_OF_BUFFER;std::cerr<<"Succeed"<<std::endl;//輸出緩沖區(qū)當(dāng)前的狀態(tài)for(inti=0;i<SIZE_OF_BUFFER;++i){std::cout<<i<<":"<<buffer[i];if(i==in)std::cout<<"<--生產(chǎn)";if(i==out)std::cout<<"<--消費";std::cout<<std::endl;}}//消耗一個產(chǎn)品voidConsume(){std::cout<<"Consuming"<<ConsumeID<<"...";std::cout<<"Succeed"<<std::endl;}//生產(chǎn)者DWORDWINAPIProducer(LPVOIDlpPara){while(p_ccontinue){WaitForSingleObject(EmptySemaphore,INFINITE);//p(empty);WaitForSingleObject(Mutex,INFINITE);//p(mutex);Produce();Append();Sleep(1500);ReleaseMutex(Mutex);//V(mutex);ReleaseSemaphore(FullSemaphore,1,NULL);//V(full);}return0;}//消費者DWORDWINAPIConsumer(LPVOIDlpPara){while(p_ccontinue){WaitForSingleObject(FullSemaphore,INFINITE);//P(full);WaitForSingleObject(Mutex,INFINITE);//P(mutex);Take();Consume();Sleep(1500);ReleaseMutex(Mutex);//V(mutex);ReleaseSemaphore(EmptySemaphore,1,NULL);//V(empty);}return0;}//讀者與寫者問題讀者先#include"stdafx.h"#include<stdio.h>#include<process.h>#include<windows.h>#include<iostream>usingnamespacestd;unsignedshortcount=0;//讀者的數(shù)量計數(shù)器//constunsignedshortMax_Count=10;boolIfCountinue=true;//主程序結(jié)束的標(biāo)志HANDLEmutex_count;//讀者數(shù)量的鎖HANDLEmutex_rw;//讀寫鎖DWORDWINAPIWriter(LPVOID);DWORDWINAPIReader(LPVOID);intmain(){mutex_count=CreateMutex(NULL,FALSE,NULL);mutex_rw=CreateMutex(NULL,FALSE,NULL);constunsignedshortreaders=2;//最大的讀者量constunsignedshortwriters=1;//最大的寫者量constunsignedshortall_s=readers+writers;//讀寫者總量HANDLEhandle_all_s[all_s];DWORDreadersID[readers];DWORDwritersID[writers];for(inti=0;i<writers;i++){handle_all_s[i]=CreateThread(NULL,0,Writer,NULL,0,&writersID[i]);//創(chuàng)建寫者線程if(handle_all_s[i]==NULL){return-1;}}for(inti=0;i<readers;i++){handle_all_s[writers+i]=CreateThread(NULL,0,Reader,NULL,0,&readersID[i]);//創(chuàng)建讀者線程if(handle_all_s[writers+i]==NULL){return-1;}}boolget=getchar();//等待輸入字符結(jié)束主進程if(get==true){IfCountinue=false;}return0;}voidwriting(){cout<<"Iamawriter!!!"<<endl<<endl;Sleep(1000);}voidreading(){cout<<"Iamareader,thereare(is)"<<::count<<"readershear!"<<endl<<endl;Sleep(1000);}DWORDWINAPIWriter(LPVOIDlpPara){while(IfCountinue){WaitForSingleObject(mutex_rw,INFINITE);//鎖住讀寫鎖,每次一個人操作writing();ReleaseMutex(mutex_rw);//釋放讀寫鎖}return0;}DWORDWINAPIReader(LPVOIDlpPara){while(IfCountinue){WaitForSingleObject(mutex_count,INFINITE);//開啟讀者數(shù)量鎖,每次只能一個線程進入進行操作if(::count==0){WaitForSingleObject(mutex_rw,INFINITE);//鎖住讀寫鎖,每次一個人操作}::count++;ReleaseMutex(mutex_count);//釋放讀者數(shù)量鎖reading();WaitForSingleObject(mutex_count,INFINITE);//開啟讀者數(shù)量鎖,每次只能一個線程進入進行操作::count--;if(::count==0){ReleaseMutex(mutex_rw);//釋放讀寫鎖}ReleaseMutex(mutex_count);//釋放讀者數(shù)量鎖}return0;}實驗結(jié)果與分析生產(chǎn)者消費者問題步驟2:步驟3:線程的第一個執(zhí)行函數(shù)是第三個參數(shù)指定的函數(shù),位于CreateThread的第三個參數(shù)。步驟4:消費者數(shù)目大于生產(chǎn)者的時候,消費者總是在等待生產(chǎn)者,由此得知數(shù)量多的線程執(zhí)行的次數(shù)也多,成正比關(guān)系。步驟5:修改之后程序沒有反應(yīng),說明沒有可用的信號量,程序陷入饑餓的狀態(tài)。步驟6:CreateMutex有三個參數(shù),第一個是指向安全屬性的指針,第二個是初始化互斥對象的所有者,第三個是指向互斥對象名的指針。CreateSemaphore有四個參數(shù),第一個參數(shù)定義了信號量的安全特性,第二個參數(shù)設(shè)置信號量的初始計數(shù),第三個參數(shù)設(shè)置信號量的最大計數(shù),第四個參數(shù)指定信號量對象的名稱;信號量的初值在第二個參數(shù)中。P()對應(yīng)的是WaitForSingleObject(),V()對應(yīng)的是ReleaseMutex()或者ReleaseSemaphore()。CreateMutex能用CreateSemaphore替代,CreateMutex(NULL,FALSE,NULL)改成CreateSemaphore(NULL,0,1,NULL)。讀者寫者問題(選做)小結(jié)與心得體會編寫程序首先得確定思路,然后再考慮具體的實現(xiàn),實現(xiàn)的同時可以考慮多種方法,比如上面的CreateMutex改成CreateSemaphore,不能掛死在同一棵樹上。

實驗四實驗題目實驗四銀行家算法的模擬與實現(xiàn)實驗?zāi)康倪M一步了解進程的并發(fā)執(zhí)行。加強對進程死鎖的理解,理解安全狀態(tài)與不安全狀態(tài)的概念。掌握使用銀行家算法避免死鎖問題??傮w設(shè)計基本概念死鎖:多個進程在執(zhí)行過程中,因為競爭資源會造成相互等待的局面。如果沒有外力作用,這些進程將永遠無法向前推進。此時稱系統(tǒng)處于死鎖狀態(tài)或者系統(tǒng)產(chǎn)生了死鎖。安全序列:系統(tǒng)按某種順序并發(fā)進程,并使它們都能達到獲得最大資源而順序完成的序列為安全序列。安全狀態(tài):能找到安全序列的狀態(tài)稱為安全狀態(tài),安全狀態(tài)不會導(dǎo)致死鎖。不安全狀態(tài):在當(dāng)前狀態(tài)下不存在安全序列,則系統(tǒng)處于不安全狀態(tài)。銀行家算法銀行家算法顧名思義是來源于銀行的借貸業(yè)務(wù),一定數(shù)量的本金要滿足多個客戶的借貸周轉(zhuǎn),為了防止銀行家資金無法周轉(zhuǎn)而倒閉,對每一筆貸款,必須考察其是否能限期歸還。在操作系統(tǒng)中研究資源分配策略時也有類似問題,系統(tǒng)中有限的資源要供多個進程使用,必須保證得到的資源的進程能在有限的時間內(nèi)歸還資源,以供其它進程使用資源。如果資源分配不當(dāng),就會發(fā)生進程循環(huán)等待資源,則進程都無法繼續(xù)執(zhí)行下去的死鎖現(xiàn)象。當(dāng)一進程提出資源申請時,銀行家算法執(zhí)行下列步驟以決定是否向其分配資源:檢查該進程所需要的資源是否已超過它所宣布的最大值。檢查系統(tǒng)當(dāng)前是否有足夠資源滿足該進程的請求。系統(tǒng)試探著將資源分配給該進程,得到一個新狀態(tài)。執(zhí)行安全性算法,若該新狀態(tài)是安全的,則分配完成;若新狀態(tài)是不安全的,則恢復(fù)原狀態(tài),阻塞該進程。實驗內(nèi)容本實驗的內(nèi)容是要通過編寫和調(diào)試一個模擬系統(tǒng)動態(tài)分配資源的銀行家算法程序,有效地避免死鎖發(fā)生。具體要求如下:初始化時讓系統(tǒng)擁有一定的資源;用鍵盤輸入的方式允許進程動態(tài)申請資源;如果試探分配后系統(tǒng)處于安全狀態(tài),則修改系統(tǒng)的資源分配情況,正式分配資源;如果試探分配后系統(tǒng)處于不安全狀態(tài),則提示不能滿足請求,恢復(fù)原狀態(tài)并阻塞該進程。詳細設(shè)計主要的數(shù)據(jù)結(jié)構(gòu)程序流程圖關(guān)鍵代碼//初始化voidBanker_Algorithm::Initialization(){qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));//資源總量for(inti=0;i<Num_ResourseAndAvailable;i++){inttempAlloc=0;resLoop:if((tempAlloc=qrand()%20)>=15){Resourse[i]=tempAlloc;//qDebug()<<"Resourse"<<i<<"="<<Resourse[i];Available[i]=tem

溫馨提示

  • 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)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論