2024年3月14日发(作者:)

句柄和指针区别。

从广义上,能够从一个数值拎起一大堆数据的东西都可以叫做句柄。句柄的英文是

"Handle",本义就是"柄" 。

指针其实也是一种"句柄",只是由于指针同时拥有更特殊的含义——实实在在地对应

内存里地一个地址——所以,通常不把指针说成是"句柄"。但指针也有着能从一个32位

的值引用到一大堆数据的作用。

Windows系统中有许多内核对象(这里的对象不完全等价于"面向对象程序设计"一词

中的"对象",虽然实质上还真差不多),比如打开的文件,创建的线程,程序的窗口,等等。

这些重要的对象肯定不是4个字节或者8个字节足以完全描述的,他们拥有大量的属性。

为了保存这样一个"对象"的状态,往往需要上百甚至上千字节的内存空间,那么怎么在程

序间或程序内部的子过程(函数)之间传递这些数据呢? Windows操作系统就采用进一

步的间接:在进程的地址空间中设一张表,表里头专门保存一些编号和由这个编号对应一

个地址,而由那个地址去引用实际的对象,这个编号跟那个地址在数值上没有任何规律性

的联系,纯粹是个映射而已。

在Windows系统中,这个编号就叫做"句柄"。

Handle在Windows中的含义很广泛,以下关于谈到的Handle除非特别说明,将仅

限于进程、线程的上下文中。

1、先来谈谈Handle

Handle本身是一个32位的无符号整数,它用来代表一个内核对象。它并不指向实际

的内核对象,用户模式下的程序永远不可能获得一个内核对象的实际地址(一般情况下)。

那么Handle的意义何在?它实际上是作为一个索引在一个表中查找对应的内核对象的实

际地址。那么这个表在哪里呢?每个进程都有这样的一个表,叫句柄表。该表的第一项就

是进程自己的句柄,这也是为什么你调用GetCurrentProcess()总是返回0x7FFFFFFF原

因。

简单地说,Handle就是一种用来"间接"代表一个内核对象的整数值。你可以在程序中

使用handle来代表你想要操作的内核对象。这里的内核对象包括:事件(Event)、线程、

进程、Mutex等等。我们最常见的就是文件句柄(file handle)。

另外要注意的是,Handle仅在其所属的进程中才有意义。将一个进程拥有的handle

传给另一个进程没有任何意义,如果非要这么做,则需要使用DuplicateHandle(),在多

个进程间传递Handle是另外一个话题了,与这里要讨论的无关。

2、进程ID

首先,进程ID是一个32位无符号整数,每个进程都有这样的一个ID,并且该ID在

系统范围内是唯一的。系统使用该ID来唯一确定一个进程。

深入些说,系统可能使用进程ID来计算代表该进程的内核对象的基地址(及

EPROCESS结构的基地址),具体的计算公式你可以去问微软的OS开发人员。

3、HINSTANCE