句柄表的详细说明
什么内核对像
像进程,线程,文件,互斥体,事件等在内核都有一个对应的结构体,这些结构体由内核负责管理。我们称这样的对象为内核对象。
如何管理内核对象
- 该案例中一个进程可以对应4个内核对象,创建一个文件,线程等,内核中的内核对象才是核心,它控制了几乎所有的信息,用户层的不过是一个接口而已。
但是,在创建完那些内核对象后,用户层需要使用这些内核对象。 - 最简单的办法就是在使用这些内核对象时返回这些内核对象的结构体地址,但是为了安全考虑,操作系统禁止用户直接访问内核区(比如用户修改的内核对象的地址,导致无法找到内核对象,在用户区地址错误会返回报错信息,内核区地址错误是直接蓝屏的,而且这容易产生安全漏洞)。
- 所以windows引入了句柄表的概念,每个进程都有一个句柄表(只有进程有句柄表,简单来说,就是只有EPROCESS这个对象有句柄表)(这个对于深入理解windows运行机制非常重要)
其实句柄表就像一个防火墙,每创建一个内核对象,句柄表就会增加一行,每一行都有一个句柄编号来索引该行,这一行还存放着内核对象的真正地址,当应用层程序需要使用内核对象时,只需要索引句柄,系统就可以自动返回内核对象,这就是windows设计句柄的原因。
要想调用内核对象,使用句柄间接调用内核对象是windows系统唯一的方式。
多进程共享一个内核对象
当两个进程共享一个内核对象时,比如A,B进程共享A内核对象,A内部有一个引用计数器,A内核对象创建时引用计数为1,每多一个程序打开了A内核对象,A的引用计数就会加1,当关闭该内核对象时,引用计数就会减1。当内核对象减为0时,会析构内核对象相关联的程序。但只有两个是例外的,线程内核对象和进程内核对象。
要想移除一个线程,必须同时满足两个条件:
- 引用计数为0
- 线程执行完毕或终止执行。
要想移除进程内核对象必须同时满足两个条件
- 进程内核对象的引用计数为0
- 进程内部的线程全部销毁