計算機操作系統(tǒng)實驗指導(dǎo)_第1頁
計算機操作系統(tǒng)實驗指導(dǎo)_第2頁
計算機操作系統(tǒng)實驗指導(dǎo)_第3頁
計算機操作系統(tǒng)實驗指導(dǎo)_第4頁
計算機操作系統(tǒng)實驗指導(dǎo)_第5頁
已閱讀5頁,還剩172頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第二章windows的進程管理

2.1實驗一:線程的創(chuàng)建與撤銷

2.1.1實驗?zāi)康?/p>

(1)熟悉windows系統(tǒng)提供的線程創(chuàng)建與撤銷系統(tǒng)調(diào)用.

(2)掌握windows系統(tǒng)環(huán)境下線程的創(chuàng)建與撤銷方法.

2.1.2實驗準備知識

1.線程的創(chuàng)建

CeateThread。完成線程的創(chuàng)建.它在調(diào)用進程的地址空間上創(chuàng)建?個線程,執(zhí)行指定的函

數(shù),并返回新建立的線程的句柄.

原型:

HANDLECeateThread(

LPSECURITY_ATTRIBUTESIpThreadAttributes,

DWORDdwStackSize,

LPSECURITY_START_ROUTINEIpStartAddress,

LPVOIDIpparameter,

DWORDdwCreationFlags,

LPDWORDIpThreadld

);

參數(shù)說明:

⑴IpThreadAttributes:為線程指定安全屬性.為NULL時,線程得到一個默認的安全描述符.

(2)dwStackSize:線程堆棧的大小淇值為0時,其大小與調(diào)用該線程的線程堆棧大小相同.

⑶IpStartAddress:指定線程要執(zhí)行的函數(shù).

⑷Ipparameter:函數(shù)中要傳遞的參數(shù).

⑸dwCreationFlags:指定線程創(chuàng)建后所處的狀態(tài).若為CRRATE_SUSPENDED,表示創(chuàng)建后出

于掛起狀態(tài),用ResumeThread。激活線程才可以執(zhí)行.若該值為0,表示線程創(chuàng)建后立即執(zhí)行.

⑹IpThreadld:用一個32位的變量接受系統(tǒng)返回的線程標識符.若該值設(shè)為NULL,系統(tǒng)不

返回線程標識符.

返回值:

如果線程創(chuàng)建成功,將返回線程的句柄;如果失敗,系統(tǒng)返回NULL,可以調(diào)用函數(shù)

GetLastError查詢失敗的原因.

用法舉例:

staticHANDLEhHandlel=NULL;〃用于存儲線程返回句柄的變量

DWORDdwThreadlDl;〃用于存儲線程標識符的變量

〃創(chuàng)建一個名為ThreadNamel的線程

hHandlel=CeateThread((LPSECURITY_ATTRIBUTES))NULL

0,

(LPSECURITY_START_ROUTINE)ThreadNamel,

(LPDWORD)NULL,

0,&dwThreadlDl);

2.撤銷進程

ExitThread。用于撤銷當(dāng)前進程.

原型:

VOIDExitThread(

DWORDdwExitCode);〃線程返回碼

參數(shù)說明:

dwExitCode:指定線程返回碼,可以調(diào)用GetExitCodeThread。查詢返回碼的含義.

返回值:

該函數(shù)沒有返回值.

用法舉例:

ExitThread(O);〃參數(shù)0表示要撤銷進程中的所有線程

3.終止線程

TerminateThread。用于終止當(dāng)前線程.該函數(shù)與ExitThread。的區(qū)別在于,ExitThread()在撤

銷線程時將該線程所擁有的資源全部歸還給系統(tǒng),而TerminateThreadO不歸還資源.

原型:

BOOLTerminateThread(

HANDLEhHandle,〃線程句柄

DWORDdwExitCode);〃線程返回碼

參數(shù)說明:

⑴hThread:要終止線程的線程句柄.

⑵dwExitCode:指定線程返回碼,可以調(diào)用GetExitCodeThread()查詢返回碼的含義.

返回值:

函數(shù)調(diào)用成功,將返回一個非0值;若失敗,返回0,可以調(diào)用函數(shù)GetLastError()查詢失敗

的原因.

4.掛起線程

Sleep。用于掛起當(dāng)前正在執(zhí)行的線程.

原型:

VOIDSleep(DWORDdwMilliseconds);

參數(shù)說明:

dwMilliseconds;指定掛起時起單位為ms(毫秒).

返回值:

該函數(shù)沒有返回值.

5.關(guān)閉句柄

函數(shù)CloseHandle()用于關(guān)閉已打開的對象的句柄淇作用與釋放動態(tài)申請的內(nèi)存空間類

似,這樣可以釋放系統(tǒng)資源,使線程安全運行.

原型:

BOOLCloseHandle(HANDLEhObject);

參數(shù)說明:

hObject:已打開對象的句柄.

返回值:

如果函數(shù)調(diào)用成功,則返回值為非。值;如果函數(shù)調(diào)用失敗,則返回值為0.若要得到更多的

錯誤信息,調(diào)用函數(shù)GetLastError。查詢.

2.1.3實驗內(nèi)容

使用系統(tǒng)調(diào)用CreatThread()創(chuàng)建一個子線程,并在子線程中顯示;ThreadisRunning!.為了

能讓用戶清楚地看到線程的運行情況,使用Sleep。使線程掛起5s,之后使用ExitThread⑼撤銷

進程.

2.1.4實驗要求

能正確使用CreatThread。,ExitThread。及Sleep。等系統(tǒng)調(diào)用,進?步理解進程與線程理論.

2.1.5實驗指導(dǎo)

本實驗在WindowsXP,MicrosoftVisualC++6.0環(huán)境下實現(xiàn),利用WindowsSDK提供的API

完成程序的功能.實驗在WindowsXP環(huán)境下安裝由于WindowsXP,MicrosoftVisualC++6.0是

一個集成開發(fā)環(huán)境,其中包含了WindowsSDK所有工具和定義,所以安裝了

WindowsXP,MicrosoftVisualC++6.0后不用特意安裝SDK.試驗中所有的API是操作系統(tǒng)提供

的用來進行應(yīng)用程序開發(fā)的系統(tǒng)功能接口.

⑴首先啟動安裝好的,MicrosoftVisualC++6.0.

(2)在,MicrosoftVisualC++6.0環(huán)境下選擇File->new命令,然后在Project選項卡中選擇

Win32ConsoleApplication建立一個控制臺工程文件.

⑶由于CreatThread()等函數(shù)是Micros。代Windows操作系統(tǒng)的系統(tǒng)調(diào)用,因此,在下圖中

選擇AnapplicationthatsupportsMFC,之后單擊Finish按

鈕.

⑷之后將打開,MicrosoftVisualC++6,0編輯環(huán)境(見下圖),按本實驗的要求編輯C程序,之

后編輯,鏈接并運行該程序即可.

2.1.6實驗總結(jié)

在Windows系統(tǒng)中進程是資源的擁有者,線程是系統(tǒng)調(diào)用的單位.進程創(chuàng)建后,其主線程

也隨即被創(chuàng)建.在該實驗中,有創(chuàng)建了一個名為ThreadNamel的子線程,該子線程與主線程并

并發(fā)的被系統(tǒng)調(diào)度.為了能讓用戶清楚地看到線程的運行情況,在主線程創(chuàng)建了子線程之后,

將主線程掛起5s,以確保子線程能夠運行完畢,之后調(diào)用ExitThread(O)將所有線程撤銷.線程運

行如下圖所示.

2.1.7源程序

//ThreadCreate.cpp:Definestheentrypointfortheconsoleapplication.

//

include"stdafx.h"

#include"ThreadCreate.h"

#ifdef_DEBUG

#definenewDEBUG_NEW

#undefTHIS_FILE

staticcharTHIS_FILE[]=_FILE_;

#endif

lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll

//Theoneandonlyapplicationobject

CWinApptheApp;

usingnamespacestd;

voidThreadName()

(

printf(HThreadisRunning!\n");

)

staticHANDLEhHandlel=NULL;〃〃需要改成hHandle

DWORDThreadIDl;〃需要改成ThreadID

int_tmain(intargc,TCHAR*argv[],TCHAR*envp[])

(

intnRetCode=0;

hHandle=CreateThread((LPSECURITY_ATTRIBUTES)NULL,

0,

(LPTHREAD_START_ROUTINE)ThreadName/

(LPVOID)NULL,

0,

&ThreadlD);

ThreadName();〃需要在這里添加一個調(diào)用

ThreadName()l;〃需要在這里添加一個調(diào)用

Sleep(SOOO);

CloseHandle(hHandle);

ExitThread(O);

returnnRetCode;

//initializeMFCandprintanderroronfailure

if(!AfxWinlnit(::GetModuleHandle(NULL),NULL,::GetCommandLine(),0))

{

//TODO:changeerrorcodetosuityourneeds

cerr?_T("FatalError:MFCinitializationfailed")?endl;

nRetCode=1;

)

else

(

//TODO:codeyourapplication'sbehaviorhere.

CStringstrHello;

strHello.LoadString(IDS_HELLO);

cout?(LPCTSTR)strHello?endl;

}

returnnRetCode;

voidThreaNamel()

(

Printf("ThreadisRuning!\n");

)

2.1.8實驗展望

可以進一步完善程序功能,請思考以下問題.

⑴如何向線程對應(yīng)的函數(shù)傳遞參數(shù)?一個參數(shù)如何傳遞,多個參數(shù)又如何傳遞?

(2)深入理解線程與進程的概念,在Windows環(huán)境下何時使用進程,何時使用線程?

2.2實驗二:線程的同步

2.2.1實驗?zāi)康?/p>

進一步掌握windows系統(tǒng)環(huán)境下線程的創(chuàng)建和撤銷

熟悉windows系統(tǒng)提供的線程同步API

使用windows系統(tǒng)提供的線程同步API解決實際問題

2.2.2實驗準備知識:相關(guān)API函數(shù)介紹

2.2.2.1等待對象

等待對象(waitfactions)函數(shù)包括等待一個對象(WaitForSingleObject())和等待多對

象(WaitForMultipleObject())兩個API函數(shù)。

等待一個對象

WaitForMultipleObject()用于等待一個對象。他等待的對象可以為以下對象之一。

Changenotification:變化通知。

Consoleinput:控制臺輸入。

Events:事件。

Job:作業(yè)。

Mutex:互斥信號量。

Process:進程。

Semaphore:計數(shù)信號量。

Thread:線程。

Waitabletimer:定時器。

原型:

DWORDWaitForSingleObject(

HANDLEhHandle,〃對象句柄

DWORDdwMilliseconds〃等待時間

);

參數(shù)說明:

hHandle:等待對象的對象句柄。該對象句柄必須為SYNCHRONIZE訪問。

dwMilliseconds:等待時間,單位為ms。若改值為0,函數(shù)在測試對象的狀態(tài)后立即返

回,若為INFINITE,函數(shù)一直等待下去,直到收到一個信號將其喚醒,如表2-1所示。

返回值:

如果返回成功,其返回值說明是何種事件導(dǎo)致函數(shù)返回。

表2-1函數(shù)描述

WAITABANDONED等待對象的是?個互斥(mutex)對象,該互斥對象沒有被擁

有它的線程釋放,他被設(shè)置為不能被喚醒

WAIT_OBJECT_0指定對象被喚醒

WAIT_TIMEOUT超時

用法舉例:

StaiticHANDLEhHandlel=NULL;

DWORDdRes;

dRes=WaitForSingleObject(hHandlel,10);〃等待對象的句柄為hHandle,等待時間為

1000ms

等待多個對象

WaitForMultipleObject()在指定時間內(nèi)等待多個對象,他等待的對象與

WaitForSingleObject()相同。

原型:

DWORDWaitForMultipleObject(

DWORDnCount,〃句柄數(shù)組中的句柄數(shù)

XONSTHANDLE*lpHandles,〃指向?qū)ο缶浔鷶?shù)組的指針

BOOLfWaitAII,〃等待類型

DWORDdwMilliseconds〃等待時間

);

參數(shù)說明:

nCount:由指針*lpHandles指定的句柄數(shù)組中的句柄數(shù),最大數(shù)是

MAXIMUM_WAIT_OBJECTS?

*lpHandles:指向?qū)ο缶浔鷶?shù)組的指針。

fWAitAII:等待類型。若存為true,當(dāng)由IpHandles數(shù)組指定的所有對象被喚醒時函數(shù)返

回;若為FALSE,當(dāng)由IpHandles數(shù)組制定的某一個對象被喚醒時函數(shù)返回,且有返回值說

明事由哪個對象引起的函數(shù)返回。

dwMilliseconds:等待時間。單位為ms。若該值為0,函數(shù)測試對象的狀態(tài)后立即返回;

若為INFINITE,函數(shù)一直等待下去,直到收到一個信號將其喚醒。

返回值:

如果成功返回,其返回值說明是何種事件導(dǎo)致函數(shù)返回。

各參數(shù)的描述如表2-2所示。

表2-2各參數(shù)描述

m贏

WAIT_OBJECT_0to(WAIT_OBJECT芥bWaitAII為TRUE,返回值說明所有被等待的對象均

被喚醒;若

_0+nCount-l)bWaitAII為FALSE?返回值減去WAIT_OBJECT_0說明

IpHandles數(shù)組下標指定的對象滿足等待條件。如果調(diào)用時多個對象同時被喚醒,則取多個

對象中最小的那個數(shù)組下標

WAIT_ABANDONED_0to若bWaitAII為TRUE,返回值說明所有被等帶的對象

均被喚醒,并且(WIAT_ABANDONED-0+NcOUNT-l)至少有一個對象是沒有約束的互斥

對象;若bWaitAII

為FALSE,返回值減去WAIT_ABANDONED_0說明IpHandles數(shù)組下標指定的沒有約束的互斥

對象滿足等待條件

WAIT_TIMNEOUT超時且參數(shù)bWaitAII指定的條件不能滿足

信號量對象(semaphore)

信號量對象(semaphore)包括創(chuàng)建信號量(CreateSemaphore())打開信號量

OpenSemaphore()及增加信號量的值(ReleaseSemaphore())API函數(shù)。

創(chuàng)建信號量

CreateSemaphore()用I于創(chuàng)建一個信號量。

原型:

HANDLECreateSemaphore(

LPSECURITY_ATTRIBUTESIpSemaphoreAttributes,〃安全屬性

LONGIlnitialCount,〃信號量對象初始值

LONGliMaximumCount,〃信號量最大值

LPCTSTRIpName〃信號量名

);

參數(shù)說明:

IpSemaphoreAttributes:指定安全屬性,為null是,信號量得到-個默認的安全描述符。

IlnitialCount:指定信號量對象的初始值。該值必須大于等于0,小于等于

iMaximumCount?當(dāng)其值大于0是,信號量被喚醒。當(dāng)該函數(shù)釋放了一個等待該信號量的

線程時,IlnitialCount值減1,當(dāng)調(diào)用函數(shù)ReleaseSemaphore。時,按其指定的數(shù)量加一個值。

IMaximumCount:指出該信號量的最大值,該值必須大于0.

IpName:給出該信號量的名字。

返回值:

信號量創(chuàng)建成功,將返回該型號量的句柄。如果給出的信號量名是系統(tǒng)已經(jīng)存在的信號

量,將返回這個已經(jīng)存在的信號量的句柄。如果失敗,系統(tǒng)返回null,還可以調(diào)用函數(shù)

GEtLastError()查詢失敗的原因。

用法舉例:

StaticHANDLEhHandlel=null;

〃創(chuàng)建一個信號量,其初值為0,最大值為5,信號量的名字為“SemphoreNamel”

hHnadlel=CreateSemaphore(NULL,0,5,"SemphoreNamel");

打開信號量

OpenSem叩hore()用于打開一個信號量。

原型:

HANDLEOpenSem叩hore(

DWORDdwDesidedAccess,〃訪問標志

BOOLblnheritHandle,〃繼承標志

LPCTSTRIpNme〃信號量名

);

參數(shù)說明:

(1).dwDesiredAccess:指出打開后要對信號量進行何種訪問,如表2—3所示。

表2-3訪問狀態(tài)

訪問描述

SEMAPHORE_ALL_ACCESS可以進行任何對信號量的訪問

SEMPHORE_MODFIY_STATE可以使用ReleaseSemaphore()修改信號量的值,使信號量

的值成為可用狀態(tài)

SYNCHRONIZE使用等待函數(shù)(waitfunctions),等待信號量成為可用狀態(tài)

(2).blnheritHandle:指出返回的的信號量句柄是否可以繼承。

(3).IpName:給出信號量的名字

返回值:

信號量打開成功,將返回信號量的句柄;如果失敗,系統(tǒng)返回null,可以調(diào)用函數(shù)

GetLastError()查詢失敗的原因。;

用法舉例:

StaticHANDLEhHandlel=null;

〃打開一個名為"SemphoreNamel”的信號量,之后可使用ReleaseSemaphore()函

數(shù)增加信號量的值

hHandlel=OpenSemaphore(SEMAPHORE_MOFDIFY_STAR1;NULL,"

SemphoreNamel");

3.增加信號量的值

ReleaseSemaphore()用于增加信號量的值。

原型:

BOOLReleaseSemaphore(

HANDLEhSemaphore,〃信號量對象句柄

LONGIReleaseCount,〃信號量要增加數(shù)值

LPLONGIpPreiousCount〃信號量要增加數(shù)值地址

);

參數(shù)說明:

(1).hSemaphore:創(chuàng)建或打開信號量時給出的信號量對象句柄。WindowsNT中建議

使用SEMAPHORE_MODIFY_STARTE訪問屬性打開該信號量。

(2).IReleaseCount:信號量要增加數(shù)值。該值必須大于0。如果增加該值后大于信號

創(chuàng)建時給出的iMaximumCount值,則增加操作失效,函數(shù)返回FALSE。

(3).IpPreiousCount:接收信號量的一個32位的一個變量。若不需要接受該值,可

以指定為nullo

返回值:

如果成功,將返回一個非0值;如果失敗,系統(tǒng)返回一個0,可以調(diào)用一個GetLastError

()查詢失敗的原因。

用法舉例:

StaticHANDLEhHandlel=NULL;

BOOLrc;

rc=ReleaseSemaphore(hHandlel,1,NULL);〃給信號量的值加1;

2.2.3實驗內(nèi)容

完成主子兩個線程之間的同步,要求子線程先執(zhí)行。在主線程中使用系統(tǒng)調(diào)用

CreateThread()創(chuàng)建一個子線程。主線程創(chuàng)建一個子線程后進入阻塞狀態(tài),直到子線程運

行完畢后喚醒主線程。

2.2.4實驗要求

能正確使用等待對象、WaitForSingleObject()或WaitForMultipleObject(0及信號量對

象CreateSemaphore()、OpenSemaphore()、Releasesemaphore()等系統(tǒng)調(diào)用,進一步

理解線程的同步。

2.2.5實驗指導(dǎo)

具體操作過程同本章實驗一,在MicrosoftvisualC++6.0環(huán)境下建立一個MFC支持的控

制臺文件,編寫C程序,在程序中使用CreateSemaphore(NULL,0,1,"SemaphoreNamel")

創(chuàng)建?個名為"SemaphoreNamel”的信號量,信號量的初始值為0,之后使用OpenSemaphore

(SYNCHRONIZE|SEMAPHORE_MODIFY_STARTE,NULL,"SemaphoreNamel)打開該信號量,這

里訪問標志使用“SYNCHRONIZE|SEMAPHORE_MODIFY_STARTE”,以便之后可以使用

WaitForSingleObject()等待該信號量及使用Releasesemaphore()釋放該信號量,然后創(chuàng)

建一個子線程,主線程創(chuàng)建子線程后調(diào)用WaitForSingleObject(hHandlel,INFINITE),這里

等待時間設(shè)置為INFINITE表示一直等待下去,直到該信號量被喚醒為止。子線程結(jié)束,調(diào)用

Releasesemaphore(hHandlel,1,NULL)釋放信號量,使信號量的值加1。

2.2.6實驗總結(jié)

實驗完成了主、子線程的同步,主線程創(chuàng)建子線程后,主線程塞,讓子線程先執(zhí)行,等

子線程執(zhí)行完后,由子線程喚醒子線程。主子線程運行情況如圖:

D回漢

密C:\Windows\system32\cmd.exe

SemaphoreCreateSuccess?

SemaphoreOpenSuccess?

IhreadCreateSuccess?

NoviInThread?

WaitForSingleObjecterr=0

l/AIT_OBJECT?=dres=0

ReleaseSemphoreerr=0

SenphoreReleaseSuccessrc=1

Pressanykeytocontinue

主、子線程的運行情況

2.2.7源程序

2.2.7源程序

//Semaphore.cpp:Definestheentrypointfortheconsoleapplication.

//

include"stdafx.h"

include"Semaphore.h"

#ifdef_DEBUG

#definenewDEBUG_NEW

#undefTHIS_FILE

staticcharTHIS_FILE[]=_FILE_;

#endif

〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃/

//Theoneandonlyapplicationobject

CWinApptheApp;

usingnamespacestd;

staticHANDLEhl;〃線程句柄

staticHANDLEhHandlel=NULL;〃信號量句柄

voidfunc();

int_tmain(intargc,TCHAR*argv[],TCHAR*envp[])

(

intnRetCode=0;

DWORDdwThreadIDl;

DWORDdRes,err;

,一個信號量

hHandlel=CreateSemaphore(NULL/Ozl,"SemaphoreNamel");//^J?

if(hHandle==NULL)printf("SemaphoreCreate!\n");

elseprintf("SemaphoreCreateSuccess!\n");

hHandlel=OpenSemaphore(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE,

NULL,

"SemaphoreNamel");〃打開信號量

if(hHanlel==NULL)printf("SemaphoreOpenFail!\n");

elseprintf("SemaphoreOpenSuccess!\n");

hl=CreateThread((LPSECURITY_ATTRIBUTES)NULL,

0,

(LPTHREAD_START_ROUTINE)func,

(KPVOID)NULL,

0,&dwThreadlDl);〃創(chuàng)建子線程

if(hl==NULL)prienf("ThreadlcreateFail!\n");

elseprintf(uThreadlcreateSuccess!\n");

dRes=WaitForSingleObject(hHandlel,INFINITE);〃主線程等待子線程結(jié)束

err=GetLastError();

printf("WaitForSingleObjecterr=%d\n"zerr);

if(dRes==WAIT_TIMEOUT)printf("TIMEOUT!dRes=%d\n"zdRes);

elseif(dRes==WAIT_OBJECT_0)printf("WAIT_OBJECT!dRes=%d\n",dRes);

elseif(dRes==WAIT_ABANDONED)

,

printf("WAIT_ABANDONED!Dres=%d\n'/dRes);

elseprintf("dRes=%d\n"zdRes);

CloseHand(hl);

CloseHandle(hHandlel);

ExitThread(O);

returnnRetCode;

voidfunc()

(

BOOLre;

DWORDerr;

Printf("NowInThread!\n");

rc=ReleaseSemaphore(hHandlel,l,NULL);

err=GetLastError();〃子線程喚醒主線程

printf("ReleaseSemaphoreerr=%d\n",err);

if(rc==O)printf(HSemaphoreReleaseFail!\nH);

elseprintf("SemaphoreReleaseSuccess!rc=%d\n",rc);

)

2.2.8實驗展望

上面的程序完成了主、子兩個線程執(zhí)行先后順序的同步關(guān)系,思考以下問題。

如何實現(xiàn)多個線程的同步?

若允許子線程執(zhí)行多次后主線程再執(zhí)行,又如何設(shè)置信號量的初值?

實驗三:線程的互斥

2.3.1實驗?zāi)康?/p>

(1)熟練掌握Windows系統(tǒng)環(huán)境下線程的創(chuàng)建與撤銷。

(2)熟悉Windows系統(tǒng)提供的線程互斥API。

(3)使用Windows系統(tǒng)提供的線程互斥API解決實際問題。

2.3.2實驗準備知識:相關(guān)API函數(shù)介紹

23.2.1臨界區(qū)對象

臨界區(qū)對象(CriticalSection)包括初始化臨界區(qū)(InitializeCriticalSection())、進入臨界

區(qū)(EnterCriticalSection())、退出臨界區(qū)(LeaveCriticalSection())及刪除臨界區(qū)

(DeleteCriticalSection())燈API函數(shù)。

初始化臨界區(qū)

InitializeCriticalSection()用于初始化臨界區(qū)對象。

原型:

VOIDInitializeCriticalSection(

LPCRITICAL__SECTIONIpCriticalSection

);

參數(shù)說明:

IpCriticalSection:指出臨界區(qū)對象的地址。

返回值:

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

用法舉例:

LPCRITCAL_SECTIONhCriticalSection;

CRITICAL_SECTIONCritical:

hCriticalSection=&Critical;

InitializeCriticalSection(hCriticalSection);

進入臨界區(qū)

EnterCriticalSection()等待進入臨界區(qū)的權(quán)限,當(dāng)獲得該權(quán)限后進入臨界區(qū)。

原型:

VOIDEnterCriticalSection(

LPCRITICAL_SECTIONIpCriticalSection

);

參數(shù)說明:

IpCriticalSection:指出臨界區(qū)對象的地址。

返回值:

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

用法舉例:

LPCRITICAL_SECTIONhCriticalSection;

CRITICAL_SECTIONCritical;

hCriticalSection=&Critical;

EnterCriticalSection(hCriticalSection);

退出臨界區(qū)

LeaveCriticalSection。釋放臨界區(qū)的使用權(quán)限。

原型:

VOIDLeaveCriticalSection(

LPCRITICAL_SECTIONIpCriticalSection

);

參數(shù)說明:

IpCriticalSection:指出臨界區(qū)對象的地址。

返回值:

該函數(shù)沒有返回值

用法舉例:

LPCRITICAL_SECTIONhCriticalSection;

CRITICAL_SECTIONCritical;

hCriticalSection=&Critical;

LeaveCriticalSection(hCriticalSection);

刪除臨界區(qū)

DeleteCriticalSection()刪除與臨界區(qū)有關(guān)的所有系統(tǒng)資源。

原型:

VOIDDeleteCriticalSection(

LPCRITICAL_SECTIONIpCriticalSection

);

參數(shù)說明:

IpCriticalSection:指出臨界區(qū)對象的地址。

返回值:

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

用法舉例:

LPCRITICAL_SECTIONhCriticalSection;

CRITICAL_SECTIONCritical;

hCriticalSection=&Critical;

DeleteCriticalSection(hCriticalSection);

互斥對象

互斥對象(Mutex)包括創(chuàng)建互斥對象(CreateMutex())、打開互斥對象(OpenMutex

())及釋放互斥對象(ReleaseMutex())API函數(shù)。

創(chuàng)建互斥對象

CreateMutex(0用于創(chuàng)建一?個互斥對象。

原型:

HANDLECreateMutex(

LPSECURITY_ATTRIBUTESIpMutexAttributes,

BOOLblnitialOwner,

LPCTSTRIpName

);

參數(shù)說明:

IpMutexAttributes:指定安全屬性,為NULL時,信號量得到一個,默認的安全描述符。

blnitialOwner:指定初始的互斥對象。如果該值為TRUE并且互斥對象已經(jīng)純在,則調(diào)

用線程獲得互斥對象的所有權(quán),否則調(diào)用線程不能獲得互斥對象的所有權(quán)。想要知道互斥對

象是否已經(jīng)存在,參見返回值說明。

IpName:給出互斥對象的名字。

返回值:

互斥對象創(chuàng)建成功,將返回該互斥對象的句柄。如果給出的互斥對象是系統(tǒng)已經(jīng)存在的

互斥對象,將返回這個已存在互斥對象的句柄。如果失敗,系統(tǒng)返回NULL,可以調(diào)用函數(shù)

GetLastError()查詢失敗的原因。

用法舉例:

staticHANDLEhHandlel=NULL;

〃常見一個名為"MutexNamel"的互斥對象

hHandlel=CreateMutex(NULL,FALSE,"MutexNamel");

打開互斥對象

OpenMutex()用于打開一個互斥對象。

原型:

HANDLEOpenMutex(

DWORDdwDesiredAccess,

BOOLblnheritHandle,

LPCTSTRIpName

);

參數(shù)說明:

指明系統(tǒng)安全屬性支持的對互斥對象所有可能的訪問。如果系統(tǒng)安全屬性不支持,則不

能獲得對互斥對象訪問權(quán)。

(1)dwDesireAccess:指出發(fā)開后要對互.斥對象進行何種訪問,具體描述如表2-4所示。

表2-4對互斥對象的訪問種類

訪問―

-MUTEX_ALL_ACCESS可以進行對任何互斥對象的訪問

SYNCHRONIZE使用等待函數(shù)waitfunctions等待互斥對象成為可

用狀態(tài)或使用

ReleaseMutex()釋放使用權(quán),從而獲得互斥對象的

使用權(quán)

(2)blnheritHandle:指出返回信號量的句柄是否可以繼承。

(3)IpName:給出信號量的名字。

返回值

互斥對象打開成功,將返回該互斥對象的句柄;如果失敗,系統(tǒng)返回NULL,可以調(diào)用

函數(shù)GetLastError()查詢失敗的原因。

用法舉例:

staticHANDLEhHandlel=NULL;

〃打開一個名為"MutexNamel"的互斥對象

hHandle=OpenMutex(SYNCHRONIZE,NULL,"MutexNamel");

3.釋放互斥對象

ReleaseMutex()用于釋放互斥對象。

原型:

BOOLReleaseMutex(

HANDLEhMUTEX;

);

參數(shù)說明:

hMutex:Mutex對象的句柄。CreateMutex()和OpenMutex()函數(shù)返回I該句

柄。

返回值:

如果成功,將返回一個非0值;如果失敗系統(tǒng)將返回0,可以調(diào)用函數(shù)GetLastErrorO查

詢失敗的原因。

用法舉例:

staticHANDLEhHandlel=NULL;

BOOLrc;

rc=ReleaseMutex(hHandlel)

2.3.3實驗內(nèi)容

完成兩個子線程之間的互斥。在主線程中使用系統(tǒng)調(diào)用CreleaseThread()創(chuàng)建兩個子線

程,并使兩個子線程互斥的使用全局變量count。

2.3.4實驗要求

能正確的使用臨界區(qū)對象,包括初始化臨界區(qū)lnitializeCriticalSection()進入臨界區(qū)

EnterCriticalSection()>退出臨界區(qū)LeaveCritical()及刪除臨界區(qū)DeleteCriticalSection()進

一步理解線程的互斥。

2.3.5實驗指導(dǎo)

具體操作過程同實驗一,在MicrosoftVisualC++6.0環(huán)境下建立一個MFC支持的捽制

臺工程文件,編寫C程序,在主線程中使用Initia程eCriticalSection()初始化臨界區(qū),然后

建立兩個子線程,在兩個子線程中使用全局變量count的前、后分別使用EnterCriticalSeation

()進入臨界區(qū)LeaveCriticalSection()退出臨界區(qū),等兩個子線程運行完畢,主線程使用

DeleteCriticalSection()刪除臨界區(qū)并撤銷線程。

2.3.6實驗總結(jié)

該試驗完成了兩個子線程之間的互斥。若去掉互斥對象,觀察全局變量count的變化,

了解互斥對象的作用,進一步理解線程的互斥。本試驗也可以使用互斥對象(Mutex)來完

成兩個線程的互斥,互斥對象(Mutex)的使用方法與信號量對象相似,這里不再說明,請

同學(xué)自己完成。線程互斥訪問全局變量count

如圖2-5所示。

2.3.7源程序

//Mutex.cpp:Definestheentrypointfortheconsoleapplication.

//

include"stdafx.h"

#include"Mutex.h"

#ifdef_DEBUG

#definenewDEBUG_NEW

#undefTHIS_FILE

staticcharTHIS_FILE[]=_FILE_;

#endif

llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll

〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃//Theoneandonlyapplicationobject

CWinApptheApp;

Usingnamespacestd;

staticintcount=5;

staticHANDLEhl;

staticHANDLEh2;

LPCRITICAL_SECTIONhCriticalSection;〃定義指向臨界區(qū)對象的地址指針

CRITICAL_SECTIONCritical;〃定義臨界區(qū)

voidfuncl();

voidfunc2();

lnt_tmain(intargc,TCHAR*argv[],TCHAR*envp[])

{intnRetCode=0;

DWORDdwThreadIDl,dwThreadlD2;

HCriticalSection=&Critical;〃將指向臨界區(qū)對象的指針指向臨界區(qū)

InitializeCriticalSection(hCriticalSection);〃初始化臨界區(qū)

hl=CreateThread((LPSECURITY_ATTRIBUTES)NULL,

0,

(LPTHREAD_START_ROUTINE)funcl,

(LPVOID)NULL,

0,&dwThreadlDl);〃創(chuàng)建線程funcl

if(hl==NULL)printf("ThreadlcreateFAIL!\n,,);

elseprintf("ThreadlcreateSuccess!\nv);

h2=CreateThread((LPSECURITY_ATTRIBUTES)NULL,

0,

(LPTHREAD_START_ROUTINE)func2,

(LPVOID)NULL,

0,&dwThreadlD2);〃創(chuàng)建線程func2

if(h2==NULL)printf("Thread?createFAIL!\n,,);

elseprintf("Thread?createSuccess!\n,,)

Sleep(lOOO);

CloseHandle(hl);

CloseHandle(h2);

DeleteCriticalSection(hCriticalSection);〃刪除臨界區(qū)

ExitThread(O);

ReturnnRetCode;

)

voidfunc2()

{intr2;

EnterCriticalSection(hCriticalSection);〃進入臨界區(qū)

r2=count;

_sleep(100);

3r2+1;

count=r2;

printf(z/countinfunc2=%d\n?,,count);

LeaveCriticalSection(hCriticalSection);〃退出臨界區(qū)

voidfuncl()

{intrl;

EnterCriticalSection(hCriticalSection);〃進入臨界區(qū)

Rl=count;

_sleep(500);

rl=rl+l;

count=rl;

printf(/zcountinfuncl=%d\n,/,count);

LeaveCriticalSection(hCriticalSection);〃退出臨界區(qū)

2.3.8實驗展望

上面的實驗是使用臨界區(qū)對象(CriticalSection)實現(xiàn)的,同學(xué)們可以使用互斥對象

(Mutex)來完成。

在完成以上三個實驗后,同學(xué)們對Windows系統(tǒng)提供的線程創(chuàng)建與撤銷、線程的同步

與互斥、API有了一定的了解,在此基礎(chǔ)上設(shè)計并完成一個綜合性的實驗解決實際同步與互

斥問題,如生產(chǎn)者與消費者問題、讀者與寫者問題等。飾演的題目可以自行設(shè)計,但要求必

須涉及縣城的創(chuàng)建與撤銷、等待對象函數(shù)(waitFunctions)、信號量對象(Semaphore)臨界

區(qū)對象(CriticalSection)或互斥對象(Mutex)的使用。

2.4實驗四:使用命名管道實現(xiàn)進程通信

2.4.1實驗?zāi)康?/p>

(1)了解windows系統(tǒng)環(huán)境下的進程通訊機制。

(2)熟悉Windows系統(tǒng)提供的進程通信API。

2.4.2實驗準備知識:相關(guān)API函數(shù)介紹

1.建立命名管道

函數(shù)CreateNamePipe()創(chuàng)建??個命名管道實例,并返回該管道的句柄。

原型:

HANDLECreateNamePipe(

LPCTSTRIpName,〃命名管道的名字

DWORDdwOpenMode,〃命名管道的訪問模式

DWORDdwPipe'Mode,〃命名管道的模式

DWORDnMaxInstances,〃可創(chuàng)建實例的最大值

DWORDnOutBufferSize,〃以字節(jié)為單位的輸出緩沖區(qū)的大小

DWORDnlnBufferSize,〃以字節(jié)為單位的輸入緩沖區(qū)的大小

DWORDnDefaultTimeOut,〃默認超時時間

LPSECURITY_ATTRIBUTESIpSecurityAttributes〃安全屬性

);

參數(shù)說明:

IpName:為命名管道的名字,管道的命名方式為\\ServerName\pipe\pipename,其中

ServerName為用命名管道通信時服務(wù)器的主機名或IP地址,pipename為命名管道的名字,

用戶可自行定義。

dwOpenMode:指出命名管道的訪問模式。模式如表2-5所示。

dwPipeMode:指出管道的模式。模式如表2-6所示、

nMaxInstances:該命名管道可以創(chuàng)建實例的最大值。

nOutBufferSize:輸出緩沖區(qū)的大小,以字節(jié)為單位。

nlnBufferSize:輸入緩沖區(qū)的大小,以字節(jié)為單位。

nDefaultTimeOut:默認的超時時間,以ms為單位。如果函數(shù)WaitNamePipe。指出

NMWAIT_USE_DEFAULT_WAIT,每個管道實例必須指定同一值的名字。

IpSecurityAttributes:為管道指定安全屬性,為NULL時,管道得到一個默認的安全描述

符。

返回值:

如果管道創(chuàng)建成功,將返回服務(wù)器命名管道實例的句柄。如果失敗,返回

INVALID_HANDLE_VALUE,可以調(diào)用函數(shù)GetLastError()查詢失敗的原因;當(dāng)返回

ERROR_INVALID_PARAMETER時,表明參數(shù)nMaxInstances指定的值大于

PIPE_UNLIMTED_INSTANCES?

2.連接命名管道

服務(wù)器用函數(shù)ConnectNamePipe()連接命名管道。創(chuàng)建后命名管道也等待客戶端的連接,

客戶端可以使用函數(shù)CreateFile()和CallNamedPipe。進行連接。

原型:

BOOLConnectNamedPipe(

HANDLEhNamePipe,〃命名管道實例句柄

LPOVERLAPPEDIpOverlapped〃指向Overlapped結(jié)構(gòu)的指針

);

參數(shù)說明:

hNamedPipe:為命名管道創(chuàng)建時得到的一個命名管道實例句柄。

IpOverlapped:指向Overlapped結(jié)構(gòu)的指針,可設(shè)其為NULL。

返回值:

成功,將返回一個非0值;失敗,系統(tǒng)返回0,可以調(diào)用函數(shù)GetLastError()查詢失敗的

原因。

3.拆除命名管道的連接

函數(shù)DisconnecrNamePipe()拆除命名管道服務(wù)器與客戶端的連接。

原型:

BOOLDisconnectNamePipef

HANDLEhNamePipe

);

參數(shù)說明:

hNamedPipe:為命名管道創(chuàng)建時得到的一個命名管道實例句柄。

返回值:

成功,將返回一個非。值;失敗,系統(tǒng)返回0,可以調(diào)用函數(shù)GerLasrError()查詢失敗的

原因。

4.客戶端連接服務(wù)器已建立的命名管道

客戶端使用函數(shù)CallNamePipe()連接服務(wù)器建立的命名管道。

原型:

BOOLCallNamePipe(

LPCTSTRIpNamePipeName,〃命名管道的名字

LPVOIDIpInBuffer;〃輸出數(shù)據(jù)緩沖區(qū)

DWORDnlnBufferSize,〃以字節(jié)為單位的輸出數(shù)據(jù)緩沖區(qū)的大小

LPVOIDIpOurBuffer,〃輸入數(shù)據(jù)緩沖區(qū)指針

DWORDnOurBufferSize,〃以字節(jié)為單位的輸入數(shù)據(jù)緩沖區(qū)的大小

LPDWORDIpBytesRead,〃輸入字節(jié)數(shù)指針

DWORDnTimeOUT〃等待時間

);

參數(shù)說明:

IpNamedPipeName:命名管道的名字。

IpInBuffer:指出用于輸出數(shù)據(jù)(向管道寫數(shù)據(jù))的緩沖區(qū)指針。

nlnBufferSize:用于輸出數(shù)據(jù)緩沖區(qū)的大小,以字節(jié)為單位。

IpOutBuffer:指出用于接收數(shù)據(jù)(從管道讀出數(shù)據(jù))的緩沖區(qū)指針。

nOutBufferSize:指向用于接收數(shù)據(jù)緩沖區(qū)的大小,以字節(jié)為單位。

IpBytesRead:一個32位的變量,改變量用于存儲從管道讀出的字節(jié)數(shù)。

nTimeOut:等待命名管道成為可用狀態(tài)的時間,單位為ms,

返回值:

成功,將返回一個非。值;失敗,系統(tǒng)返回0,可用調(diào)用函數(shù)GetLastError。查詢失敗的

原因。

5.客戶端等待命名管道

客戶端使用函數(shù)WairNamedPipe()等待服務(wù)器連接命名管道。

原型:

BOOLWaitNamedPipe(

LPCTSTRIpNamedPipeName,〃要等待的命名管道名

DWORDnTimeOut〃等待時間

);

參數(shù)說明:

IpNamedPipeName:要等待的命名管道的名字。

nTimeOut:等待命名管道成為可用狀態(tài)的時間,單位為ms.

返回值:

在等待時間內(nèi)要連接的命名管道可以使用,將返回一個非。值。在等待時間內(nèi)要連接的

命名管道不可以使用,系統(tǒng)返回0,可用調(diào)用GetLastError。查詢失敗的原因。

2.4.3使用內(nèi)容

使用命名管道完成兩個進程之間的通信。

2.4.4實驗要求

使用Windows系統(tǒng)提供的命名管道完成兩個進程之間的通信,要求能正確使用創(chuàng)建命名

管道CreateNamePipe()、連接命名管道ConnectNamePipe()、拆除命名道的連接

DisconnectNamePipe()、連接服務(wù)器已建立的命名管道CallNamePipe()、等待命名管道

WaitNamedPipe。等API.

2.4.5實驗指導(dǎo)

完成兩個進程之間的通信,需要建立兩個過程文件,在MicrosoftVisualC++6.0環(huán)境下

建立服務(wù)器工程文件Pipeserver和客戶端工程文件PipeClienr。在服務(wù)器程序中,首先使用

CreateNamePipe()建立一個命名管道,之后使

溫馨提示

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

評論

0/150

提交評論