内核对象理解

来源:互联网 发布:分布式数据库设计案例 编辑:程序博客网 时间:2024/06/06 16:50

1. 什么是内核对象

内核对象是操作系统为一些系统级的对象(像进程,线程,信号量)维护的一些数据结构。这些数据构保存了与系统级对象相关的系统级信息。例如:所有内核对象都会保存该对象的引用计数。进程对象会保存进程ID。文件对象会保存当前字节偏移量,共享模式,打开模式等。操作系统中所有内核对象对是保存在一块内存空间中,系统上所有的进程都共享这一块内存空间。内核对象使用计数器, 当计数器减为0时,内核释放此内核对象资源。一般创建内核对象都有SECURITY_ATTRIBUTES(安全属性)这个参数,传NULL使用默认安全属性。主要的内核对象有:访问令牌(access token)对象、事件对象、文件对象、文件映射对象、I/O完成端口对象、作业对象、mailslot对象、mutex对象、pipe对象、进程对象、semaphore对象、线程对象、waitable timer对象以及thread pool worker factory对象等等。

2.进程内核对象句柄表

一个进程在初始化时,系统将为它分配一个句柄表(handle table)。这个句柄表仅供内核对象使用,不适用于User或GDI对象。


对于内核对象我们使用它返回的句柄来操作(句柄值实际应该除以4(或右移两位,以忽略Windows操作系统内部使用的最后两位),从而得到在进程句柄表中的真正索引)。

3.关闭内核对象

(1)一进程中一个内核对象只能关闭一次, 关闭后就不能再使用, 如果使用成员变量来存储最好将些句柄赋值为NULL防止关闭到其它内核对象。

(2)如果传给CloseHandle函数的是一个无效的句柄,那么可能发生以下两种情况之一:如果进程是正常运行的,CloseHandle将返回FALSE,而GetLastError返回ERROR_INVALID_HANDLE。如果进程正在被调试,那么系统将抛出0xC0000008异常(“指定了无效的句柄”),便于你调试这个错误。

(3)当你的应用程序运行时,它可能会泄漏内核对象;但当进程终止运行,系统能保证一切都被正确清除。顺便说一下,这适用于所有内核对象、资源(包括GDI对象在内)以及内存块。

4.跨进程边界共享内核对象

有三种方法可以共享内核对象

(1)创建内核对象时通过SECURITY_ATTRIBUTES让对象可以被继承, 再创建进程CreateProcess,将bInheritHandles设置为true继承父进程“可被继承的内核对象”, 然后再将内核对象句柄值传为子进程(创建时命令行参数或者其它IPC)。

(2)创建内核对象命名, 创建内核对象时提供此对象的“名字”, 然后在其它进程中使用Create*,Open*传入相同名字打开相应对象,注意区分Create*和Open*的效果, 前者无论如何都会返回一个内核对象(返回已存在或者创建一个),后者如果未创建有则返回NULL。此共享可以是任意两个进程, 可使用这种共享创建单例程序。

(3)使用DuplicateHandle, 向目标进程复制一个内核对象,然后将此句柄传为目标进程。可以使用DuplicateHandle创建wvud健壮程序,如使用DuplicateHandle复制一个可读写的内核对象到一个只能读的,再将这个对象传给相应函数,防止被修改。




原创粉丝点击