Windows对象管理

这是本页的一个历史版本,由Low power留言 | 贡献2015年1月21日 (三) 15:33 (对象目录的描述)编辑。这可能和当前版本存在着巨大的差异。

对象管理Windows Executive的一个子系统实现,用于管理Windows资源。 资源包括物理设备、文件、文件目录、注册表条目、正在运行的进程等等。所有子系统访问资源都必须通过对象管理子系统。

体系结构

Windows NT操作系统体系结构中,对象管理子系统管理所有的资源。资源被表示为对象。对象管理子系统保持着对每个对象的引用计数。任何访问对象的系统调用都必须通过对象管理子系统。

对象可分为即内核对象(Kernel objects)与Executive objects. 内核对象表示一些基本资源,如物理设备、同步服务等等。用户态的程序不能访问内核对象。[1]用户态的系统服务与应用程序使用Executive objects, 这是Windows Executive对外暴露的对象, 用来封装了一个或多个内核对象。 Executive objects还用于实现了NT子系统或POSIX子系统的一些功能。

当对象创建时,指向对象实例的索引也被创建,称为句柄(handle)[2]。对象管理子系统使用句柄与命名两种方式管理对象实例。句柄在一个进程内部是共享的,但在进程之间不是直接可复用,需要特别方式在进程间传递对象句柄。一个进程任何时刻最多拥有224,即大约16,000,000个句柄。句柄按照对象的分类可分为文件句柄、事件句柄、进程句柄等。一个进程对一个对象可以有多个句柄,以便按照不同权限来访问对象。

Windows NT暴露的Executive object的类型包括:

类别 描述 创建句柄函数 摧毁句柄函数 未通知状态 通知状态 等待成功的副作用
进程 线程的集合,拥有共同的虚拟内存空间与控制信息 CreateProcess, OpenProcess, GetCurrentProcess CloseHandle, TerminateProcess 进程仍然活动时 进程终止运行时
(TerminateProcess
ExitProcess)
线程 进程内部,执行程序的实体。 线程仍然活动时 线程终止运行时
(TerminateThread
ExitThread)
作业 进程的集合 CreateJobObject CloseHandle 当作业的时间尚未结束时 当作业的时间已经结束时
文件 一个打开的计算机文件或I/O设备。 CreateFile CloseHandle, DeleteFile 当I/O请求正在处理时 当I/O请求处理完毕时
文件映射对象 一块内存区域,映射到一个文件。
访问令牌 一个对象的访问权。 CreateRestrictedToken, DuplicateToken, DuplicateTokenEx, OpenProcessToken, OpenThreadToken CloseHandle
事件 封装了某些信息的一个对象,用于通知某些进程。 CreateEvent, CreateEventEx, OpenEvent CloseHandle ResetEvent,或PulseEvent,或自动重置事件等待成功 当调用SetEvent,或PulseEvent 自动重置事件等待成功后将自动reset
信号量 用于串行化访问某些资源的对象。 CreateSemaphore, CreateSemaphoreEx, OpenSemaphore CloseHandle 当数量<=0时 当数量>0时 (ReleaseSemaphore) 数量递减1
互斥锁 用于串行化访问某些资源的对象。 CreateMutex, CreateMutexEx, OpenMutex CloseHandle 被其他线程拥有时 未被其他线程拥有时 等待成功的线程获得CPU所有权
临界区域 使得指定的代码段被串行执行 被其他线程拥有时(试图EnterCriticalSection) 未被其他线程拥有时(LeaveCriticalSection) 等待成功的线程获得CPU所有权
定时器 按照固定时间间隔通知某些进程的对象。 CloseHandle CancelWaitableTimer或自动重置定时器等待成功 当时间到时 (SetWaitableTimer) 自动重置定时器等待成功将reset
Timer queue
Timer-queue timer
键值 Windows注册表条目的键值。
桌面 包含GUI元素的一个逻辑显示面。 GetThreadDesktop 用户不能删除这个对象
剪贴板 用于其它对象的临时存储空间。
WindowStation 包含一些桌面对象、一块剪贴板对象、以及其他对象的对象。 GetProcessWindowStation 用户不能删除这个对象
符号链接 对其他对象的引用
事件日志 OpenEventLog, RegisterEventSource, OpenBackupEventLog CloseEventLog
Change notification FindFirstChangeNotification FindCloseChangeNotification
Communications device CreateFile CloseHandle
控制台输入 CreateFile, with CONIN$ CloseHandle 不存在任何输入时 存在输入时
Console screen buffer CreateFile, with CONOUT$ CloseHandle
文件修改通知 FindFirstChangeNotification CloseHandle 没有任何文件被修改 当文件系统发现修改时 重置通知
Heap HeapCreate HeapDestroy
I/O completion port CreateIoCompletionPort CloseHandle
Mailslot CreateMailslot CloseHandle
Memory resource notification CreateMemoryResourceNotification CloseHandle
模块 LoadLibrary, GetModuleHandle FreeLibrary
管道 CreateNamedPipe, CreatePipe CloseHandle, DisconnectNamedPipe
Socket socket, accept closesocket
Update resource BeginUpdateResource EndUpdateResource

与内核对象相对,还有用户对象与GDI对象。

  • 用户对象:每个对象仅有一个句柄,句柄不能复制或继承,不能引用其他用户会话中的进程的用户句柄。任何进程只要有对某个用户句柄访问权限,既可以访问该用户对象。一个进程最多有65536个用户对象句柄。用户对象包括:Accelerator table、Caret、Cursor、DDE conversation、Hook、Icon、Menu、Window、Window position。[3]
  • GDI对象:每个对象仅有一个句柄,句柄为进程私有。一个进程最多有65536个GDI对象句柄。GDI对象包括:Bitmap、Brush、DC、Enhanced metafile、Enhanced metafile DC、Font、Memory DC、Metafile、Metafile DC、Palette、Pen and extended pen、Region.[4]

对象结构

每个被对象管理子系统所管理的对象,包含头部和体部。头部是对象管理子系统使用的状态信息。体部是对象相关的数据与暴露的服务。

对象头部对外暴露的信息称为Properties, 包括:

  • Object Name,用来标识对象
  • Object Directory,对象所属类别
  • Security Descriptors,对象的访问权限,一般在创建对象时传入,大多数时候传入值为NULL,表示采用默认安全属性。
  • Quota Charges,对象的资源使用信息
  • Open handle count,打开的句柄计数
  • Open handle list,活动引用的进程列表
  • Reference count,活动引用进程的计数
  • Type,用来标识对象体部结构

对象管理子系统所管理的对象必须提供下属服务:

  • Close,关闭对象的一个句柄
  • Duplicate,创建对象的另一个句柄,用来给另一个进程共享访问该对象
  • Query object,获得对象的属性与性质等信息
  • Query security,得到对象的安全描述信息
  • Set security,改变对象的安全访问信息
  • Wait,同步一个或多个对象,通过特定事件。

同一类型的对象具有一些相同的属性,如类型名、是否分配在非分页内存、访问权限、同步信息等。这些由一个类型对象(type object)来表示。所有同一类型的对象实例共享这唯一的类型对象。 可以创建新的对象类型,这通过把一个对象的属性作为对外暴露的状态,把其方法作为对外暴露的服务来实现。

对象名(Object name)是一个对象的描述性标识。对象管理子系统保持一个已经用于表示对象的名字列表,映射每个名字到对象实例。实际上大多数访问对象的行为是通过句柄;通过对象名来查找对象实例仅发生在创建对象时、跨进程共享一个对象时。

Object directories用于按照类型来分类对象。预定义的Object directories包括:

  • \?? (Win32 设备名,其中只有符号链接)
  • \BaseNamedObjects (互斥、事件、信号量、可等待计时器和段对象)
  • \Callback (回调函数)
  • \Device (设备)
  • \Drivers
  • \FileSystem
  • \KnownDlls
  • \Nls (language tables)
  • \ObjectTypes (对象类型对象)
  • \RPC ControlsRPC端口)
  • \Security (安全子系统对象)
  • \Windows (窗口子系统对象)

对象属于命名空间(Namespace). 每个用户会话(user session)是一个名字空间。这使得多个客户同时运行一个应用程序而不会发生干扰。在所有名字空间共享的对象属于GLOBAL命名空间。例如,在Global命名空间中创建一个事件,名字叫CSAPP:

CreateEvent( NULL, FALSE, FALSE, "Global\\CSAPP" );

全局命名空间使得多个客户会话间的进程可以通信。例如,一个客户/服务器使用互斥锁来同步,服务器模块在全局命名空间创建一个互斥锁对象,然后客户进程使用"Global\"前缀来打开这个互斥锁对象。 客户进程可以明示使用 "Local\"前缀来在客户会话命名空间中创建对象。[5]

OBJECT_ATTRIBUTES结构:

typedef struct _OBJECT_ATTRIBUTES{
 ULONG Length;
 HANDLE RootDirectory;
 PUNICODE_STRING ObjectName;
 ULONG Attributes;
 PSECURITY_DESCRIPTOR SecurityDescriptor;
 PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
}

Attributes成员域可以是0,或下述标志的组合:

OBJ_INHERIT
OBJ_PERMANANT
OBJ_EXCLUSIVE
OBJ_CASE_INSENSITIVE
OBJ_OPENIF
OBJ_OPENLINK
OBJ_KERNEL_HANDLE

参加

参考文献

  1. ^ Kernel objects
  2. ^ 每个进程中都存在一个句柄表,列出了所有本进程内可以使用的句柄。句柄表实际上是一个数组,每个数组元素为一个结构,包含一个指向内核对象的指针、访问掩码、继承标识等。句柄实际上是进程句柄表数组的下标。因此句柄是进程私有的。
  3. ^ User Objects
  4. ^ GDI Objects
  5. ^ Kernel object namespaces

外部链接