内核对象句柄是特定于进程的。也就是说,一个进程必须创建一个内核对象或打开一个现有的对象来获得一个对象句柄。任何进程都可以为现有的内核对象创建一个新的句柄(即使是由其他进程创建的对象),前提是该进程知道对象的名称,并可以按用户安全性定义对对象的访问。有关安全性的更多信息,请参阅安全.
进程可以继承或复制以下类型的内核对象的句柄:
*进程
*线程
*文件(包括文件映射对象)
*活动
*信号灯
*互斥
*管道(命名和匿名)
*邮筒
*通讯设备
所有其他内核对象对创建它们的进程是私有的;对象句柄不能重复或继承。
如果在创建原始句柄时指定了继承,并且子进程是使用“inherit handles”标志设置创建的,则子进程从其父进程继承一个打开的句柄。继承的句柄仅在子进程的上下文中有效。
DuplicateHandle功能将句柄复制到当前进程或另一进程。如果应用程序将其一个句柄复制到另一个进程中,则重复的句柄仅在其他进程的上下文中有效。
复制或继承的句柄是唯一的值,但它指向与原始句柄相同的对象。
内核对象句柄包括指示应用程序要对对象执行的操作的访问权限。应用程序在创建对象或获取现有对象句柄时指定访问权限。每种类型的内核对象都支持自己的一组访问权限。例如,事件句柄可以具有“设置”或“等待”访问(或两者),文件句柄可以具有“读取”或“写入”访问(或两者),等等。有关访问权限的详细信息,请参阅安全和描述各个对象的主题。
在下图中,应用程序创建一个事件对象。CreateEvent函数创建事件对象并返回一个对象句柄。
创建事件对象后,应用程序可以使用事件句柄来设置或等待事件。手柄保持有效,直到应用程序关闭手柄或终止。
大多数内核对象都支持单个对象的多个句柄。例如,上图中的应用程序可以通过使用OpenEvent函数获取附加的事件对象句柄,如下图所示。
该方法使应用程序具有不同访问权限的句柄。例如,句柄1可能对事件进行“设置”和“等待”访问,而句柄2可能只有“等待”访问。
如果另一个进程知道事件名称并具有对对象的安全访问权限,则可以使用OpenEvent创建自己的事件对象句柄,如下图所示。
原始应用程序也可以通过使用DuplicateHandle功能将其一个句柄重复为相同的进程或另一个进程,如下图所示。
下图显示了子进程如何继承其父进程创建的句柄。
应用程序的子进程自动继承其父进程创建的句柄,如果在创建句柄时指定了继承,并且子进程是使用“inherit handles”标志设置创建的。请注意,在上图中,句柄2不等同于句柄1,而是引用相同的事件对象。
只要存在至少一个对象句柄,对象就保留在内存中。在下图中,应用程序使用CloseHandle函数关闭其事件对象句柄。当没有事件句柄时,系统会从内存中删除对象,如下图所示。
有时候,所有对象句柄关闭后,对象都保留在内存中。例如,线程可以创建一个事件对象并等待事件句柄。当线程正在等待时,另一个线程可以关闭相同的事件对象句柄。事件对象保留在内存中,没有任何事件对象句柄,直到事件对象被设置为信号状态并且等待操作完成为止。此时,系统从内存中删除对象。
Windows管理与其他内核对象有些不同的文件对象。文件对象包含文件指针__指向要读取或写入文件的下一个字节的指针。无论何时应用程序创建一个新的文件句柄,系统将创建一个新的文件对象。因此,多个文件对象可以引用磁盘上的单个文件,如下图所示。
只有通过复制或继承,多个文件句柄可以引用相同的文件对象,如下图所示。
下表列出了每个Windows内核对象和每个对象的创建者和析构函数。创建者函数可以创建对象和对象句柄,也可以创建一个新的现有对象句柄。析构函数关闭对象句柄。当应用程序关闭内核对象的最后一个句柄时,系统将从内存中删除该对象。
内核对象