?? chap2_3.htm
字號:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><meta name="GENERATOR" content="Microsoft FrontPage 3.0"><title> WIN32開發(fā)</title></head><body link="#3973DE" alink="#3973DE" background="../bg.gif"><font SIZE="5"><b><div align="center"><center><table border="0" width="85%" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF"> <tr> </b><td><div align="center"><center><table border="0" width="615" cellpadding="0" cellspacing="0" height="20"> </table> </center></div><p align="center"><font size="4" color="#3973DE"><br> </font><font color="#3973DE"><font FACE="Times New Roman" size="5">2.3 WIN32</font><font size="5">開發(fā)</font></font></p> <font FACE="Times New Roman" size="5"><p ALIGN="JUSTIFY"></font><span style="font-size: 9pt">Visual C++5.0是一個全32位的軟件開發(fā)工具,它完全支持32位的Win32平臺開發(fā)。Win32平臺包括32位的Windows操作系統(tǒng)和軟件開發(fā)系統(tǒng)Win32 API。所謂API(應(yīng)用程序接口)指的是一組由操作系統(tǒng)提供的函數(shù)。Win32 API是Windows平臺上的一個32位的軟件開發(fā)系統(tǒng),它使應(yīng)用程序可以充分利用32位Windows操作系統(tǒng)的能力。使用Win32 API寫成的應(yīng)用程序可以在Windows95或更高版本以及Windows NT上運行。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">由于Microsoft在Windows 3.x及其Win16 API上取得巨大的成功,因此,在研制Win32 API時,首先考慮的就是保證Win32與Win16 API兼容,只有讓軟件開發(fā)者能將Win16代碼很容易移植到Win32 API上,才有實際意義。Win32 API在語法上只作了極小的改動,API的命名與Windows 的Win16 API相同,語義也相同,消息序號也相同。事實上,完全可以保存獨立的源代碼,并選擇編譯成16位的Win16程序或32位的Win32程序。</span></p> <p><span style="font-size: 9pt">其次,如其名所示,在設(shè)計Win32 API時考慮到了充分利用32位處理器的能力。隨著硬件的發(fā)展,內(nèi)存和CPU價格的降低和性能的提高,32位CPU的486、Pentium已成為主流。據(jù)有關(guān)數(shù)據(jù)顯示,目前在我國家用計算機用戶中,使用Pentium系列處理器的計算機已占80%以上。如何充分利用當前32位(和64位)處理器的能力,并預見將來處理器的發(fā)展,就成為Win32設(shè)計時考慮的重要因素之一。</span></p> <p><span style="font-size: 9pt">再次,為了擺脫操作系統(tǒng)對Intel處理器的依賴,使應(yīng)用程序可以運行于各種處理器平臺上,Win32設(shè)計時增強了它的可移植性,提供了Microsoft Windows95和Windows NT之間的透明的移植能力。雖然Windows95只能運行于Intel平臺上,但是Win32還支持Windows NT,而Windows NT已經(jīng)被移植到許多非Intel的處理器上,如Alpha、RISC硬件平臺等。</span></p> <p><span style="font-size: 9pt">Win32可以應(yīng)用于特定的操作系統(tǒng),這種系統(tǒng)可以直接控制和處理PC硬件資源,而不必象Win16 API那樣依賴于MS-DOS系統(tǒng)服務(wù)。然而,Win32不是簡單的由Win16從16位到32位的升級,更重要的在于它支持:</span><ul> <li><span style="font-size: 9pt">高性能的搶先式多任務(wù)和多線程</span></li> <li><span style="font-size: 9pt">連續(xù)的32位地址空間和先進的內(nèi)存管理</span></li> <li><span style="font-size: 9pt">對所有的可為進程共享的對象,解決了它的安全性問題</span></li> <li><span style="font-size: 9pt">內(nèi)存映射文件</span></li> </ul> <b><p></b><span style="font-size: 9pt"><font color="#3973DE">2.3.1 搶先式多任務(wù)和多線程</font></span></p> <p><span style="font-size: 9pt">我們知道Windows是一個多任務(wù)操作系統(tǒng),它提供了一次運行多個應(yīng)用程序的能力。但是,Windows 3.x和Windows95在多任務(wù)的實現(xiàn)上有所不同。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">Windows 3.x的多任務(wù)是一種由協(xié)作、軟件方式產(chǎn)生的有限的非搶先式的多任務(wù)。它是借助于每個應(yīng)用程序的消息循環(huán)這種軟件協(xié)議方式來實現(xiàn)多任務(wù)的。Windows 3.x管理所有的消息,并存放于系統(tǒng)的消息隊列中。操作系統(tǒng)判斷消息應(yīng)歸哪一個窗口去處理,再將消息發(fā)送給該窗口。每個應(yīng)用程序窗口處于等待消息狀態(tài),直到有消息來,然后進行處理,處理完畢將控制權(quán)交給操作系統(tǒng)。在對消息進行處理時,對于用戶用鍵盤或者鼠標輸入的任何命令,Win16都不會理睬。比如,我們用WORD載入一個文件時,其他程序都得等待文件I/O操作完成才能獲得響應(yīng)。而且,一個應(yīng)用程序切換到另一個應(yīng)用程序時,需要較長的等待時間。各應(yīng)用程序在取得消息、處理消息時是平等的,無優(yōu)先級的,系統(tǒng)無法設(shè)置應(yīng)用程序的優(yōu)先級和時間片的大小。</span></p> <p><span style="font-size: 9pt">Windows95的多任務(wù)是一種搶先式多任務(wù)。比如,我們在用資源管理器復制一個文件的同時,還可以啟動另外一個應(yīng)用程序,如紙牌游戲,而且隨時都可以切換回資源管理器,察看文件復制進度,系統(tǒng)始終保持較好的響應(yīng)和靈活性。Windows95的搶先式多任務(wù)機制不是用Windows 3.x下的軟件調(diào)度來實現(xiàn)的。要了解搶先式多任務(wù),我們需要首先了解一下進程和線程的概念。調(diào)入內(nèi)存準備執(zhí)行的應(yīng)用程序叫做進程(process)。每個進程至少有一條線程,叫做主線程(primary thread)。一個進程包含代碼、數(shù)據(jù)和其他屬于應(yīng)用程序的資源。一條線程包含一組指令,相關(guān)的CPU寄存器值和一個堆棧。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">在搶先式多任務(wù)操作系統(tǒng)中,系統(tǒng)在所有運行的所有進程之間對CPU時間進行共享,從而保證每個進程都能頻繁的訪問處理器,并且實現(xiàn)指令的連續(xù)執(zhí)行。這樣,每個Win32進程都需要分配一個優(yōu)先級,系統(tǒng)調(diào)度程序利用這種優(yōu)先級來決定哪一時刻該運行哪一個進程。具有高優(yōu)先級的進程(嚴格的說應(yīng)當是線程)就是當前運行的哪一個。更高優(yōu)先級的線程可以中斷當前進程的執(zhí)行。同一優(yōu)先級的線程通過時間片來調(diào)度。一個線程處于以下三種狀態(tài)之一:正在執(zhí)行,掛起,準備運行。在單處理器環(huán)境下(如Windows 95),同一時刻只能運行一個線程。有關(guān)多線程,我們還將在后面的章節(jié)里作專門介紹。</span></p> <p><span style="font-size: 9pt">為了在Win32中支持多線程進程結(jié)構(gòu),Win32在原來Win16基礎(chǔ)上增加了:</span></p> <blockquote> <p><span style="font-size: 9pt">對進程以及線程創(chuàng)建、操縱的支持</span></p> <p><span style="font-size: 9pt">對一個進程內(nèi)線程之間的同步和同步對象的支持</span></p> <p><span style="font-size: 9pt">一個統(tǒng)一的共享機制。</span></p> </blockquote> <p><b> </p> <p></b><span style="font-size: 9pt"><font color="#3973DE">2.3.2 連續(xù)的地址空間和先進的內(nèi)存管理</font></span></p> <p><span style="font-size: 9pt">對于各種操作系統(tǒng)和平臺來說,內(nèi)存管理都是一個非常重要的問題。在Windows3.1下,有兩種形式的內(nèi)存管理函數(shù)調(diào)用:局部的和全局的。全局內(nèi)存管理函數(shù)從物理內(nèi)存中分配一段,然后返回一個句柄值。該句柄可以轉(zhuǎn)換為一個GlobalLock函數(shù)所使用的遠指針。基本處理過程如下:</span><ol> <li><span style="font-size: 9pt">申請一塊可移動的內(nèi)存塊</span></li> <li><span style="font-size: 9pt">鎖定該內(nèi)存塊。因為Windows引入了虛擬內(nèi)存管理,可以把內(nèi)存塊移動到硬盤交換文件中,所以在使用內(nèi)存塊之前,必須將它鎖定在真正的內(nèi)存RAM之中,也就是告訴操作系統(tǒng),現(xiàn)在這塊內(nèi)存暫時由應(yīng)用程序來管理。</span></li> <li><span style="font-size: 9pt">對該內(nèi)存塊進行各種操作:如復制數(shù)據(jù)到內(nèi)存塊。</span></li> <li><span style="font-size: 9pt">解鎖內(nèi)存,應(yīng)用程序?qū)υ搩?nèi)存的控制交與Windows。</span></li> </ol> <p> </p> <p><span style="font-size: 9pt">下面給出一個程序片段,來說明內(nèi)存管理函數(shù)的用法。</span></p> <p><span style="font-size: 9pt">HGLOBAL memHandle;//內(nèi)存句柄</span></p> <p><span style="font-size: 9pt">char far* lpMem;//假設(shè)長度為memLen</span></p> <p><span style="font-size: 9pt">memHandle=GlobalAlloc(GHND,memLen+1);//申請內(nèi)存塊,此處未做返回結(jié)果檢查,</span></p> <p><span style="font-size: 9pt">//事實上,申請內(nèi)存有時會失敗</span></p> <p><span style="font-size: 9pt">memcpy(lpMem,string,textLen);//拷貝數(shù)據(jù),其中string為一字符串變量,textLen是這個</span></p> <p><span style="font-size: 9pt">//字符串的長度</span></p> <p><span style="font-size: 9pt">GlobalUnlock(memHandle);//解鎖內(nèi)存</span></p> <p><span style="font-size: 9pt">...</span></p> <p><span style="font-size: 9pt">GlobalFree((HGLOBAL) memHandle);//釋放內(nèi)存</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">全局內(nèi)存對所有的應(yīng)用程序都是可見的,不管是顯式的還是隱式的請求。因為Windows 3.x的實現(xiàn)方式就是所有的進程在同一地址空間中運行。局部內(nèi)存管理則是從64KB的段內(nèi)分配對象并返回所分配內(nèi)存的16位偏移量。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">在Win32下,局部和全局內(nèi)存管理函數(shù)基本相同,仍然可以使用可移動和可丟棄選項。但是它引入了連續(xù)(flat)的32位內(nèi)存管理概念。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">在Win32中,每個進程都有其特有的32位虛擬地址空間,該空間最大可達4GB。如圖所示,低端內(nèi)存的2GB是用戶可用的,高端內(nèi)存的2GB為內(nèi)核(Kernel)保留。其中,最高的1GB用于VxD、內(nèi)存管理和文件系統(tǒng)。下面的1GB用于共享的Win32 DLL、內(nèi)存映射文件和共享內(nèi)存區(qū)域。進程所使用的虛擬地址不代表一個對象在內(nèi)存的實際的物理位置(事實上,我們大部分的PC還沒有配置4GB內(nèi)存)。操作系統(tǒng)為每個進程維護一個映射表,根據(jù)該表將虛擬地址映射到真正的物理位置處(RAM或者交換頁文件中)。</span></p> <p ALIGN="CENTER"><span style="font-size: 9pt"><img src="T2_7.gif" alt="T2_7.tif (136561 bytes)" WIDTH="385" HEIGHT="325"></span></p> <p ALIGN="CENTER"><span style="font-size: 9pt">圖2.7 Windows95的內(nèi)存映射</span></p> <p ALIGN="CENTER"> </p> <p><span style="font-size: 9pt">在Win32下局部內(nèi)存對象有一個32位句柄而不是Windows 3.x下的16位句柄,而且這個句柄是一個實際指針而不是一個相對于段的偏移量。</span></p> <p><span style="font-size: 9pt">Win32和16位Windows一個重要區(qū)別是:在Win32下,所有的進程都有自己獨立的地址空間(在進程內(nèi)部的線程仍然共享進程的內(nèi)存變量),全局內(nèi)存不再對所有的Windows應(yīng)用程序都可見。由于每個應(yīng)用程序都有自己的地址空間,一個進程分配的內(nèi)存在該進程的地址之外就不再可見。DDE會話中使用的內(nèi)存對接收者進程來說是透明的。這樣,進程的安全性就得到大大提高,程序更加強壯。一個進程崩潰一般不會影響另外一個進程的執(zhí)行。但是,這也給多個應(yīng)用程序共享內(nèi)存帶來了困難。在許多情況下,需要在多個應(yīng)用程序之間進行通訊和數(shù)據(jù)交換,這時,該怎么辦呢?Win32引入了內(nèi)存映射文件,很好的解決了這個問題。</span><b></p> <p></b><span style="font-size: 9pt"><font color="#3973DE">2.3.3 內(nèi)存映射文件</font></span></p> <p><span style="font-size: 9pt">內(nèi)存映射文件是由一個文件到一塊內(nèi)存的映射。Win32提供了允許應(yīng)用程序把文件映射到一個進程的函數(shù)(CreateFileMapping)。這樣,文件內(nèi)的數(shù)據(jù)就可以用內(nèi)存讀/寫指令來訪問,而不是用ReadFile和WriteFile這樣的I/O系統(tǒng)函數(shù),從而提高了文件存取速度。</span></p> <p><span style="font-size: 9pt">這種函數(shù)最適用于需要讀取文件并且對文件內(nèi)包含的信息做語法分析的應(yīng)用程序,如對輸入文件進行語法分析的彩色語法編輯器,編譯器等。把文件映射后進行讀和分析,能讓應(yīng)用程序使用內(nèi)存操作來操縱文件,而不必在文件里來回地讀、寫、移動文件指針。</span></p> <p><span style="font-size: 9pt">有些操作,如放棄“讀”一個字符,在以前是相當復雜的,用戶需要處理緩沖區(qū)的刷新問題。在引入了映射文件之后,就簡單的多了。應(yīng)用程序要做的只是使指針減少一個值。</span></p> <p><span style="font-size: 9pt">映射文件的另一個重要應(yīng)用就是用來支持永久命名的共享內(nèi)存。要在兩個應(yīng)用程序之間共享內(nèi)存,可以在一個應(yīng)用程序中創(chuàng)建一個文件并映射之,然后另一個應(yīng)用程序可以通過打開和映射此文件把它作為共享的內(nèi)存來使用。</span><b></p> <p></b><span style="font-size: 9pt"><font color="#3973DE">2.3.4 Win32s:Windows 3.x對Win32 API的支持</font></span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">我們經(jīng)常會遇到Win32s這個詞,它與Win32是有區(qū)別的。Win32s的s的含義是指子集(subset)。它指的是,在一個Win32程序中移入一些DLLs和一個VxD,使它運行于配置80386以上處理器的Windows 3.x系統(tǒng)之上,并且以一種增強模式運行(但有一定限制)。運行在Windows 3.x/Win32s系統(tǒng)上的Win32程序支持32位指針和32位寄存器,只需要在系統(tǒng)調(diào)用之前稍作形式替換。如果程序中使用大的數(shù)據(jù)結(jié)構(gòu)或很多的計算時,Win32s性能明顯優(yōu)于16位Windows版本,根據(jù)Microsoft的測試,性能可以提高兩倍左右;如果程序只是大量的調(diào)用Windows API,則16位版本的性能可能會強于32位版本,因為Win32s會對每一次API調(diào)用作一個從16位到32位的轉(zhuǎn)換。</span></p> <p><span style="font-size: 9pt">Win32s子集同Win32相比,不支持:多線程,高級圖形API,異步文件I/O,Unicode和安全性;而且它是運行于16位的Windows系統(tǒng)上的。但是同Win16相比,有它的優(yōu)越之處,目前在16位Windows程序開發(fā)方面有相當?shù)臐摿Α?lt;/span></p> <p><span style="font-size: 9pt">Visual C++4.1及以前版本支持Win32s,但Visual C++5.0不再支持Win32s。</span></p> <b><p></b><span style="font-size: 9pt"><font color="#3973DE">2.3.5 Win32編程基礎(chǔ)</font></span><b></p> <p><span style="font-size: 9pt">Win32數(shù)據(jù)類型</span></b></p> <p><span style="font-size: 9pt">這里的數(shù)據(jù)類型指的是一些關(guān)鍵字,這些關(guān)鍵字定義了Win32中的函數(shù)中的有關(guān)參數(shù)和返回值的大小和意義。Win32常用的數(shù)據(jù)類型有:</span></p> <p> </p> <table BORDER="1" CELLSPACING="2" BORDERCOLOR="#7f7f7f" CELLPADDING="1" WIDTH="557"> <tr> <td WIDTH="16%"><span style="font-size: 9pt">數(shù)據(jù)類型</span></td> <td WIDTH="84%"><span style="font-size: 9pt">描述</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">HANDLE</span></td> <td WIDTH="84%"><span style="font-size: 9pt">定義一個32位無符號的整數(shù),用作句柄</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">HINSTANCE</span></td> <td WIDTH="84%"><span style="font-size: 9pt">定義一個32位的無符號整數(shù),用作實例句柄</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">HWND</span></td> <td WIDTH="84%"><span style="font-size: 9pt">定義一個32位的無符號整數(shù),用作窗口句柄</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">HDC</span></td> <td WIDTH="84%"><span style="font-size: 9pt">一個設(shè)備描述背景的句柄</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">LONG</span></td> <td WIDTH="84%"><span style="font-size: 9pt">說明一個32位帶符號整數(shù)</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">LPSTR</span></td> <td WIDTH="84%"><span style="font-size: 9pt">定義一個線性的32位字符串指針</span></td> </tr> <tr> <td WIDTH="16%"><span style="font-size: 9pt">UINT</span></td> <td WIDTH="84%"><span style="font-size: 9pt">定義一個新的Win32數(shù)據(jù)類型,它會把一個參數(shù)強制轉(zhuǎn)換成Windows3.x應(yīng)用中的16位值或Win32應(yīng)用中的32位</span></td>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -