文件句柄和句柄


所謂句柄實際上是一個數據,是一個Long (整長型)的數據。

句柄是WONDOWS用來標識被應用程序所建立或使用的對象的唯一整數,WINDOWS使用各種各樣的句柄標識諸如應用程序實例,窗口,控制,位圖,GDI對象等等。WINDOWS句柄有點象C語言中的文件句柄。

從上面的定義中的我們可以看到,句柄是一個標識符,是拿來標識對象或者項目的,它就象我們的姓名一樣,每個人都會有一個,不同的人的姓名不一樣,但是,也可能有一個名字和你一樣的人。從數據類型上來看它只是一個16位的無符號整數。應用程序幾乎總是通過調用一個WINDOWS函數來獲得一個句柄,之后其他的WINDOWS函數就可以使用該句柄,以引用相應的對象。

如果想更透徹一點地認識句柄,我可以告訴大家,句柄是一種指向指針的指針。我們知道,所謂指針是一種內存地址。應用程序啟動后,組成這個程序的各對象是住留在內存的。如果簡單地理解,似乎我們只要獲知這個內存的首地址,那么就可以隨時用這個地址訪問對象。但是,如果您真的這樣認為,那么您就大錯特錯了。我們知道,Windows是一個以虛擬內存為基礎的操作系統。在這種系統環境下,Windows內存管理器經常在內存中來回移動對象,依此來滿足各種應用程序的內存需要。對象被移動意味着它的地址變化了。如果地址總是如此變化,我們該到哪里去找該對象呢?

為了解決這個問題,Windows操作系統為各應用程序騰出一些內存儲地址,用來專門登記各應用對象在內存中的地址變化,而這個地址(存儲單元的位置)本身是不變的。Windows內存管理器在移動對象在內存中的位置后,把對象新的地址告知這個句柄地址來保存。這樣我們只需記住這個句柄地址就可以間接地知道對象具體在內存中的哪個位置。這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Unload)又釋放給系統。


句柄地址(穩定)→記載着對象在內存中的地址────→對象在內存中的地址(不穩定)→實際對象


本質:WINDOWS程序中並不是用物理地址來標識一個內存塊,文件,任務或動態裝入模塊的,相反的,WINDOWS API給這些項目分配確定的句柄,並將句柄返回給應用程序,然后通過句柄來進行操作。


但是必須注意的是程序每次從新啟動,系統不能保證分配給這個程序的句柄還是原來的那個句柄,而且絕大多數情況的確不一樣的。假如我們把進入電影院看電影看成是一個應用程序的啟動運行,那么系統給應用程序分配的句柄總是不一樣,這和每次電影院售給我們的門票總是不同的一個座位是一樣的道理。

關於句柄和文件句柄
2008-09-04 12:16

 

       句柄是一個(通常為32位的無符號)整數,它代表一個對象。Windows中的句柄類似傳統C或者MS-DOS程序設計中使用的文件句柄。程序幾乎總是通過呼叫Windows函數取得句柄。程序在其它Windows函數中使用這個句柄,以使用它代表的對象。代號的實際值對程序來說是無關緊要的。但是,向您的程序提供代號的Windows模塊知道如何利用它來使用相對應的對象。

       句柄是WONDOWS用來標識被應用程序所建立或使用的對象的唯一整數,WINDOWS使用各種各樣的句柄標識諸如應用程序實例,窗口,控制,位圖,GDI對象等等。

       句柄是一個標識符,是拿來標識對象或者項目的,它就象我們的姓名一樣,每個人都會有一個,不同的人的姓名不一樣,但是,也可能有一個名字和你一樣的人。從數據類型上來看它只是一個16位的(或32位)無符號整數。應用程序幾乎總是通過調用一個WINDOWS函數來獲得一個句柄,之后其他的WINDOWS函數就可以使用該句柄,以引用相應的對象。

Richard Wilton:

在Windows環境中,句柄是用來標識項目的,這些項目包括:模塊(module)、任務(task)、實例 (instance)、文件(file)、內存塊(block of memory)、菜單(menu)、控制(control)、字體(font)、資源(resource),包括圖標(icon),光標 (cursor),字符串(string)等、GDI對象(GDI object),包括位圖(bitmap),畫刷(brush),元文件(metafile),調色板(palette),畫筆(pen),區域 (region),以及設備描述表(device context)。

HANDLE也是PVOID,也就是無類型指針。

       說的確切一點,句柄實際上是一種指向某種資源的指針,但與指針又有所不同:指針對應着一個數據在內存中的地址,得到了指針就可以自由地修改該數據。Windows並不希望一般程序修改其內部數據結構,因為這樣太不安全。所以Windows給每個使用GlobalAlloc等函數聲明的內存區域指定一個句柄(本質上仍是一個指針,但不要直接操作它),平時你只是在調用API函數時利用這個句柄來說明要操作哪段內存。
       引喻:牧童遙指杏花村
牧童的手為指針,杏花村的牌子為句柄,杏花村酒店為對象的實例.

附注:獲得窗口句柄三種方法

1.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)

HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)

2.HWND WindowFromPoint(POINT& Point)//獲得當前鼠標光標位置的窗口HWND

3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)

BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)

BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

       句柄不是指針(哪怕說是指針的指針,要知道指針包含了太多的信息),若說句柄含有指針的某些意思(或在某種模式情況下就是指針)似乎更好; 而把句柄當做一個人的名字,並"可以通過名字(句柄),實現對句子的引用和訪問",感覺這種比喻好象貼近,但問題是可能有許多人叫同一個名字,但句柄之所以有意義正因為它具有唯一性,所以這種比喻也有問題。如果換個說法,說句柄是表示你的進程與外界的i/o連接,把它當作是一個連接的名字是不是更恰當些? 至於文件句柄么,記得曾有資料給出這樣的解釋(大意):它類似於門把手,有它你可找到“門”這個對象,就可以控制對象"門"了,但覺得把它類比於門把手似乎並不貼切,感覺象是直譯句柄這個詞的詞意,我們知道,其實文件句柄是一個十六位長度的二進制代碼(Windows95后為32位無符號整數),代表一個已被打開文件的通道號,借助於這個句柄,你的應用程序即可使用這個相應的句柄對文件進行隨意存取操作,說白了文件句柄其實是一串代表着特殊含義的號碼; 當然其實系統是用句柄與一些資源聯系起來的,當由系統管理,動態分配給你應用程序的某些資源的代號,你就可以使用句柄訪問相應的資源了,尤其在Windows系統中,有很多東東都使用句柄,如窗口,socket……等資源都使用句柄來標識,於是也就有了窗口句柄...等之說。

 

       如果想更透徹一點地認識句柄,我可以告訴大家,句柄是一種指向指針的指針(待商議!)。我們知道,所謂指針是一種內存地址。應用程序啟動后,組成這個程序的各對象是住留在內存的。如果簡單地理解,似乎我們只要獲知這個內存的首地址,那么就可以隨時用這個地址訪問對象。但是,如果您真的這樣認為,那么您就大錯特錯了。我們知道,Windows是一個以虛擬內存為基礎的操作系統。在這種系統環境下,Windows內存管理器經常在內存中來回移動對象,依此來滿足各種應用程序的內存需要。對象被移動意味着它的地址變化了。如果地址總是如此變化,我們該到哪里去找該對象呢?
       為了解決這個問題,Windows操作系統為各應用程序騰出一些內存儲地址,用來專門登記各應用對象在內存中的地址變化,而這個地址(存儲單元的位置)本身是不變的。Windows內存管理器在移動對象在內存中的位置后,把對象新的地址告知這個句柄地址來保存。這樣我們只需記住這個句柄地址就可以間接地知道對象具體在內存中的哪個位置。這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Unload)又釋放給系統。
        句柄地址(穩定)→記載着對象在內存中的地址————→對象在內存中的地址(不穩定)→實際對象
        本質:WINDOWS程序中並不是用物理地址來標識一個內存塊,文件,任務或動態裝入模塊的,相反的,WINDOWS API給這些項目分配確定的句柄,並將句柄返回給應用程序,然后通過句柄來進行操作。
但是必須注意的是程序每次從新啟動,系統不能保證分配給這個程序的句柄還是原來的那個句柄,而且絕大多數情況的確不一樣的。假如我們把進入電影院看電影看成是一個應用程序的啟動運行,那么系統給應用程序分配的句柄總是不一樣,這和每次電影院售給我們的門票總是不同的一個座位是一樣的道理。

        句柄用以標識系統核心對象,只有系統函數知道該值的意義,應用程序不知道,不同的句柄含義也是不同的(及代表的系統數據結構是不同的)。

        句柄是一些表的索引也就是指向指針的指針,句柄和指針都是地址,句柄是Windows編程的一個關鍵性的概念,編寫Windows應用程序總是要和各種句柄打交道。所謂句柄,就是一個唯一的數,用以標識許多不同的對象類型,如窗口、菜單、內存、畫筆、畫刷、電話線路等。在Win32里,句柄是指向一個“無類型對象”(void*)的指針,也就是一個4字節長的數據。無論它的本質是什么,句柄並不是一個真正意義上的指針。從構造上看,句柄是一個指針,盡管它沒有指向用於存儲某個對象的內存位置。事實上,句柄指向一個包含了對該對象進行的引用的位置。句柄的聲明是這樣的:typedef void *HANDLE由於Windows是一個多任務操作系統,它可以同時運行多個程序或一個程序的多個副本。這些運行的程序稱為一個實例。為了對同一程序的多個副本進行管理,Windows引入了實例句柄。Windows為每個應用程序建立一張表,實例句柄就好象是這張表的一個索引。不同在於: 1,句柄所指的可以是一個很復雜的結構,並且很有可以是與系統有關的,比如說上面所說的線程的句柄,它指向的就是一個很類或者結構,他和系統有很密切的關系,當一個線程由於不可預料的原因,而終止時在系統就可以回它所占用的資料,如CPU,內存等等,反過來想可以知道,這個句柄中的某一些項,是與系統進行交互的。由於Windows系統,是一個多任務的系統,它隨時都可能要分配內存,回收內存,重組內存。 2,指針它也可以指向一個復雜的結構,但是通常是用戶定義的,所以的必需的工作都要用戶完成,特別是在刪除的時候。 但在VC++6.0中也有一些指針,它們都是處理一些小問題才用的,如最常見的字符的指針,它也是要用戶處理的如果你動態分配了內存;但是Cstring就不要用戶處理了,它其實是VC++中的一個類,所以的操作都由成員函數完成,產生(分配)由構造函數,刪除(回收)由析構函數完成。

 

1.句柄是什么?
在windows中,句柄是和對象一一對應的32位無符號整數值。對象可以映射到唯
一的句柄,句柄也可以映射到唯一的對象。
2.為什么我們需要句柄?
更准確地說,是windows需要句柄。windows需要向程序員提供必要地編程接口
,在這些接口中,允許程序員訪問、創建和銷毀對象。但是,出於封裝地考慮,wi
ndows並不想向程序員返回指針。指針包含了太多的信息。首先指針給出了對象存儲
的確切位置;其次,要操作一個指針,程序員必須知道指針所指對象的內部結構特
征,也即,windows必須向程序員暴露相應的數據結構,而這些數據結構也許是操作
系統想向程序員隱藏的。
如果說COM技術向用戶隱藏了數據,只暴露了接口並只允許按接口定義的方法操
作數據的話,句柄這種方式則允許你按自己的方式直接操作數據,但windows又不向
你直接暴露數據。直接操作數據是程序員需要的,不暴露數據是windows所需要的,
句柄封裝方式實現了各取所需。
3.句柄如何與對象映射?
封裝背后,必須有一個地方可以實現解碼,以實現句柄和對象的相互轉換。在
windows中,存在兩種映射方式:
a. 全等映射。也即,句柄本身就是一個指針。映射在這里只是類型轉換而已。
這種情況有,進程實例句柄或模塊句柄,以及資源句柄等等。
b. 基於表格的映射。這是對象指針與句柄之間最普通的映射機制。操作系統創
建表格,並保存所有要考慮的對象。需要創建新對象時,要先在表格中找到空入口
,然后把表示對象的數據添入其中。當對象被刪除時,它的數據成員和其在表中的
入口被釋放。

 

句柄就是用來區分各種內存對象的唯一標識符號,是個32位整數。有些是整個系統唯一(如窗口句柄),有些是當前進程或線程中唯一(如線程句柄,全局的有另一個標識符)。詳細的可分為許多種,都是以H開頭的。在VB中使用時全部都用Long。

 

常見的有窗口句柄(HWND),設備描述表句柄(HDC),內存句柄(HMEM),文件句柄,進程句柄,線程句柄,筆的類型句柄(HPEN),字體句柄(HFONT),區域句柄(HRGN)等等。在申請句柄時是要占用資源的,分三類SYSTEM、USER、GDI。而WINDOWS的資源是固定的,並不隨內存的擴大而擴大,所以使用完以后一定要釋放。如果只用VB本身的代碼一般是不會用到句柄的,但要是使用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不過是應用程序自定義的一些索引之類的東東,具體的意義和應用程序相關


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM