句柄

句柄,是整個Windows編程的基礎。一個句柄是指使用的一個唯一的整數值,即一個4字節(64位程序中爲8字節)長的數值,來標識應用程序中的不同對象和同類對象中的不同的實例,諸如,一個窗口,按鈕圖標,滾動條,輸出設備,控件或者文件等。應用程序能夠通過句柄訪問相應的對象的信息,但是句柄不是一個指針,程序不能利用句柄來直接閱讀文件中的信息。如果句柄不用在I/O文件中,它是毫無用處的。 句柄是Windows用來標誌應用程序中建立的或是使用的唯一整數,Windows使用了大量的句柄來標誌很多對象

基本信息

  • 中文名稱

    句柄

  • 外文名稱

    Handle

  • 定義

    是整個windows編程的基礎

 
  • 使用

    使用的一個唯一的整數值

  • 由來

    源於內存管理機制的問虛擬地址

  • 重要性

    在許多地方都扮演着重要的角色

基本概念摺疊編輯本段

句柄的由來

vam『windows 之所以要設立句柄,根本上源於內存管理機制的問題—虛擬地址,簡而言之數據的地址需要變動,變動以後就需要有人來記錄管理變動,(就好像戶籍管理一樣),因此係統用句柄來記載數據地址的變更。

數據對象加載進入內存中之後即獲得了地址,但是這個地址並不是固定的,(至於爲什麼以及什麼情況下變動具體需要大家研究虛擬地址的原理與機制我這裏只提我確定知道的例子)數據對象會根據需要在內存與硬盤之間遊弋移動(例如不常用的數據會爲常用數據讓出其佔用的內存空間進而被淘汰進硬盤中的虛擬內存之中以優化配置整體系統的資源進而提升效率性能),因此其物理地址總是變動的,那麼作爲管理者 則必須對 管理對象所發生的變化瞭如指掌才行,因此係統爲進程分配固定的地址(句柄)來存儲進程下的數據對象變化後的地址也就是當前的地址,其實設計機制很簡單 :系統的某個部門移動了對象的地址後,同時上報給句柄所屬部門管理者,管理者將改動寫入句柄即可。再數據被重新起用時去其所屬句柄內按內容存取即可.』vam

句柄,英文:HANDLE,在Windows編程中是一個很重要的概念,在許多地方都扮演着重要的角色。但由此而產生的句柄概念也大同小異,比如:《Microsoft Windows 3 Developer's Workshop》(Microsoft Press,by Richard Wilton)一書中句柄的概念是:在Windows環境中,句柄是用來標識項目的。

程序設計中,句柄是一種特殊的智能指針 。當一個應用程序要引用其他系統(如數據庫、操作系統)所管理的內存塊或對象時,就要使用句柄。

句柄與普通指針的區別在於,指針包含的是引用對象的內存地址,而句柄則是由系統所管理的引用標識,該標識可以被系統重新定位到一個內存地址上。這種間接訪問對象的模式增強了系統對引用對象的控制。

在上世紀80年代的操作系統(如Mac OS 和Windows)的內存管理中,句柄被廣泛應用。Unix系統的文件描述符基本上也屬於句柄。和其它桌面環境一樣,Windows API大量使用句柄來標識系統中的對象,並建立操作系統與用戶空間之間的通信渠道。例如,桌面上的一個窗體由一個HWND類型的句柄來標識。如今,內存容量的增大和虛擬內存算法使得更簡單的指針愈加受到青睞,而指向另一指針的那類句柄受到冷淡。儘管如此,許多操作系統仍然把指向私有對象的指針以及進程傳遞給客戶端內部數組下標稱爲句柄。

原理信息摺疊編輯本段

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

在《WINDOWS編程短平快》(南京大學出版社)一書中是這麼說的:句柄是WINDOWS用來標識被應用程序所建立或使用的對象的唯一整數,WINDOWS使用各種各樣的句柄標識諸如應用程序實例,窗口,控件,位圖,GDI對象等等。WINDOWS句柄有點象C語言中的文件句柄

從上面的2個定義中我們可以看到,句柄是一個標識符,是拿來標識對象或者項目的。它就像我們的車牌號一樣,每一輛註冊過的車都會有一個確定的號碼,不同的車號碼各不相同,但是也可能會在不同的時期出現兩輛號碼相同的車,只不過它們不會同時處於使用之中罷了。從數據類型上來看它只是一個32位的無符號整數。應用程序幾乎總是通過調用一個WINDOWS函數來獲得一個句柄,之後其他的WINDOWS函數就可以使用該句柄,以引用相應的對象。在WINDOWS編程中會用到大量的句柄,比如:HINSTANCE(實例句柄),HBITMAP(位圖句柄),HDC(設備描述表句柄),HICON(圖標句柄)等等。這當中還有一個通用的句柄,就是HANDLE。

語句信息摺疊編輯本段

HINSTANCE hInstance;

可以改成:

HANDLE hInstance;

上面的2條語句都是對的。

一個WINDOWS應用程序可以用不同的方法獲得一個特定項的句柄。許多API函數,諸如CreateWindow,GlobalAlloc,OpenFile的返回值都是一個句柄值。另外,WINDOWS也能通過應用程序的引出函數將一個句柄作爲參數傳送給應用程序,應用程序一旦獲得了一個確定項的句柄,便可在WINDOWS環境下的任何地方對這個句柄進行操作。其實句柄的大量使用已經影響到了每一個WINDOWS的程序設計。

一個句柄,只有當唯一地確定了一個項目的時候,它纔開始有意義。句柄對應着項目表中的一項,而只有WINDOWS本身才能直接存取這個表,應用程序只能通過API函數來處理不同的句柄。舉個例子來說吧,比如:我們可以爲我們的應用程序申請一塊內存塊,通過調用API函數GlobalAlloc,來返回一個句柄值:

hMem=GlobalAlloc(......);

其實現在hMem的值只是一個索引值,不是物理地址,應用程序還不能直接存取這塊內存。這兒還有一句題外話,是關於操作系統的內存管理的。一般情況下操作系統給應用程序分配的內存塊都是可以被移動的或者是可以丟棄的,這樣能使有限的內存資源得到充分利用。所以,我們剛開始分配到的那塊內存的地址是不確定的,因爲它是可以被移動的,所以得先鎖定那塊內存塊,這裏應用程序需要調用API函數GlobalLock函數來鎖定句柄。如下:

lpMem=GlobalLock(hMem);

這樣應用程序才能存取這塊內存。

作用介紹摺疊編輯本段

句柄是一個標識符,是拿來標識對象或者項目的。應用程序幾乎總是通過調用一個WINDOWS函數來獲得一個句柄,之後其他的WINDOWS函數就可以使用該句柄,以引用相應的對象。

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

爲了解決這個問題,Windows操作系統爲全體應用程序騰出一些內存單元,用來專門登記各應用程序的對象在內存中的地址的變化,而前者的物理地址在系統運行期間是始終保持不變的。Windows內存管理器移動了對象在內存中的位置後,會把該對象新的地址及時地告知給對應的句柄進行更新。這樣我們只要知道這個句柄,就可以間接地知道對象具體在內存中的哪個位置了。這個地址是在對象裝載(Load)時由系統分配給的,當對象卸載時(Unload)又釋放給系統。

注意事項摺疊編輯本段

內核對象句柄,是用來標識某個內核對象的一個ID 同一個對象的該id對於每個進程是不同的,具體如何實現是ms不公開的算法,以下是一個近似的,可能的算法:

進程創建時,windows系統爲進程構造了一個句柄表

當該進程希望獲得一個內核對象句柄或者創建一個內核對象從而獲得該對象句柄時

系統會將在句柄表中增加一個表項,表項的內容中存儲了指向目標內核對象的指針

同時,系統返回這個表項在句柄表中的索引作爲句柄


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章