關於windows句柄

理解句柄

什麼是句柄?

功能上的理解:
什麼是"句柄"(handle),handle的本意是把柄,把手的意思。是你與操作系統打交道的東東。
舉個通俗的例子,比如你考上了大學,入學後,學校(操作系統)會給你一個學生證號。
注意,這個號碼是學校指定的,你無法自選。
有了這個號碼(學生證,假設一證多用)享受學校提供的服務:
如你就可以去圖書館借書,去食堂喫飯,去教室上課等等。

但你不能到食堂裏買啤酒,因爲學校不允許這種服務。
而在計算機中系統提供的服務就是API調用,你有了HANDLE,就可以理直氣壯地向系統提出調用API的服務。
而指針的權力就大多了,有了指針你可以到處去喝酒,打架,學校(操作系統)管不着,
所以句柄和指針的區別在於句柄指針調用系統提供的服務。
而句柄雖然是一個能相互區別的號碼,但與我們普通的ID號又有區別,
普通的ID號是可以由程序員自己定義的,而句柄不行,它是對象生成是系統指定的,
是爲了區別系統中存在的各個對象,這個句柄不是由程序員符給的。

概念上的理解
1。句柄,是整個windows編程的基礎,一個句柄是指使用的一個唯一的整數值,
是指一個四字節長的數值,用於標誌應用程序中的不同對象和同類對象中的不同的實例,
諸如,一個窗口,按鈕,圖標,滾動條,輸出設備,控件或者文件等。
應用程序能夠通過句柄訪問相應的對象的信息。
2。句柄不是一個指針,程序不能利用它句柄來直接閱讀文件中的信息。
如果句柄不用在I/O文件中,它是毫無用處的。
3。句柄是windows用來標誌應用程序中建立的或是使用的唯一整數,
windows使用了大量的句柄來來標誌很多對象。

機制上的理解
前面的分析很經典,但我認爲有一點必須指出的。如果不對,請各位指證。
句柄是指針,一點不假,但是這個指針又與C中的指針有不同之處。
因爲Windows是一個多任務的系統,其內存是可以移動的,
這樣的話如果某一時刻有一個指針指向一塊內存,之後的某個時刻卻被系統移走了,
如果你再用這個指針的話就會出錯。
爲了解決這一問題,windows在系統專區開一塊內存用於存放句柄,這個句柄的值就是一個地址,
當這一塊內存被移走後,windows就修改這個句柄的值,再訪問這塊內存時,句柄的值總是有效的。
正因爲這樣當你使用GlobalAlloc分配的內存時,如果你指定這塊內存的屬性是固定的,
那麼它的返回值可以直接給一個指針,如果是可以移動的,
返回值就必須給一個句柄,你就必須先GlobalLock後才能使用。
這是我對句柄理解,不知道對不對?

我的理解
其實,句柄是一個指向指針的指針。即:
在windows程序設計中,句柄僅是一個應用程序用來識別某些事情的數字

如果想更透徹一點地認識句柄,我可以告訴大家,句柄是一種指向指針的指針。
我們知 道,所謂指針是一種內存地址。
應用程序啓動後,組成這個程序的各對象是住留在內的 。
如果簡單地理解,似乎我們只要獲知這個內存的首地址,那麼就可以隨時用這個地址訪問對象。
但是,如果您真的這樣認爲,那麼您就大錯特錯了。
我們知道,Windows是一個以虛擬內存爲基礎的操作系統。在這種系統環境下,
Windows內存管理器經常在內存中來回移動對象,依此來滿足各種應用程序的內存需要。
對象被移動意味着它的地址變化 了。如果地址總是如此變化,我們該到哪裏去找該對象呢?
爲了解決這個問題,Windows操作系統爲各應用程序騰出一些內存儲地址,
用來專門 登記各應用對象在內存中的地址變化,而這個地址(存儲單元的位置)本身是不變的。
Wi ndows內存管理器在移動對象在內存中的位置後,把對象新的地址告知這個句柄地址來保存。
這樣我們只需記住這個句柄地址就可以間接地知道對象具體在內存中的哪個位置。
這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Unload)又釋放給系統 。

句柄地址(穩定)→記載着對象在內存中的地址→對象在內存中的地址(不穩定) →實際對象
    但是,必須注意的是程序每次從新啓動,系統不能保證分配給這個程序的句柄還是
原來的那個句柄,而且絕大多數情況的確不一樣的。假如我們把進入電影院看電影看成
是一個應用程序的啓動運行,那麼系統給應用程序分配的句柄總是不一樣,這和每次電
影院售給我們的門票總是不同的一個座位是一樣的道理。

############################################

bool與BOOL的區別聯繫?
bool是C++中的一種變量類型(布爾類型),只可以寫
bool   x;
x   = true;
x   = false;
在VC++中BOOL是這樣說明的:
typedef int   BOOL;
也就是說BOOL是當int用的。
BOOL   x;
x   = 1;
x   = 0;
當然爲了方便,VC++已經定義了
#define    TRUE   0
#define    FALSE  1

###############################################

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/andylin02/archive/2008/02/03/2079729.aspx

 

句柄是一種指向指針的指針。

      我們知 道,所謂指針是一種內存地址。應用程序啓動後,組成這 個程序的各對象是住留在內存的。如果簡單地理解,似乎我們只要獲知這個內存的首地址,那麼就可以隨時用這個地址 訪問對象。但是,如果您真的這樣認爲,那麼您就大錯特錯了。我們知道,Windows是一 個以虛擬內存爲基礎的操作系統。在這種系統環境下,Windows內存管理器經常在內存中來回移動對象,依此來滿足各種應用程序的內存需要。對象被移動意味着它的地址變化 了。如果地址總是如此變化,我們該到哪裏去找該對象呢?爲了解決這個問題,Windows操作系統爲各應用程序騰出一些內存儲地址,用來專門 登記各應用對象在內存中的地址變化,而這個地址(存儲單元的位置)本身是不變的。Windows內存管理器在移動對象在內存中的位置後,把對象新的地址告知這個句柄地址來保存。這樣我們只需記住這個句柄地址就可以間接地知道對象具體在內存中的哪個位置。這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Unload)又釋放給系統。句柄地址(穩定)→記載着對象在內存中的地址→對象在內存中的地址(不穩定)→實際對象。但是,必須注意的是程序每次從新啓動,系統不能保證分配給這個程序的句柄還是原來的那個句柄,而且絕大多數情況的確不一樣的。假如我們把進入電影院看電影看成 是一個應用程序的啓動運行,那麼系統給應用程序分配的句柄總是不一樣,這和每次電 影院售給我們的門票總是不同的一個座位是一樣的道理。 

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lxrm_fly/archive/2007/08/24/1757929.aspx

 

 

windows句柄

1.句柄是什麼?
    在windows中,句柄是和對象一一對應的32位無符號整數值。對象可以映射到唯
一的句柄,句柄也可以映射到唯一的對象。
2.爲什麼我們需要句柄?
    更準確地說,是windows需要句柄。windows需要向程序員提供必要地編程接口
,在這些接口中,允許程序員訪問、創建和銷燬對象。但是,出於封裝地考慮,wi
ndows並不想向程序員返回指針。指針包含了太多的信息。首先指針給出了對象存儲
的確切位置;其次,要操作一個指針,程序員必須知道指針所指對象的內部結構特
徵,也即,windows必須向程序員暴露相應的數據結構,而這些數據結構也許是操作
系統想向程序員隱藏的。
    如果說COM技術向用戶隱藏了數據,只暴露了接口並只允許按接口定義的方法操
作數據的話,句柄這種方式則允許你按自己的方式直接操作數據,但windows又不向
你直接暴露數據。直接操作數據是程序員需要的,不暴露數據是windows所需要的,
句柄封裝方式實現了各取所需。
3.句柄如何與對象映射?
    封裝背後,必須有一個地方可以實現解碼,以實現句柄和對象的相互轉換。在
windows中,存在兩種映射方式:
    a. 全等映射。也即,句柄本身就是一個指針。映射在這裏只是類型轉換而已。
這種情況有,進程實例句柄或模塊句柄,以及資源句柄等等。
    b. 基於表格的映射。這是對象指針與句柄之間最普通的映射機制。操作系統創
建表格,並保存所有要考慮的對象。需要創建新對象時,要先在表格中找到空入口
,然後把表示對象的數據添入其中。當對象被刪除時,它的數據成員和其在表中的
入口被釋放。
4.句柄的定義和實現
    我們以GDI對象爲例進行討論。創建了GDI對象,就會得到該對象的句柄。句柄
的對象可能是HBRUSH、HPEN、HFONT或HDC中的一種,這依賴於你創建 的GDI對象類
型。但是最普通的GDI對象類型是HGDIOBJ。HGDIOBJ被定義成空指針。
    HPEN的實際編譯類型定義隨編譯時間宏STRICT的不同而不同。如果STRCIT已經
被定義了,HPEN是這樣的:
    struct HPEN__ {int unused};
    typedef struct HPEN__* HPEN;
    如果STRICT沒有定義,HPEN是這樣定義的:
    typedef void *HANDLE;
    typedef HANDLE HPEN;
    上面這段代碼是一個注重細節的程序員最接近句柄的地方,因此我們重點分析
一下。這裏有一點點技巧。如果定義了STRICT宏,HPEN是指向有單個未使用字段的
結構的指針,否則HPEN是空指針。C/C++編譯器允許把任何類型的指針作爲空指什傳
遞,反之則不可以。兩個不同類型的非空指針是互不兼容的。在STRICT版本中,編
譯對GDI對象句柄的不正確混用將給出警告,對於非GDI句柄,如HWND、HMENU的不正
確混用也會給出警告,從而使程序在編譯器得到更STRICT的檢查。
    接下來的分析可能不那麼令你感興趣,但它更深刻地揭示了句柄。對GDI句柄來
說,儘管windows頭文件把它定義成指針,但如果你仔細檢查這些句柄的值,它根本
就不像指針,這也是爲什麼我說它只是一個32位無符整數值的原因。對句柄就是指
針的情況,這句話也仍然適用。讓我們隨意地生成一些句柄,比如你用GetStockOb
ject()以得到一些句柄,你會發現,它們的值總在區間0x01900011到0xba040389。
前者指向用戶區中的未分配的無效區域,後者指向內核地址空間。另外你可能發現
,兩個句柄之間的值可能只差數值1,這也說明GDI句柄不是指針。
    和多數人想象的不一樣,句柄也不是一個單純的索引值。對GDI對象句柄來說,
GDI句柄由8位 、1位堆對象標記(表明對象是否創建在堆中)、7位對象類型信息和
高4位爲0的16位索引組成,如圖:
 3 3 2 2 2 2 2 2  2  2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
 1 0 9 8 7 6 5 4  3  2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|  8 位引用計數 |堆 |  對象類型7  |            16位索引           |
                 標
                 記
在這裏你可以看到,對GDI來說,它只使用了16位作爲索引。這意味着一個進程最多隻
可以創建小於64K個句柄,實際上受其他一些限制,整個windwos系統中大概可以容納約
16384(0x4000)個GDI對象。

原文地址:http://old.blog.edu.cn/user2/zwxiao/archives/2007/1696634.shtml

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