内核对象与句柄的关系

一:一个对象是不是内核对象,通常可以看创建此对象API的参数中是否需要:PSECURITY_ATTRIBUTES 类型的参数。

二:内核对象只是一个内存块,这块内存位于操作系统内核的地址空间,内存块中存放一个数据结构(此数据结构的成员有如:安全描述符、使用计数等)。

三:每个进程中有一个句柄表(handle table),这个句柄表仅供内核对象使用,如下图:


四:解开此中的秘密

比如调用创建一个线程的API:

 HANDLE  hThread ;

DWORD threadId;

 hThread = CreateThread(... , &threadId);

此时发生的事情是:系统查找句柄表,找到一项可用的分配给以上创建的线程;,hThread >> 2 得到句柄在句柄表中的索引(Windows操作系统内部使用hThread最后两位,所以

右移两位得到真正的索引);也是此时内核对象被创建,其数据结构中的引用计数初始为1(这样理解:只要内核对象被创建,其引用计数被初始化为1),这里实则发生两件事:创建了一个内核对象和创建线程的函数打开了此对象,所以内核对象的引用计数加1,这时引用计数就为2了。

当调用CloseHandle(hThread); 时发生这样的事情:系统通过hThread计算出此句柄在句柄表中的索引,然后把那一项处理后标注为空闲可用的项,内核对象的引用计数减1即此时此内核对象的引用计数为1,之后这个线程句柄与创建时产生的内核对象已经没有任何关系了。

问题:我们知道只有当内核对象的引用计数为0时,内核对象才会被销毁,而此时它的引用计数为1,那它什么时候会被销毁?

答:当此线程结束的时候,它的引用计数再减1即为0,内核对象被销毁。此时又有一个新问题产生:我们已经关闭了线程句柄,也就是这个线程句柄已经和内核对象没有瓜葛了,那么那个内核对象是怎么又可以和此线程联系起来了呢? 我觉得是创建线程时产生的那个线程ID,接下来我就证明那个ID与内核对象是有联系的:

请看如下简单的程序:

#include <stdio.h>
#include <windows.h>
#include <WinBase.h>


DWORD WINAPI ThreadProc( LPVOID lpParameter)
{
	printf("I am comming...");
	while (1){} 
	return 0;
}


int main()
{
	HANDLE hThread;
	HANDLE headle2;
	DWORD threadId;

	hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, &threadId);
	CloseHandle(hThread);  //  关闭了线程句柄
	headle2 = OpenThread(THREAD_QUERY_INFORMATION, FALSE, threadId);
	headle2= OpenThread(THREAD_QUERY_INFORMATION, FALSE, threadId);
	headle2 = OpenThread(THREAD_QUERY_INFORMATION, FALSE, threadId);

	return 0;
}


图1:


图2:


调试此程序观察headle2的值,可以发现headle2的值是有效的,即函数调用是成功的,证明了线程ID与线程创建当初产生的内核对象是有关系的。

可以猜想:当线程结束时,系统通过线程ID与内核对象联系,使其引用计数减1,为0内核对象被销毁。

ps:观察以上两图,当把CloseHandle(hThread)这一句注释掉,以上程序三次调用OpenThread(),返回值是不相同的,说明返回的句柄不是原来句柄表中原来

的索引项,而是新建了一个内容一样的索引项。让CloseHandle(hThread); 这句也执行,再看看结果:hThread与headle2 的值是一样,证明了系统

管理句柄表的规则:我们把hThread关闭之后,它所在的索引项就被标记为可用;当需要向句柄表中加入新项时会查找第一项可用的索引项,这就是

hThread与headle2 的值是一样的原因。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值