1:什么是内核对象?
内核对象是一组可以被内核创建、识别和操作的数据结构的总称。我的理解是操作系统为了管理资源而定义和实现的一组内部数据,这些数据只能被内核创建和修改。而用户层是无法看到他们的真正内容或者对他们直接进行操作的。我们的用户程序只能通过windows提供的一些api来获得这些内核对象的句柄,从而通过windows本身提供的其他api来间接访问和修改内核对象本身。这就好比windows为内核对象的操作提供了一个类似c++的封装。而一个内核对象的句柄与一个内核对象之间存在着一种间接的引用关系。
内核对象的生命周期是由内核来管理的,用户层的程序只能通过增删引用计数来提醒内核,某个内核对象的使用数为0或者其他,内核一旦发现某个内核对象的使用计数为0时才真正删除这个对象。
内核对象有一个重要的特性是安全访问机制,在创建一个内核对象的时候,可以指定该对象的访问权限。凡是在创建的时候可以指定一个SECURITY_ATTRIBUTES的对象都是一个内核对象。这可以用来区分普通的gdi对象。
2:内核对象的使用
每个进程都有可能创建或者打开若干内核对象,但是前面说过,用户无法获得真正的内核对象的内容,只能通过windows提供的api来创建和访问内核对象。具体表现为一个内核对象句柄(HANDLE)。windows为每个进程都创建一个内核对象句柄表。不同的进程的内核对象句柄表是互相独立的。windows提供的操作内核对象的api需要根据这个句柄表来进一步完成其任务。一般的内核对象句柄的值为真正内核对象在这个句柄表中的索引。windows的api根据句柄表和索引可以找到指向真正的内核对象的指针,及其访问权限和继承标志等信息。而这一切对于用户都是不可见的。不过将来句柄的值也许就不是索引,而是另外一种方式了,这里windows做了一个抽象,只要记住内核对象句柄于一个真正的内核对象之间存在着某种引用关系。
在每个进程中都一个内核句柄表,这也就说明同一个内核对象其在不同的进程中其内核句柄值可能是不一样的。但是内核对象的作用很大程度上就在于能够在进程之间共同访问。这就需要提供一种跨越进程间的共享机制。目前有3种方法可以在进程间共享内核对象:
1:利用对象句柄的继承性;
前面说过每个进程有一个独立的句柄表,当该进程创建子进程的时候,可以指定子进程是否能继承其句柄表中的可继承句柄。如果子进程继承了父进程的对象句柄表,那么意味着同样的句柄值在两个进程中都是可以访问的。关于句柄是否可继承的需要在创建内核对象的时候指定其可继承性。如果将一个不可继承的句柄值传递给子进程使用,子进程的句柄表中并没有这个句柄值的索引,就会发生错误。
2:利用对象的可命名性;
在创建内核对象的时候可以给其指定一个全局的名字。其他进程中则可以通过这个名字获得这个内核对象的句柄。
3:利用windows提供的转换机制;
windows本身提供了将一个进程的内核对象句柄表中一个句柄拷贝到另一个进程的内核对象句柄表中的机制,利用他可以在进程间共享内核对象。