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