版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 紋身定金合同范本
- 做監(jiān)理合同協(xié)議
- 福建省百校2026屆高三上學(xué)期12月聯(lián)合測評英語試卷(含答案詳解)
- 程序設(shè)計崗位面試要點及參考答案
- 英文講師考點解析
- 高效率公關(guān)經(jīng)理求職測試題目
- 健康科技產(chǎn)品經(jīng)理的面試題與解析參考
- 市場調(diào)研員面試題及問卷設(shè)計能力含答案
- 人??头繂T工培訓(xùn)考核標準
- 2025年智慧城市建設(shè)咨詢服務(wù)可行性研究報告
- 污水廠安全知識培訓(xùn)
- (2025年標準)存單轉(zhuǎn)讓協(xié)議書
- 醫(yī)學(xué)科研誠信專項培訓(xùn)
- 電力通信培訓(xùn)課件
- 第五版FMEA控制程序文件編制
- 藥物致癌性試驗必要性指導(dǎo)原則
- 軟骨肉瘤護理查房
- 高級生物化學(xué)知識要點詳解
- 肌電圖在周圍神經(jīng)病中的應(yīng)用
- 2025春季學(xué)期國開電大??啤独砉び⒄Z1》一平臺機考真題及答案(第五套)
- GB/T 45683-2025產(chǎn)品幾何技術(shù)規(guī)范(GPS)幾何公差一般幾何規(guī)范和一般尺寸規(guī)范
評論
0/150
提交評論