Windows核心编程:(一)内核对象

一:何为内核对象


      每个内核对象都只是一个内存块,它由操作系统内核分配,并只能由操作系统内核访问。这个内存块是一个数据结构,其成员维护着与对象相关的信息。


二:使用计数


     每个内核对象都包含一个使用计数,初次创建一个对象的时候,其使用计数被设为1.另一个进程获得对现有内核对象的访问后,使用计数就会递增;进程终止,操作系统内核自动递减打开的所有内核对象的使用计数。若使用计数变为0,则操作系统内核就会销毁该对象。


三:进程内核对象句柄表(一个指向内核对象的指针,一个访问掩码,一些标志)


      一个进程在初始化时,系统将为它分配一个句柄表。这个句柄表仅供内核对象使用,不适用于用户对象或GDI对象。一个进程首次初始化的时候,其句柄表为空。当进程的一个线程调用一个会创建内核对象的函数时,内核将为这个对象分配并初始化一个内存块,然后扫描进程的句柄表,查找一个空白的记录项,并对其初始化。(指针成员会被设置成内核对象的数据结构内部内存地址,访问掩码被设置成拥有完全访问权限,标志也会被设置)


      用于创建内核对象的任何函数都会返回一个与进程相关的句柄,这个句柄可由同一个进程中运行的所有线程使用。系统用索引来表示内核对象的信息保存在进程句柄表中的具体位置,要得到实际的索引值,句柄值实际应该除以4。由于句柄值实际是作为进程句柄表的索引来使用的,所以这些句柄是与当前这个进程相关的,无法供其他进程使用。


     调用函数创建一个内核对象时,若调用失败,那么返回的句柄值通常为0,即为第一个有效的句柄值为4.


四:关闭内核对象
      在CloseHandle函数返回之前,会清除进程句柄表中对应的记录项—这个句柄现在对我们的进程来说是无效的,无论内核对象是否销毁,这个清除过程都会发生。


      当进程终止时,系统能保证一切都被正确的清除,这适用于所有内核对象,资源以及内存块。进程终止时,系统会确保我们的进程不会留下任何东西。


五:进程共享内核对象
      (1)使用对象句柄继承:
        只有在进程之间有一个父子关系的时候,才可以使用对象句柄继承。父进程有一个或多个内核对象句柄可以使用,而且父进程决定生成一个子进程,并允许子进程访问父进程的内核对象。


        首先,当父进程创建一个内核对象时,父进程必须向系统指出它希望这个对象的句柄是可以继承的(可将对应记录项的是否继承的标志位置1);其次由父进程生成子进程,指定其中的一个参数bInheritHandles参数为TRUE,子进程就会继承父进程的“可继承的句柄”值。传递TRUE时,操作系统会创建新的子进程,但不允许子进程立即执行它的代码。系统为子进程创建一个新的,空白的进程句柄表;然后会遍历父进程的句柄表,对它的每一个记录进行检查,凡是包含一个有效的“可继承的句柄”的项,都会被完整地复制到子进程的句柄表。在子进程的句柄表中,复制项的位置与它在父进程句柄表中的位置是完全一样的,系统还会递增内核对象的使用计数。


       内核对象的内容被保存在内核地址空间中—系统上运行的所有进程都共享这个空间。对32位系统,是ox80000000到oxFFFFFFFF之间的内存空间,对64位系统,是0x00000400'00000000到0xFFFFFFFF'FFFFFFFF之间的内存空间。对象句柄的继承只会在生成子进程的时候发生。
      (2)为对象命名
        对象命名都共享同一个命名空间,即使它们的类型并不相同。
         
        HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("JeffObj"));
        HANDLE hSem = CreateSemaphore(NULL, 1, 1, TEXT("JeffObj"));
        第二个函数肯定会调用失败。
        以此种方式共享对象的方法:
 HANDLE hMutexProcessA = CreateMutex(NULL, FALSE, TEXT("JeffMutex"));   进程A创建一个新的互斥量内核对象,后来某个进程B(B不一定是A的子进程)执行以下代码:
 HANDLE hMutexProcess = CreateMutex(NULL, FALSE, TEXT("JeffMutex")); 系统查看是否存在一个名为“JeffMutex”的内核对象。若存在,内核接着检查对象的类型,若相同则接着执行一次安全检查,若肯定,系统就会在进程B的句柄表中查找一个空白的记录项,并将其初始化为指向现有的内核对象。若对象的类型不匹配,或拒绝访问,则会失败。


     (3)复制对象句柄
             使用DuplicateHandle函数,原型如下:
       
           BOOL DuplicateHandle(
                     HANDLE hSourceProcessHandle,
                     HANDLE hSourceHandle,
                     HANDLE hTargetProcessHandle,
                     HANDLE phTargetHandle,
                     DWORD dwDesiredAccess,
                     BOOL bInheritHandle,
                     DWORD dwOptions          
);
这个函数获得一个进程的句柄表中的一个记录项,然后在另一个进程的句柄表中创建这个记录项的一个副本。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值