欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《Windows》内核对象

程序员文章站 2022-03-03 20:42:19
...

感谢两位兄弟优秀的总结:
https://blog.csdn.net/Sagittarius_Warrior/article/details/52247917
https://blog.csdn.net/ljianhui/article/details/8171266

内核对象(Kernel Object)是Windows操作系统中的一个核心概念。

本章主要介绍了“内核对象”的公共属性:usage count(使用计数)、Security Descriptor(SD,安全描述符)、进程的内核对象句柄、内核对象的命名空间和垮进程共享内核对象。

1. 什么是内核对象?
1.1 内核对象是操作系统各项资源的抽象;

Windows操作系统采用的是面向对象的编程模式,它将其管理的各项资源,都抽象为各种对象.

如:file、event、process、thread、iocompletationport、mailslot、mutex和 registry 等。

1.2 内核对象是内核代码中的一种数据结构

每个内核对象只是内核分配的一个内存块,并且只能由该内核访问。该内存块是一种数据结构,它的成员负责维护该对象的各种信息。

有些数据成员(如安全性描述符、使用计数等)在所有对象类型中是相同的,但大多数数据成员属于特定的对象类型。例如,进程对象有一个进程I D、一个基本优先级和一个退出代码,而文件对象则拥有一个字节位移、一个共享模式和一个打开模式。

2. 内核对象的属性
2.1 使用计数(usage count)

内核对象由内核所拥有,而不是由进程所有用。

如果进程创建一个内核对象,进程终止运行,内核对象不一定结束

内核通过计数的方式来确定当前有多少进程正在使用该内核对象。

当一个内核对象被创建时,其使用计数设置为1;当另一个进程访问该内核对象时,计数再次加1;当进程终止运行时,内核对象计数减1,

若内核对象计数降为0,内核则回收该内核对象资源。

2.2 安全性

创建任一内核对象时,需要传入一个“PSECURITY_ATTRIBUTES”结构体参数,它代表的就是该内核对象的SD。

SD 实际上表征的是内核对象(系统资源)的访问权限,比如:谁是这个内核对象的 owner,谁有 read/write 权限等等。这里的“谁”,简单来说指的是进程,严格来说,还包括运行进程的用户(common user, administrator and so on)。

大多数时候,应用程序都不关心安全性,一般传“NULL”进去即可。少数如操作注册表、打开IO端口等,可以参考MSDN文档,选择传入的参数。Jeffrey 特意提到 windows 2000 以后,调用 RegOpenKeyEx 时,传入 KEY_ALL_ACCESS 可能(非管理员用户)会失败

3. 进程的内核对象句柄表

应用程序通过句柄来标记内核对象,通过Windows APIs来操作内核对象。

当一个进程被初始化时,系统要为它分配一个句柄表。该句柄表只用于内核对象,不用于用户对象或GDI对象。它只是个数据结构的数组。每个结构都包含一个指向内核对象的指针、一个访问屏蔽和一些标志。

3.1 句柄(handle)

严格来说应称为“进程的内核对象句柄”,它是内核对象在某个具体的进程空间的一种标记。Jeffrey 的原话如下:

“进程在初始化时,系统将为它分配一个句柄表(handle table)”,而句柄实际上是内核对象在进程句柄表中的索引值。

它在winnt.h文件中被定义:

#ifdef STRICT
typedef void *HANDLE;
4. 关闭内核对象

通过调研CloseHandle来结束对该对象的操作:

BOOL CloseHandle(Handle h);

调用CloseHandle函数之后,将不再拥有对该内核对象的访问权。

当进程终止运行时,系统自动扫描进程的句柄表。。如果该表拥有任何无效项目(即在终止进程运行前没有关闭的对象),系统将关闭这些对象句柄。如果这些对象中的任何对象的使用计数降为0,那么内核便撤消该对象。

5. 垮进程共享内核对象
5.1 对象句柄继承
  • 对象之间具有父子关系;
  • 内核对象设置了可继承属性;
  • 在创建子进程时,存在的内核对象才能被继承;

父进程在创建子进程时,需要遍历父进程的句柄表,对于找到的包含有效可继承的句柄,系统会将该句柄拷贝到子进程的相同句柄表索引下,该句柄在父进程和子进程的句柄表中的位置完全相同。

5.2 内核对象命名

备注:Windows没有提供专门的机制来保证内核对象指定的名称是唯一的。

5.3 复制句柄对象