Windows内核对象由内核管理,对象句柄依赖于进程。进程调用函数获取内核对象句柄,并对其操作。
进程内内核句柄表
书中假设了一种Windows的进程内核句柄表的实现:
创建进程的时候,表会初始化为空。
如果创建了一个内核对象,操作系统在该表内寻找一个没有使用过的槽(内存块,类似数组的一个单元),填入地址信息和句柄属性信息。
如果释放一个内核对象,操作系统会对该内核对象引用计数减一,如果计数为零,那么释放该对象的内存。操作系统清除进程内核对象表相应的位置。
如果进程结束,操作系统会在快结束的时候遍历这个表,释放所有的句柄。所以操作系统能保证在进程退出后没有内核对象的泄漏。
内核对象实际内存是在句柄表的一个属性中,创建句柄函数返回的是一个和进程相关的地址,该地址除以4得到句柄表的index,从句柄表这一行取实际内核对象地址。
因此,注意:
1.对句柄做释放操作以后,不要再引用该句柄。因为句柄是内核对象表的槽地址相关,该地址在释放后有2种状态,1是指向空内存,2是被新创建的内涵对象占用,指向新内核对象。
句柄的继承
通过设置参数,在创建内核对象的时候,可以把内核对象设为可继承的。
那么当一个进程创建一个子进程的时候,可以继承该对象句柄,实现的过程是:
子进程初始化句柄表以后会复制父进程表中所有可继承的内核对象,因此子进程和父进程有相同的这部分对象句柄的值。
防止句柄关闭
如果父进程创建了一个子进程,子进程再创建一个孙子进程。有时候父进程希望孙子进程也继承了这个内核对象,并用这个内核对象互相通信。为了防止子进程把这个内核对象关闭,可以设置内核对象属性为“保护关闭”,阻止关闭。