句柄是什么
句柄,handle,英文單詞,主要用作名詞、動詞,作名詞時意思是“(門的)把手;柄;(織物等的)手感;(非正式)(人或地方的)稱呼;(非正式)賭注總額”,作動詞時意思是“(用手)觸摸;以手(或前臂)觸球;操縱(車輛);(車輛)按特定方式作出反應;處理;對付(某人或某事);有辦法應付;經營;接受(或經營)贓物;泰然承受;(車輛容易或難以)駕駛;運送(貨物)”。通過門把手才能打開門。通過句柄才能使用winapi操作對象。
句柄(Handle)是一個是用來標識對象或者項目的標識符,可以用來描述窗體、文件等,值得注意的是句柄不能是常量。HANDLE:句柄,是Windows用來表示對象的(不是C++的對象),HWND是其中一種,HWND是HANDLE,但HANDLE不只是HWND,HANDLE是一個通用句柄表示,HWND是一個專用表示窗口的句柄。更具體的可查找MSDN。包含在winnt.h頭文件中。
句柄只屬于Windows,只能由WindowsAPI使用。通過句柄,程序員只能調用系統提供的服務(即API調用),不能像使用指針那樣,做其它的事。
Windows之所以要設立句柄,根本上源于內存管理機制的問題,即虛擬地址。簡而言之數據的地址需要變動,變動以后就需要有人來記錄、管理變動,因此系統用句柄來記載數據地址的變更。在程序設計中,句柄是一種特殊的智能指針,當一個應用程序要引用其他系統(如數據庫、操作系統)所管理的內存塊或對象時,就要使用句柄。
Windows是一個以虛擬內存為基礎的操作系統,很多時候,進程的代碼和數據并不全部裝入內存,進程的某一段裝入內存后,還可能被換出到外存,當再次需要時,再裝入內存。兩次裝入的地址絕大多數情況下是不一樣的。也就是說,同一對象在內存中的地址會變化。(對于虛擬內存不是很了解的讀者,可以參考有關操作系統方面的書籍)那么,程序怎么才能準確地訪問到對象呢?為了解決這個問題,Windows引入了句柄。
系統為每個進程在內存中分配一定的區域,用來存放各個句柄,即一個個32位無符號整型值(32位操作系統中)。每個32位無符號整型值相當于一個指針,指向內存中的另一個區域(我們不妨稱之為區域A)。而區域A中存放的正是對象在內存中的地址。當對象在內存中的位置發生變化時,區域A的值被更新,變為當前時刻對象在內存中的地址,而在這個過程中,區域A的位置以及對應句柄的值是不發生變化的。這種機制,用一種形象的說法可以表述為:有一個固定的地址(句柄),指向一個固定的位置(區域A),而區域A中的值可以動態地變化,它時刻記錄著當前時刻對象在內存中的地址。這樣,無論對象的位置在內存中如何變化,只要我們掌握了句柄的值,就可以找到區域A,進而找到該對象。而句柄的值在程序本次運行期間是絕對不變的,我們(即系統)當然可以掌握它。這就是以不變應萬變,按圖索驥,順藤摸瓜。
所以,我們可以這樣理解Windows句柄:
數值上,是一個32位無符號整型值(32位系統下);邏輯上,相當于指針的指針;形象理解上,是Windows中各個對象的一個唯一的、固定不變的ID;作用上,Windows使用句柄來標識諸如窗口、位圖、畫筆等對象,并通過句柄找到這些對象。
下面,關于句柄,再交代一些關鍵性細節:
1.所謂“唯一”、“不變”是指在程序的一次運行中。如果本次運行完,關閉程序,再次啟動程序運行,那么這次運行中,同一對象的句柄的值和上次運行時比較,一般是不一樣的。
其實這理解起來也很自然,所謂“一把歸一把,這把是這把,那把是那把,兩者不相干”(“把”是形象的說法,就像打牌一樣,這里指程序的一次運行)。
2.句柄是對象生成時系統指定的,屬性是只讀的,程序員不能修改句柄。
3.不同的系統中,句柄的大小(字節數)是不同的,可以使用sizeof()來計算句柄的大小。
4.通過句柄,程序員只能調用系統提供的服務(即API調用),不能像使用指針那樣,做其它的事。
簡介
句柄(handle)是C++程序設計中經常提及的一個術語。它并不是一種具體的、固定不變的數據類型或實體,而是代表了程序設計中的一個廣義的概念。句柄一般是指獲取另一個對象的方法——一個廣義的指針,它的具體形式可能是一個整數、一個對象或就是一個真實的指針,而它的目的就是建立起與被訪問對象之間的惟一的聯系。
在C++中,要訪問一個對象,通常可以建立一個指向對象的指針。但是在很多具體的應用中,直接用指針代表對象并不是一個好的解決方案。
對象
句柄是Windows系統中對象或實例的標識,這些對象包括模塊、應用程序實例、窗口、控制、位圖、GDI對象、資源、文件等。
數據類型
從數據類型上來看,它只是一個16位的無符號整數。應用程序總是通過調用Windows API獲得一個句柄,之后其他 Windows函數就可以使用該句柄,以引用和操作相應的內核對象。句柄可以像指針那樣置空,那樣句柄就沒有任何意義,不代表任何內核對象。
使用
句柄在 Windows編程中是一個很重要的概念,在 Windows程序中并不是用物理地址來標識一個內存塊、文件、任務或動態裝入模塊的。相反地,Windows API給這些項目分配確定的句柄,并將句柄返回給應用程序,然后通過句柄來進行操作。
應該明白的是,句柄是一個標識符,是用來標識對象或者項目的。從數據類型上來看它只是一個16位的無符號整數。應用程序幾乎總是通過調用一個Windows函數來獲得一個句柄,之后其他的Windows函數就可以使用該句柄,以引用相應的對象。在 Windows編程中會用到大量的句柄。
好處
句柄可以給我們帶來如下的好處:
1、我們可以在實現中用尺寸大小固定的(constant-sized)對象來表示尺寸大小不定的(variable-sized)值。
2、我們可以在實現中用運行時綁定(run-time bounding)而不是編譯時(compile-timebounding)綁定的方式來處理對象。
3、對于實現的改變通常只會引起一次重新鏈接,而不是重新編譯。
4、我們可以對他人隱藏對象的實現。
發展
在早期的Windows應用程序中,句柄的使用是很頻繁的。但隨著MFC類庫發展,其對Windows內核的封裝程度不斷提高。這樣如果用MFC類庫編程的話,就很少會有機會直接對句柄進行操作。但是如果使用 Windows API函數的話,依然需要對句柄進行直接操作?。
在Windows系統中,句柄分為三大類:KernelHandle、UserHandle和應用程序自定義的Handle。KernelHandle實際上是進程內Kernel對象的指針表索引,Kernel對象包括進程、文件、信號等。但是MS為了掩蓋著一事實,在系統啟動時生成了一個所謂Obsfucator的值(其實應該是Obfuscator(混淆器),MicrosoftBugs(R):),生成Handle后將Handle與這個值異或后返回給應用程序,所以看到的Handle都是一些很大而且毫無意義的數字。這些Handle和索引的對象是由KRNL32.DLL和VMM32.VXD共同管理的,所以稱之為KernelHandle。?
UserHandle是用來標示窗口、DC等對象的,他們是真實的指針,但指向的并不是對象的開頭,有一個偏移量。同樣,這些對象是由USER32.DLL管理的。第三種Handle不過是應用程序自定義的一些索引之類的東東,具體的意義和應用程序相關。
Windows句柄本質上就是一個指向結構體的指針(define STRICT的情況下)。
struct HWND__ {int unused; };int unused的作用就是使句柄指向一個4字節的內存,以便將來句柄指向對象的地址時能夠順利“轉化”。而從始至終,unused從來沒有被顯式地使用過,所以取名為unused。顯然,這里unused的意思是“未被使用的”,而非“沒用的”。
總結
- 上一篇: Java网络编程:TCP实现群聊功能代码
- 下一篇: 怎样让硬盘分区显示整数大小