﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-快乐的源泉-文章分类-技术应用</title><link>http://www.cppblog.com/Bachelor2004/category/2221.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 14:52:36 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 14:52:36 GMT</pubDate><ttl>60</ttl><item><title>Handle(转载)</title><link>http://www.cppblog.com/Bachelor2004/articles/11595.html</link><dc:creator>快乐的源泉</dc:creator><author>快乐的源泉</author><pubDate>Wed, 23 Aug 2006 00:37:00 GMT</pubDate><guid>http://www.cppblog.com/Bachelor2004/articles/11595.html</guid><wfw:comment>http://www.cppblog.com/Bachelor2004/comments/11595.html</wfw:comment><comments>http://www.cppblog.com/Bachelor2004/articles/11595.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Bachelor2004/comments/commentRss/11595.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bachelor2004/services/trackbacks/11595.html</trackback:ping><description><![CDATA[
		<div>
				<b>1.句柄是什么？</b>
				<br />    在windows中，句柄是和对象一一对应的32位无符号整数值。对象可以映射到唯<br />一的句柄，句柄也可以映射到唯一的对象。<br /><b>2.为什么我们需要句柄？</b><br />    更准确地说，是windows需要句柄。windows需要向程序员提供必要地编程接口<br />，在这些接口中，允许程序员访问、创建和销毁对象。但是，出于封装地考虑，wi<br />ndows并不想向程序员返回指针。指针包含了太多的信息。首先指针给出了对象存储<br />的确切位置；其次，要操作一个指针，程序员必须知道指针所指对象的内部结构特<br />征，也即，windows必须向程序员暴露相应的数据结构，而这些数据结构也许是操作<br />系统想向程序员隐藏的。<br />    如果说COM技术向用户隐藏了数据，只暴露了接口并只允许按接口定义的方法操<br />作数据的话，句柄这种方式则允许你按自己的方式直接操作数据，但windows又不向<br />你直接暴露数据。直接操作数据是程序员需要的，不暴露数据是windows所需要的，<br />句柄封装方式实现了各取所需。<br /><b>3.句柄如何与对象映射？</b><br />    封装背后，必须有一个地方可以实现解码，以实现句柄和对象的相互转换。在<br />windows中，存在两种映射方式：<br />    a. 全等映射。也即，句柄本身就是一个指针。映射在这里只是类型转换而已。<br />这种情况有，进程实例句柄或模块句柄，以及资源句柄等等。<br />    b. 基于表格的映射。这是对象指针与句柄之间最普通的映射机制。操作系统创<br />建表格，并保存所有要考虑的对象。需要创建新对象时，要先在表格中找到空入口<br />，然后把表示对象的数据添入其中。当对象被删除时，它的数据成员和其在表中的<br />入口被释放。<br /><b>4.句柄的定义和实现</b><br />    我们以GDI对象为例进行讨论。创建了GDI对象，就会得到该对象的句柄。句柄<br />的对象可能是HBRUSH、HPEN、HFONT或HDC中的一种，这依赖于你创建 的GDI对象类<br />型。但是最普通的GDI对象类型是HGDIOBJ。HGDIOBJ被定义成空指针。<br />    HPEN的实际编译类型定义随编译时间宏STRICT的不同而不同。如果STRCIT已经<br />被定义了，HPEN是这样的：<br />    struct HPEN__ {int unused};<br />    typedef struct HPEN__* HPEN;<br />    如果STRICT没有定义，HPEN是这样定义的：<br />    typedef void *HANDLE;<br />    typedef HANDLE HPEN;<br />    上面这段代码是一个注重细节的程序员最接近句柄的地方，因此我们重点分析<br />一下。这里有一点点技巧。如果定义了STRICT宏，HPEN是指向有单个未使用字段的<br />结构的指针，否则HPEN是空指针。C/C++编译器允许把任何类型的指针作为空指什传<br />递，反之则不可以。两个不同类型的非空指针是互不兼容的。在STRICT版本中，编<br />译对GDI对象句柄的不正确混用将给出警告，对于非GDI句柄，如HWND、HMENU的不正<br />确混用也会给出警告，从而使程序在编译器得到更STRICT的检查。<br />    接下来的分析可能不那么令你感兴趣，但它更深刻地揭示了句柄。对GDI句柄来<br />说，尽管windows头文件把它定义成指针，但如果你仔细检查这些句柄的值，它根本<br />就不像指针，这也是为什么我说它只是一个32位无符整数值的原因。对句柄就是指<br />针的情况，这句话也仍然适用。让我们随意地生成一些句柄，比如你用GetStockOb<br />ject()以得到一些句柄，你会发现，它们的值总在区间0x01900011到0xba040389。<br />前者指向用户区中的未分配的无效区域，后者指向内核地址空间。另外你可能发现<br />，两个句柄之间的值可能只差数值1，这也说明GDI句柄不是指针。<br />    和多数人想象的不一样，句柄也不是一个单纯的索引值。对GDI对象句柄来说，<br />GDI句柄由8位 、1位堆对象标记（表明对象是否创建在堆中）、7位对象类型信息和<br />高4位为0的16位索引组成，如图：<br /> 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<br /> 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<br />|  8 位引用计数 |堆 |  对象类型7  |            16位索引           |<br />                 标<br />                 记<br />在这里你可以看到，对GDI来说，它只使用了16位作为索引。这意味着一个进程最多只<br />可以创建小于64K个句柄，实际上受其他一些限制，整个windwos系统中大概可以容纳约<br />16384(0x4000)个GDI对象。<br /><font color="#ff3300">转自：http://sjtuwang.spaces.live.com/Blog/cns!A3588D115989691F!720.entry</font><br /></div>
<img src ="http://www.cppblog.com/Bachelor2004/aggbug/11595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bachelor2004/" target="_blank">快乐的源泉</a> 2006-08-23 08:37 <a href="http://www.cppblog.com/Bachelor2004/articles/11595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>