参考资料:http://blog.csdn.net/newjerryj/article/details/4383701html
http://www.cnblogs.com/yellowyu/archive/2009/06/07/1497910.html程序员
写在前面:编程
对于“句柄”,在下一直停留在只知其一;不知其二的认识层面,近日在下学习Windows编程,决定趁此机会将句柄完全搞清楚。查阅了一些网络上的资料,发现网络上的讲解大概能够分为两类:一种是以比喻、类比的方式说明,这种方法虽然形象易懂,但并无从原理上、本质上加以揭示,让人仍然想问“为何?”、“怎么实现?”。另外一种是给出源代码,无可厚非,这固然是最本质的说明了,但这样一来,又显得不够直观,初学者理解起来有必定的难度。鉴于此,在下尽微末之能,结合本身的愚见,在二者之间折中,用图解的方式来将原理呈现出来,作到一目了然。网络
这里须要说明:学习
1.这里将句柄所能标识的全部东西(如窗口、文件、画笔等)统称为“对象”。spa
2.图中一个小横框表示必定大小的内存区域,并不表明一个字节,如标有0X00000AC6的横框表示4个字节。操作系统
3.图解的目的是为了直观易懂,因此不必定与源码彻底对应,会有必定的简化。.net
让咱们先看图,再解释。指针
其中,图1是程序运行到某时刻时的内存快照,图2是程序日后运行到另外一时刻时的内存快照。红色部分标出了两次的变化。htm
简单解释:
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.在下知识有限,理解不深,若有错误纰漏之处,这里再三恳请你们必定要为在下指出。你们的批评指正是在下进步的源泉。