Windows核心编程笔记——(3)内核对象

每个内核对象都只是一个内存块,它由操作系统内核分配,并只能由操作系统内核访问,这个内存块是一个数据结构,其成员维护着于对象相关的信息。少数成员是所有对象都有的,像安全描述符和使用计数等;大多数成员是特有的,像进程对象的进程ID,文件对象的字节偏移量。
由于内核对象的数据结构只能由操作系统内核访问,所以应用程序不能再内存中定位这些数据结构并直接更改其内容。所以Windows提供了一组函数,让应用程序可以操作这些内核对象,调用一个会创建内核对象的函数后,函数会返回一个句柄,为了让操作系统知道我们要对那个内核对象进行操作,我们将这个句柄传给各种Windows函数就可以了。
内核对象是属于操作系统的,而不是进程,所以我们在进程中创建了一个内核对象,然后进程终止,而创建的内核对象在有些情况下(另一个进程正在使用这个对象)是不会被销毁的。那么操作系统怎么判断该不该销毁一个内核对象呢?
每一个内核对象都包含一个使用计数,初次创建的时候这个数为一,再有进程对它访问时,这个数就加一。相对的,有一个对它访问的进程终止,这个使用计数就减一,当这个数为0时系统就自动销毁这个内核对象。
每个内核对象还有一个相同的成员,就是安全描述符,安全描述符描述了谁拥有对象(通常谁创建谁拥有),描述了哪些用户可以访问或使用该对象。
应用程序除了使用内核对象,还需要使用其他的对象(菜饭,窗口,鼠标光标等),这些属于用户/GDI对象,查看创建这个对象的函数是区别该对象是用户/GDI对象还是内核对象最方便的方法。创建内核对象的函数都需要我们传入一个安全属性信息的参数(PSECURITY_ATTRIBUTES),而创建用户/GDI对象的函数就没有。
在一个进程初始化时,系统将为它分配一个只能让内核对象使用的句柄表,它是一个由数据结构组成的数组,每一个数据结构都包含一个指向内核对象的指针,一个访问掩码和一些标志。
一个进程首次初始化时,它的句柄表为空,当进程调用一个可以创建内核对象的函数时,这个内存块就会在句柄表中记录,指针成员会被设置成内核对象的数据结构的内部内存地址,访问掩码将被设置成拥有完全访问权限,标志也会设置。
所有创建内核对象的函数都会返回一个与进程相关的句柄,这个句柄可由同一个进程中运行的所有线程使用。
如果调用一个参数中有内核对象的句柄时,在内部,这个函数会查找进程的句柄表,获得该内核对象的地址,如果传入的句柄是无效的,函数失败GetLastError会返回6.
调用函数创建内核对象时,调用失败会返回0,原因可能时系统内存不够,或者遇到了一个安全问题。
不管用什么方法创建的内核对象,最后我们都要用CloseHandle()结束内核对象,该函数首先会检查句柄表,验证传入的句柄真实存在,如果句柄有效,就把“使用计数”递减。如果使用计数为0,内核对象就被销毁,并从内存中去除。如果句柄不存在CloseHandle函数就返回FALSE,GetLastError函数返回8(指定了无效的句柄)。假如没用CloseHandle函数也不一定发生泄漏内核对象,在应用程序运行时,可能会发生,但当进程终止运行,系统能保证一切都被正确清除。

参考书籍:Windows核心编程第五版

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值