当一个进程被初始化时,系统要为它分配一个句柄表。该句柄表只用于内核对象,不用于用户对象或GDI对象。
它只是个数据结构的数组。每个结构都包含一个指向内核对象的指针、一个访问屏蔽和一些标志。
索引 |
内核对象内存块的指针 |
访问屏蔽(标志位的DWORD) |
标志(标志位的DWORD ) |
1 |
0 x ? ? ? ? ? ? ? ? |
0 x ? ? ? ? ? ? ? ? |
0 x ? ? ? ? ? ? ? ? |
2 |
0 x ? ? ? ? ? ? ? ? |
0 x ? ? ? ? ? ? ? ? |
0 x ? ? ? ? ? ? ? ? |
... |
... |
... |
... |
创建内核对象
当进程初次被初始化时,它的句柄表是空的。然后,当进程中的线程调用创建内核对象的函数时,内核就为该对象分配一个内存块,并对它初始化。这时,内核对进程的句柄表进行扫描,找出一个空项。该指针成员将被设置为内核对象的数据结构的内存地址,访问屏蔽设置为全部访问权,同时,各个标志也作了 设置。
句柄值实际上是放入进程的句柄表中的索引,它用于标识内核对象的信息存放的位置。
关闭内核对象
无论怎样创建内核对象,都要向系统指明将通过调用CloseHandle来结束对该对象的操作:
BOOL CloseHandle(HANDLE hobj);
该函数首先检查调用进程的句柄表,以确保传递给它的索引(句柄)用于标识一个进程实际上无权访问的对象。如果该索引是有效的,那么系统就可以获得内核对象的数据结构的地址,并可确定该结构中的使用计数的数据成员。如果使用计数是0 ,该内核便从内存中撤消该内核对象。
在CloseHandle返回之前,它会清除进程的句柄表中的项目,该句柄现在对你的进程已经无效,不应该试图使用它。无论内核对象是否已经撤消,都会发生清除操作。当调用CloseHandle 函数之后,将不再拥有对内核对象的访问权,不过,如果该对象的使用计数没有递减为 0 ,那么该对象尚未被撤消。这没有问题,它只是意味着一个或多个其他进程正在使用该对象。当其他进程停止使用该对象时(通过调用CloseHandle),该对象将被撤消。
对于内核对象来说,系统将执行下列操作:当进程终止运行时,系统会自动扫描进程的句柄表。如果该表拥有任何无效项目(即在终止进程运行前没有关闭的对象),系统将关闭这些对象句柄。如果这些对象中的任何对象的使用计数降为0 ,那么内核便撤消该对象。
本文地址:http://www.cnblogs.com/fangyukuan/archive/2010/08/31/1813642.html