圖解說明——究竟什麼是Windows句柄

原文鏈接:https://www.cnblogs.com/zpcdbky/p/4652151.html

寫在前面:

對於“句柄”,在下一直停留在一知半解的認識層面,近日在下學習Windows編程,決定趁此機會將句柄徹底搞清楚。查閱了一些網絡上的資料,發現網絡上的講解大概可以分爲兩類:一種是以比喻、類比的方式說明,這種方法雖然形象易懂,但並沒有從原理上、本質上加以揭示,讓人仍然想問“爲什麼?”、“怎麼實現?”。另一種是給出源代碼,無可厚非,這當然是最本質的說明了,但這樣一來,又顯得不夠直觀,初學者理解起來有一定的難度。鑑於此,在下盡微末之能,結合自己的愚見,在兩者之間折中,用圖解的方式來將原理呈現出來,做到一目瞭然。

這裏需要說明:

1.這裏將句柄所能標識的所有東西(如窗口、文件、畫筆等)統稱爲“對象”。

2.圖中一個小橫框表示一定大小的內存區域,並不代表一個字節,如標有0X00000AC6的橫框表示4個字節。

3.圖解的目的是爲了直觀易懂,所以不一定與源碼完全對應,會有一定的簡化。

讓我們先看圖,再解釋。

在這裏插入圖片描述

在這裏插入圖片描述

其中,圖1是程序運行到某時刻時的內存快照,圖2是程序往後運行到另一時刻時的內存快照。紅色部分標出了兩次的變化。

簡單解釋:

Windows是一個以虛擬內存爲基礎的操作系統,很多時候,進程的代碼和數據並不全部裝入內存,進程的某一段裝入內存後,還可能被換出到外存,當再次需要時,再裝入內存。兩次裝入的地址絕大多數情況下是不一樣的。

也就是說,同一對象在內存中的地址會變化。(對於虛擬內存不是很瞭解的讀者,可以參考有關操作系統方面的書籍)那麼,程序怎麼才能準確地訪問到對象呢?爲了解決這個問題,Windows引入了句柄。

系統爲每個進程在內存中分配一定的區域,用來存放各個句柄,即一個個32位無符號整型值(32位操作系統中)。每個32位無符號整型值相當於一個指針,指向內存中的另一個區域(我們不妨稱之爲區域A)。而區域A中存放的正是對象在內存中的地址。當對象在內存中的位置發生變化時,區域A的值被更新,變爲當前時刻對象在內存中的地址,而在這個過程中,區域A的位置以及對應句柄的值是不發生變化的。

這種機制,用一種形象的說法可以表述爲:有一個固定的地址(句柄),指向一個固定的位置(區域A),而區域A中的值可以動態地變化,它時刻記錄着當前時刻對象在內存中的地址。這樣,無論對象的位置在內存中如何變化,只要我們掌握了句柄的值,就可以找到區域A,進而找到該對象。而句柄的值在程序本次運行期間是絕對不變的,我們(即系統)當然可以掌握它。這就是以不變應萬變,按圖索驥,順藤摸瓜。

所以,我們可以這樣理解Windows句柄:

  • 數值上,是一個32位無符號整型值(32位系統下);
  • 邏輯上,相當於指針的指針;
  • 形象理解上,是Windows中各個對象的一個唯一的、固定不變的ID
  • 作用上,Windows使用句柄來標識諸如窗口、位圖、畫筆等對象,並通過句柄找到這些對象。

下面,關於句柄,再交代一些關鍵性細節:

1.所謂“唯一”、“不變”是指在程序的一次運行中。如果本次運行完,關閉程序,再次啓動程序運行,那麼這次運行中,同一對象的句柄的值和上次運行時比較,一般是不一樣的。

  其實這理解起來也很自然,所謂“一把歸一把,這把是這把,那把是那把,兩者不相干”(“把”是形象的說法,就像打牌一樣,這裏指程序的一次運行)。

2.句柄是對象生成時系統指定的,屬性是隻讀的,程序員不能修改句柄。

3.不同的系統中,句柄的大小(字節數)是不同的,可以使用sizeof()來計算句柄的大小。

4.通過句柄,程序員只能調用系統提供的服務(即API調用),不能像使用指針那樣,做其它的事。

寫在後面:

1.到此爲止,有關Windows句柄就簡單介紹到這裏。需要說明的是,本文是面向初學者的,旨在讓讀者對句柄有一個完整而清晰的認知,既要避免知其然而不知其所以然的茫然困惑,又要避免深入源碼的艱難晦澀。因此,本文並不能做到絕對的直達本質,同時也可能在個別細節上與真實情況稍有出入,但在下認爲這並不貽害初學者對句柄的認識。因爲對某一知識的認知,從幾乎一無所知或是一知半解到“精通”,往往需要更多新知識的補充,短時間內很難達到,在不影響知識的使用的前提下,先把握整體,在逐步深入細節,不失爲一個明智的選擇。想進一步深入理解Windows句柄的讀者,可以看在下的下一篇文章《源碼剖析——深入Windows句柄本質》

2.在下知識有限,理解不深,如有錯誤紕漏之處,這裏再三懇請大家一定要爲在下指出。大家的批評指正是在下進步的源泉。

轉自

https://www.cnblogs.com/zpcdbky/p/4652151.html

原文的參考:

http://blog.csdn.net/newjerryj/article/details/4383701

http://www.cnblogs.com/yellowyu/archive/2009/06/07/1497910.html

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