Windows 内核对象


1.      内核对象(keneralobject )概念:操作系统用来管理文件、进程、线程等的内核数据结构,应用程序不能直接访问,必须通过handle来访问

2.      内核对象固定成员变量:每个内核对象至少有一个引用计数(用来决定是否释放内核对象,与com引用计数类似)和一个安全属性对象(用来决定访问权限等)成员变量。

3.      keneral object 与handle 区别: keneral object 是操作系统级别的,handle 是进程级别的,可以认为handle就是进程用来标识keneral object的,进程对handle的操作都是直接作用于keneral object。

4.      每个进程创建时,windows都会为进程初始话一个handletable,此handle table是windows用来隐藏内核对象实现的重要数据结构进程退出时候清理handle table。注意此handletable仅仅适用于内核对象,用户对象或者gdi对象不使用。handle table的 table项可以认为是这样一个数据结构

struct  hanleTableItem

{

      UINT uIndex; //一般值=hanle /4,此项至关重要,可以认为作用于handle有关的函数都是通过查找hanle table的这个值引用pKeneral指向的内核对象进行相应的操作,应用程序对handle的错误操作可能引起的一系列问题可能就是这项值引起的,下文将讲述

     void* pKeneral; //指向内核对象的指针

     DWORD dwAcsee;  //内核对象访问权限。参见下面网址:

http://msdn2.microsoft.com/en-us/library/ms686670.aspx

     BOOL BInheritance; //handle是否可以继承

}

当进程创建一个keneral object(如文件对象),windows查找创建进程的handle表的uIndex如果存在则返回表项的handle,否则就创建一个新的handle并且填充到handle table中。当进程结束清理handle table,如果keneral object引用计数变为0释放内核对象。

5.       调用CloseHanle并不是销毁内核对象而是减少引用计数。具体来说是windows根据handle 值/4查找handle table对应的uIndexhandle 项从handle table .中移除。引用计数为0时候销毁pKeneral指向的keneral object。

6.      上面提到的对handle的函数调用将导致的问题:如果调用CloseHanle函数后没有把相应的handle置为NULL(确保handle不再使用),后续如果程序创建一个handle刚好uIndex正好等于没有置为null的那个handle的uIndex,新的handle类型刚好跟没有置为null的那个handle的类型一样,这下悲剧了,以后对没有置为null的那个handle的操作正常进行,应用程序正常工作,但是程序状态将破坏,而且无法恢复。所以CloseHanle后handle 应该赋值为null。

7.      忘记调用CloseHanle:进程运行过程中可能会造成内存泄露,结束时候清理handle table,根据keneral object的引用计数(与com的)进行正确清理。这条规则适用于所有用户对象。可以用process explore 来查看内存泄漏。http://msdn.microsoft.com/msdnmag/issues/03/01/GDILeaks本文gdi 对象泄漏情况捕捉对项目资源泄漏可能有帮助。

8.        跨进程共享内核对象方法:

<1>使用句柄继承,主要用在父子进程当中。主要用到CreateEvent等创建内核对象的LPSECURITY_ATTRIBUTES参数和CreateProcess函数的  BOOL bInheritHandles参数。  在父子进程中传递handle值方法:命令行传递、ipc 通信机制、环境变量。

<2>使用命名内核对象:此方法最常用。如常用的mutex、file mapping

   使用命名对象的一个隐藏的坑:如果在我们的程序创建一个命名对象之前,当前系统已经跑起来的其他程序已经创建了一个相同名字的对象(即使不是相同类型的内核对象),可能引发问题。

HANDLE hMutex = CreateMutex(NULL. FALSE,"JeffObj");

HANDLE hSem = CreateSemaphore(NULL, 1, 1,"JeffObj"); // hSem为null

DWORD dwErrorCode = GetLastError();//dwErrorCode为E R R O R _I N VA L I D _ H A N D L E。

解决方案:为内核对象使用一个独一无二的命名对象。方法有:使用一个guid、使用专有空间命名(见windows核心编程第三章sington例子,应用程序sington可以参考)

<3>使用Du p l i c a t e H a n d l e.

 

参考资料:

1.      windows 核心编程第三章内核对象

2.      msdn关于CreateEvent的说明

3.      windows 图形编程第三章

                                                                          


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值