![]()
1.每个内核对象都只是一个内存块,它由操作系统内核分配,并只能由操作系统内核访问。这个内存块是一个数据结构,其成员维护着与对象相关的信息。
2.调用一个会创建内核对象的函数后,函数会返回一个句柄,它标识了所创建的对象。在32位windows进程中,句柄是一个32位的值,在64位windows进程中,则是一个64位的值。
3.为了增强操作系统的可靠性,这些句柄值是与进程相关的,不可以直接跨进程使用。
4.内核对象的所有者是操作系统内核,而非进程,在进程内创建的内核对象在进程终止时不一定会被销毁。大多数情况下是会被销毁的,但是假如另一个进程正在使用我们的进程创建的内核对象,那么在其他进程停止使用它之前是不会被销毁的。
5.操作系统的内核知道当前有多少个进程正在使用一个特定的内核对象,因为每个对象都包含一个使用计数。使用计数是所有内核对象类型都有的一个数据成员。初次创建 一个对象的时候,使用计数被设为1,另一个进程获得对现有内核对象的访问后,使用计数就会递增。进程终止运行后,操作系统内核将自动递减此进程仍然打开的所有内核对象的使用计数。一旦使用计数变成0,操作系统内核就会销毁该对象。可以保证系统中不存在没有被任何进程引用的内核对象。
6.内核对象可以用一个安全描述符来保护。安全描述符描述了谁拥有对象,哪些组和用户被允许/拒绝访问或使用此对象。
7.一个进程在初始化时,系统将为它分配一个句柄表。这个句柄表仅供内核对象使用。

8.系统用索引来表示内核对象的信息保存在进程句柄表中的具体位置,要得到实际的索引值,句柄值实际应该除以4(忽略Windows操作系统内部使用的最后两位)。
9.CloseHandle() 会先检查句柄是否有效,如果有效,系统就将获得内核对象的数据结构的地址,并将结构中的“使用计数”成员递减,如果变成0,则内核对象将被销毁,并从内存中出去。
10.在CloseHandle() 函数返回之前,它会清除进程句柄表中对应的记录项,无论内核对象当前是否销毁,这个清楚过程都会发生。
![]()
11.三种不同的机制允许进程共享内核对象:使用对象句柄继承,为对象命名,复制对象句柄。
使用对象句柄继承
1.只有在进程之间有一个父子关系的时候,才可以使用对象句柄继承。句柄表中的每个记录项都有一个指明句柄是否可以继承的标志位,如果PSECURUTY_ATTRIBUTES传入的参数时NULL,则返回的句柄是不可继承的,这个标志位为0,将bInheritHandle成员设置为TRUE,则导致这个标志位被设为1。
2.例如在CreateProcess函数的bInheritHandles参数的值是TRUE,系统会遍历父进程的句柄表,对它的每一个记录项进行检查,凡是包含一个有效的"可继承的句柄"项,都会被完整地复制到子进程的句柄表。而且在子进程的句柄表中,复制项的位置与它在父进程句柄表中的位置是完全一样的。也意味着:在父进程和子进程中,对一个内核对象进行标识的句柄值是完全一样的。同时系统还会递增内核对象的使用计数。同理,孙进程也会继承这个内核对象句柄。
3.对象句柄的继承只会发生在生成子进程的时候,假如父进程后来又创建了新的内核对象,那么子进程是不会继承这些新的句柄。
4.子进程并不知道自己继承了任何句柄。
5. SetHandleInformation()函数可以用来改变内核对象句柄的继承标志,GetHandleInformation()可以获得指定句柄的状态标志。
为对象命名
1.所有对象都共享同一个命名空间,即使它们类型并不相同。
2.如果进程A中已经创建了一个命名对象(即使是不可继承的),那么在进程B中以同样的名字来创建命名对象时,系统会首先查看是否存在相同名称的内核对象,如果确实存在,内核接着检查对象的类型,如果类型不匹配就会返回NULL。如果匹配则系统接着执行一次安全检查,严重调用者是否拥有对该对象的完全访问权限,如果拥有则系统会在进程B的句柄表中查找一个空白记录项,并将其初始化为指向现有的内核对象。如果被拒绝访问,则失败。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-68237-1.html
感谢奶茶的歌声