?? mfc教程_ mfc的進(jìn)程和線程.htm
字號(hào):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0041)http://www.vczx.com/tutorial/mfc/mfc8.php -->
<HTML><HEAD><TITLE>MFC教程_ MFC的進(jìn)程和線程</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2900.2668" name=GENERATOR></HEAD>
<BODY bgColor=#ffffff>
<OL start=8>
<P align=justify>
<LI><A name=_Toc445889076></A><A name=_Toc445782479></A><A
name=_Toc452640940></A><A name=_Toc457299038></A><B>MFC的進(jìn)程和線程</B>
<P></P>
<OL>
<P align=justify>
<LI><B><A name=_Toc445889077></A><A name=_Toc445782480></A><A
name=_Toc452640941></A><A name=_Toc457299039></A>Win32的進(jìn)程和線程概念</B>
<P></P></LI></OL></LI></OL>
<P
align=justify>進(jìn)程是一個(gè)可執(zhí)行的程序,由私有虛擬地址空間、代碼、數(shù)據(jù)和其他操作系統(tǒng)資源(如進(jìn)程創(chuàng)建的文件、管道、同步對(duì)象等)組成。一個(gè)應(yīng)用程序可以有一個(gè)或多個(gè)進(jìn)程,一個(gè)進(jìn)程可以有一個(gè)或多個(gè)線程,其中一個(gè)是主線程。</P>
<P
align=justify>線程是操作系統(tǒng)分時(shí)調(diào)度分配CPU時(shí)間的基本實(shí)體。一個(gè)線程可以執(zhí)行程序的任意部分的代碼,即使這部分代碼被另一個(gè)線程并發(fā)地執(zhí)行;一個(gè)進(jìn)程的所有線程共享它的虛擬地址空間、全局變量和操作系統(tǒng)資源。</P>
<P align=justify>之所以有線程這個(gè)概念,是因?yàn)橐跃€程而不是進(jìn)程為調(diào)度對(duì)象效率更高:</P>
<UL>
<P align=justify>
<LI>由于創(chuàng)建新進(jìn)程必須加載代碼,而線程要執(zhí)行的代碼已經(jīng)被映射到進(jìn)程的地址空間,所以創(chuàng)建、執(zhí)行線程的速度比進(jìn)程更快。
<P></P>
<P align=justify></P>
<LI>一個(gè)進(jìn)程的所有線程共享進(jìn)程的地址空間和全局變量,所以簡(jiǎn)化了線程之間的通訊。
<P></P></LI></UL>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889078></A><A name=_Toc445782481></A><A
name=_Toc452640942></A><A name=_Toc457299040></A><B>Win32的進(jìn)程處理簡(jiǎn)介</B>
<P></P>
<P align=justify>因?yàn)镸FC沒有提供類處理進(jìn)程,所以直接使用了Win32 API函數(shù)。</P>
<OL>
<P align=justify>
<LI><A name=_Toc445889079></A><A name=_Toc445782482></A><A
name=_Toc452640943></A><A name=_Toc457299041></A><B>進(jìn)程的創(chuàng)建</B>
<P></P>
<P align=justify>調(diào)用CreateProcess函數(shù)創(chuàng)建新的進(jìn)程,運(yùn)行指定的程序。CreateProcess的原型如下:</P>
<P align=justify>BOOL CreateProcess(</P>
<P align=justify>LPCTSTR lpApplicationName,</P>
<P align=justify>LPTSTR lpCommandLine,</P>
<P align=justify>LPSECURITY_ATTRIBUTES lpProcessAttributes,</P>
<P align=justify>LPSECURITY_ATTRIBUTES lpThreadAttributes,</P>
<P align=justify>BOOL bInheritHandles,</P>
<P align=justify>DWORD dwCreationFlags,</P>
<P align=justify>LPVOID lpEnvironment,</P>
<P align=justify>LPCTSTR lpCurrentDirectory,</P>
<P align=justify>LPSTARTUPINFO lpStartupInfo,</P>
<P align=justify>LPPROCESS_INFORMATION lpProcessInformation</P>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>lpApplicationName指向包含了要運(yùn)行模塊名字的字符串。</P>
<P align=justify>lpCommandLine指向命令行字符串。</P>
<P align=justify>lpProcessAttributes描述進(jìn)程的安全性屬性,NT下有用。</P>
<P align=justify>lpThreadAttributes描述進(jìn)程初始線程(主線程)的安全性屬性,NT下有用。</P>
<P
align=justify>bInHeritHandles表示子進(jìn)程(被創(chuàng)建的進(jìn)程)是否可以繼承父進(jìn)程的句柄。可以繼承的句柄有線程句柄、有名或無(wú)名管道、互斥對(duì)象、事件、信號(hào)量、映像文件、普通文件和通訊端口等;還有一些句柄不能被繼承,如內(nèi)存句柄、DLL實(shí)例句柄、GDI句柄、URER句柄等等。</P>
<P align=justify>子進(jìn)程繼承的句柄由父進(jìn)程通過命令行方式或者進(jìn)程間通訊(IPC)方式由父進(jìn)程傳遞給它。</P>
<P
align=justify>dwCreationFlags表示創(chuàng)建進(jìn)程的優(yōu)先級(jí)類別和進(jìn)程的類型。創(chuàng)建進(jìn)程的類型分控制臺(tái)進(jìn)程、調(diào)試進(jìn)程等;優(yōu)先級(jí)類別用來(lái)控制進(jìn)程的優(yōu)先級(jí)別,分Idle、Normal、High、Real_time四個(gè)類別。</P>
<P align=justify>lpEnviroment指向環(huán)境變量塊,環(huán)境變量可以被子進(jìn)程繼承。</P>
<P align=justify>lpCurrentDirectory指向表示當(dāng)前目錄的字符串,當(dāng)前目錄可以繼承。</P>
<P align=justify>lpStartupInfo指向StartupInfo結(jié)構(gòu),控制進(jìn)程的主窗口的出現(xiàn)方式。</P>
<P
align=justify>lpProcessInformation指向PROCESS_INFORMATION結(jié)構(gòu),用來(lái)存儲(chǔ)返回的進(jìn)程信息。</P>
<P align=justify>從其參數(shù)可以看出創(chuàng)建一個(gè)新的進(jìn)程需要指定什么信息。</P>
<P
align=justify>從上面的解釋可以看出,一個(gè)進(jìn)程包含了很多信息。若進(jìn)程創(chuàng)建成功的話,返回一個(gè)進(jìn)程信息結(jié)構(gòu)類型的指針。進(jìn)程信息結(jié)構(gòu)如下:</P>
<P align=justify>typedef struct _PROCESS_INFORMATION {</P>
<P align=justify>HANDLE hProcess; </P>
<P align=justify>HANDLE hThread; </P>
<P align=justify>DWORD dwProcessId; </P>
<P align=justify>DWORD dwThreadId; </P>
<P align=justify>}PROCESS_INFORMATION; </P>
<P align=justify>進(jìn)程信息結(jié)構(gòu)包括進(jìn)程句柄,主線程句柄,進(jìn)程ID,主線程ID。</P>
<P align=justify></P>
<LI><A name=_Toc445889080></A><A name=_Toc445782483></A><A
name=_Toc452640944></A><A name=_Toc457299042></A><B>進(jìn)程的終止</B>
<P></P></LI></OL></LI></OL></OL>
<P align=justify>進(jìn)程在以下情況下終止:</P>
<UL>
<P align=justify>
<LI>調(diào)用ExitProcess結(jié)束進(jìn)程;
<P></P>
<P align=justify></P>
<LI>進(jìn)程的主線程返回,隱含地調(diào)用ExitProcess導(dǎo)致進(jìn)程結(jié)束;
<P></P>
<P align=justify></P>
<LI>進(jìn)程的最后一個(gè)線程終止;
<P></P>
<P align=justify></P>
<LI>調(diào)用TerminateProcess終止進(jìn)程。
<P></P>
<P align=justify></P>
<LI>當(dāng)要結(jié)束一個(gè)GDI進(jìn)程時(shí),發(fā)送WM_QUIT消息給主窗口,當(dāng)然也可以從它的任一線程調(diào)用ExitProcess。
<P></P></LI></UL>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889081></A><A name=_Toc445782484></A><A
name=_Toc452640945></A><A name=_Toc457299043></A><B>Win32的線程</B>
<P></P>
<OL>
<P align=justify>
<LI><B><A name=_Toc445889082></A><A name=_Toc445782485></A><A
name=_Toc452640946></A><A name=_Toc457299044></A>線程的創(chuàng)建</B>
<P></P></LI></OL></LI></OL></OL>
<P align=justify>使用CreateThread函數(shù)創(chuàng)建線程,CreateThread的原型如下:</P>
<P align=justify>HANDLE CreateThread(</P>
<P align=justify>LPSECURITY_ATTRIBUTES lpThreadAttributes,</P>
<P align=justify>DWORD dwStackSize,</P>
<P align=justify>LPTHREAD_START_ROUTINE lpStartAddress,</P>
<P align=justify>LPVOID lpParameter,</P>
<P align=justify>DWORD dwCreationFlags, // creation flags</P>
<P align=justify>LPDWORD lpThreadId</P>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>lpThreadAttributes表示創(chuàng)建線程的安全屬性,NT下有用。</P>
<P align=justify>dwStackSize指定線程棧的尺寸,如果為0則與進(jìn)程主線程棧相同。</P>
<P align=justify>lpStartAddress指定線程開始運(yùn)行的地址。</P>
<P align=justify>lpParameter表示傳遞給線程的32位的參數(shù)。</P>
<P
align=justify>dwCreateFlages表示是否創(chuàng)建后掛起線程(取值CREATE_SUSPEND),掛起后調(diào)用ResumeThread繼續(xù)執(zhí)行。</P>
<P align=justify>lpThreadId用來(lái)存放返回的線程ID。</P>
<P align=justify></P>
<UL>
<P align=justify>
<LI>線程的優(yōu)先級(jí)別
<P></P></LI></UL>
<P
align=justify>進(jìn)程的每個(gè)優(yōu)先級(jí)類包含了五個(gè)線程的優(yōu)先級(jí)水平。在進(jìn)程的優(yōu)先級(jí)類確定之后,可以改變線程的優(yōu)先級(jí)水平。用SetPriorityClass設(shè)置進(jìn)程優(yōu)先級(jí)類,用SetThreadPriority設(shè)置線程優(yōu)先級(jí)水平。</P>
<P align=justify>Normal級(jí)的線程可以被除了Idle級(jí)以外的任意線程搶占。</P>
<OL>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889083></A><A name=_Toc445782486></A><A
name=_Toc452640947></A><A name=_Toc457299045></A><B>線程的終止</B>
<P></P></LI></OL></OL></OL>
<P align=justify>以下情況終止一個(gè)線程:</P>
<UL>
<P align=justify>
<LI>調(diào)用了ExitThread函數(shù);
<P></P>
<P align=justify></P>
<LI>線程函數(shù)返回:主線程返回導(dǎo)致ExitProcess被調(diào)用,其他線程返回導(dǎo)致ExitThread被調(diào)用;
<P></P>
<P align=justify></P>
<LI>調(diào)用ExitProcess導(dǎo)致進(jìn)程的所有線程終止;
<P></P>
<P align=justify></P>
<LI>調(diào)用TerminateThread終止一個(gè)線程;
<P></P>
<P align=justify></P>
<LI>調(diào)用TerminateProcess終止一個(gè)進(jìn)程時(shí),導(dǎo)致其所有線程的終止。
<P></P></LI></UL>
<P
align=justify>當(dāng)用TerminateProcess或者TerminateThread終止進(jìn)程或線程時(shí),DLL的入口函數(shù)DllMain不會(huì)被執(zhí)行(如果有DLL的話)。</P>
<OL>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889084></A><A name=_Toc445782487></A><A
name=_Toc452640948></A><A name=_Toc457299046></A><B>線程局部存儲(chǔ)</B>
<P align=justify>如果希望每個(gè)線程都可以有線程局部(Thread
local)的靜態(tài)存儲(chǔ)數(shù)據(jù),可以使用TLS線程局部存儲(chǔ)技術(shù)。TLS為進(jìn)程分配一個(gè)TLS索引,進(jìn)程的每個(gè)線程通過這個(gè)索引存取自己的數(shù)據(jù)變量的拷貝。</P>
<P
align=justify>TLS對(duì)DLL是非常有用的。當(dāng)一個(gè)新的進(jìn)程使用DLL時(shí),在DLL入口函數(shù)DllMain中使用TlsAlloc分配TLS索引,TLS索引就作為進(jìn)程私有的全局變量被保存;以后,當(dāng)該進(jìn)程的新的線程使用DLL時(shí)(Attahced
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -