第3章 内核对象(1)

3.1 何为内核对象

3.1.1 Windows平台上的3大对象

(1)分类


对象


描述


备注


GUI对象


也叫用户对象,一般是单线程访问,属于线程级的对象,如

加速键表(HACCEL)、插入记号(Caret)、光标(HCURSOR)、桌面(HDESK)、

钩子(HHOOK)、图标(HICON)、菜单(HMENU)、窗口(HWND)、窗口栈(HWINSTA)


句柄值是系统唯一的,即一个进程可以通过该句柄值对另一个进程中的对象进行操作,如发送消息。


GDI对象


如DC、Pen、Font等,一般是单线程访问,属于线程级的对象


句柄值只在进程内有效


内核对象


如进程、线程、文件等,一般允许多进程、多线程访问,因为内核对象有严格的安全机制及多线程访问控制策略,属系统级的对象。


句柄值是表示该内核对象在句柄表里的一个索引(注意,只是个索引值),该句柄值是与进程相关的,同一个对象在不同进程中可能有不同的索引

(2)内核对象——所有者为操作系统内核,而非进程


内核对象


对象名称


句柄

类型


创建函数


销毁函数


Access token


访问令牌


HANDLE


CreateRestrictedToken, DuplicateToken(Ex),

OpenProcessToken,

OpenThreadToken


CloseHandle


Change notification


文件、目录变更通知


HANDLE


FindFirstChangeNotification


FindCloseChangeNotification


Communications

device


串口通信


HANDLE


CreateFile


CloseHandle


Console input


控制台输入


HANDLE


CreateFile,with CONIN$


CloseHandle


Console screen

buffer


控制台输出


HANDLE


CreateFile,with CONOUT$


CloseHandle


Desktop


桌面


HDESK


GetThreadDestop


应用程序无法删除该对象


Event


事件


HANDLE


CreateEvent, CreateEventEx, OpenEvent


CloseHandle


Event log


事件日志


HANDLE


OpenEventLog, RegisterEventSource, OpenBackupEventLog


CloseEventLog


File


文件


HANDLE


CreateFile


CloseHandle, DeleteFile


File mapping


文件映射


HANDLE


CreateFileMapping, OpenFileMapping


CloseHandle


Find file


文件查找


HANDLE


FindFirstFile


FindClose


Heap



HANDLE


HeapCreate


HeapDestroy


I/O completion port


完成端口


HANDLE


CreateIoCompletionPort


CloseHandle


Job


作业


HANDLE


CreateJobObject


CloseHandle


Mailslot


邮槽


HANDLE


CreateMailslot


CloseHandle


Memory resource notification


内存资源通知


HANDLE


CreateMemoryResourceNotification


CloseHandle


Module


模块


HMODULE


LoadLibrary, GetModuleHandle


FreeLibrary


Mutex


互斥


HANDLE


CreateMutex, CreateMutexEx, OpenMutex


CloseHandle


Pipe


管道(命名、匿名)


HANDLE


CreateNamedPipe, CreatePipe


CloseHandle, DisconnectNamedPipe


Process


进程


HANDLE


CreateProcess, OpenProcess, GetCurrentProcess


CloseHandle, TerminateProcess


Semaphore


信标量


HANDLE


CreateSemaphore, CreateSemaphoreEx, OpenSemaphore


CloseHandle


Socket


套接字


SOCKET


socket, accept,WSASocket


closesocket


Thread


线程


HANDLE


CreateThread, CreateRemoteThread, GetCurrentThread


CloseHandle, TerminateThread


Timer


计时器


HANDLE


CreateWaitableTimer, CreateWaitableTimerEx, OpenWaitableTimer


CloseHandle


Update resource


更新资源


HANDLE


BeginUpdateResource


EndUpdateResource


Window station


窗口栈


HWINSTA


GetProcessWindowStation,CreateWindowStation


CloseWindowStation

3.1.2 内核对象的安全性

(1)安全描述符SD(SECURITY_DESCRIPTOR)


字段


描述


UCHAR  Revision


UCHAR  Sbz1


SECURITY_DESCRIPTOR_CONTROL

Control;


一个控制位集合,说明安全描述符的含义或它每个成员


PSID  Owner


拥有者的安全ID


PSID  Group


基本组对象SID


PACL  Sacl


系统访问控制链表,当一个进程常识访问一个安全对象的时候,系统检查对象的 DACL 中的访问控制实体来决定是否赋予访问权限。


PACL  Dacl


DACL指定特殊用户或组的允许或拒绝的访问权限

★程序不需要直接操作安全描述符的内容。Windows API提供设置和返回安全描述符号的函数。另外,有用来创建和初始化一个新对象安全描述符号的函数。

(2)SECURITY_ATTRIBUTES结构体——创建内核对象几乎都要传此参数。


字段


描述


LPVOID nLength


结构体大小


lpSecurityDescriptor


指向安全描述符SD的指针


BOOL bInheritHandle;


是否继承父进程可继承的对象句柄

3.2 进程内核对象句柄表

3.2.1 进程句柄表(Handle Table)的结构

(1)进程句柄表仅供内核对象使用,不适用于用户对象或GDI对象

(2)进程初始化时,句柄表为空,当创建一个内核对象时,加入句柄表的记录项。

(3)进程句柄表的结构


索引


指向内核对象内存块的指针


访问掩码(包含标志位的DWORD)


标志


1


0x????????


0x????????


0x????????


2


0x????????


0x????????


0x????????


……


……


……


……

3.2.2 创建一个内核对象

(1)创建内核对象的函数:如CreateThread、CreateFile、CreateSemaphore等。(在32位系统中,内核对象的内容被保存在0x80000000至0xFFFFFFFF的这个内核地址空间中)

(2)返回值,是个句柄,表示该内核对象的在句柄表中的索引。(注意因句柄表可能会分层,所以该句柄最后两位(共32位)表示该对象在句柄表中所在的层数,因此如果要得到实际的索引值,必将该句柄值右移2位,见《Windows内核原理与实现·潘爱民》,p131图3.4)

(3)创建失败时,返回0(NULL),这也是句柄表中第1个内核对象的索引值为1,而为是0的原因。(注意句柄值是实际的索引值的4倍,所以第1个对象的返回的句柄值是4)。但有些函数的返回值是-1(INVALID_HANDLE_VALUE),如CreateFile,使用时请参考MSDN说明。

(4)调用一个内核对象时,在该函数内部会查找进程的句柄表,获得目标内核对象地址来操作对象的数据结构,如果传入的是一人无效句柄,调用失败。GetLastError将返回ERROR_INVALID_HANDLE。

3.2.3 关闭内核对象

(1)CloseHandle内部发生的事情

①首先检查进程的句柄表,验证传进来的函数该句柄的访问权限

②如果句柄有效,获得该内核对象的内存地址,并将该内核对象的“使用计数”减1

③如果计数变为0,将内核对象销毁。

(2)返回值:


成功


TRUE


失败


当进程是正常运行的,返回FALSE;

当进程正在被调试,返回EEEOR_INVALID_HANDLE,便于调试错误。

(3)CloseHandle的几点说明

①内核对象的生命期可能长于进程的生命期。CloseHandle只是表明这个句柄不再使用了,但内核对象并不一定被销毁(可能被其他线程引用)。无论内核对象是否被销毁,都不要再试图用这个值。当 CloseHanle后,一般要将该值设为NULL。

②如果不小心再次使用这个句柄值来调用内核对象,则将可能发生如下意外情况:

A、当句柄表中的记录项己被完全删除时,会收到一个无效参数的错误报告。

B、当句柄表中的记录项被删除后,该项被新加入的内核对象重新填补,如果新内核对象与旧的内核对象类型不同,则会定位到该对象,但会报错。如果类型相同,这里并不会报错,但应用程序可能出现难于预料的结果,甚至应用程序状态被损坏,而无法恢复。

C、如果该记录未被删除(即,使用计数不为0,说明有其他线程调用),则会继续定位到该对象,但这很不安全。因为我们己经调用CloseHanle了,所以该对象不再受我们的控制,它将在什么时候被销毁,我们并不知道。这时如果这时另一线程也调用CloseHandle,则会出现内核对象被销毁,我们就会引用了一个被销毁的对象,导致程序出错。

④如果忘记调用CloseHandle,在进程运行期间会导致内存泄漏,但程序结束后,该对象仍会被系统正确清除

时间: 2024-10-11 21:52:16

第3章 内核对象(1)的相关文章

Windows核心编程之核心总结(第三章 内核对象)(2018.6.2)

学习目标 第三章内核对象的概念较为抽象,理解起来着实不易,我不断上网找资料和看视频,才基本理解了内核对象的概念和特性,其实整本书给我的感觉就是完整代码太少了,没有多少实践的代码对内容的实现,而且书本给的源码例子,有太多我们不知道的知识,并且这些知识对本章主要内容来说是多余的,所以我们理解起来也非常困难.为了更好的学习这章,我补充了一些辅助性内容.这一章的学习目标:1.Windows会话和安全机制2.什么是内核对象?3.使用计数和安全描述符4.内核对象句柄表5.创建内核对象6.关闭内核对象7.跨进

读书笔记----《windows核心编程》第三章 内核对象1(句柄与安全性)

最近一直没有更新博客,因为一直在想一个问题,内核对象这一章内容很多很重要,自己没有掌握好也没有把握写好这一章,最后还是决定能写多少写多少,一面写一面学,后续学到新的再更新吧; <windows核心编程>提了几种内核对象: 访问令牌对象:与windows的安全性有关,目前不是很懂,了解后再写; 事件对象: Event对象,可跨进程同步; 由CreateEvent创建; 文件对象: File对象,比较常见; 由CreateFile创建; 文件映射对象: 通过文件映射可以方便的操作文件(如同文件数据

第3章 内核对象(2)

3.3 跨进程边界共享内核对象 3.3.1 使用对象句柄继承 (1)对象句柄继承,只发生在进程之间有父子关系的时候(即一个进程而另一个进程CreateProcess起来) (2)内核对象句柄继承的实现 ①父进程必须先指出哪些内核对象句柄是可继承(注意不是内核对象本身的继承,而是内核对象的句柄继承),父进程在创建内核对象时要将SECURITY_ATTRIBUTES的bInheritHandle字段设为TRUE,表示可继承.这时句柄表中相应的记录项的标志位被设为1,否则为0. ②父进程调用Creat

第9章 用内核对象进行线程同步(2)_可等待计时器(WaitableTimer)

9.4 可等待的计时器内核对象——某个指定的时间或每隔一段时间触发一次 (1)创建可等待计时器:CreateWaitableTimer(使用时应把常量_WIN32_WINNT定义为0x0400) 参数 描述 psa 安全属性(如使用计数.句柄继承等) bManualReset 手动重置计时器还是自动重置计时器. ①当手动计时器被触发,所有正在等待计时器的线程都变可为可调度. ②当自动计时器被触发时,只有一个正在等待计数器的线程变为可调度 pszName 对象的名字 (2)也可以打开一个己经存在的

第9章 用内核对象进行线程同步(3)_信号量(semaphore)、互斥量(mutex)

9.5 信号量内核对象(Semaphore) (1)信号量的组成 ①计数器:该内核对象被使用的次数 ②最大资源数量:标识信号量可以控制的最大资源数量(带符号的32位) ③当前资源数量:标识当前可用资源的数量(带符号的32位) (2)信号量的使用规则 ①如果当前资源计数>0,那么信号量处于触发状态,表示有可用资源. ②如果当前资源计数=0,那么信号量处于未触发状态,表示没有可用资源. ③系统绝不会让当前资源计数变为负数: ④当前资源计数绝对不会大于最大资源计数 (3)信号量的用法 (4)相关函数

第9章 用内核对象进行线程同步(4)_死锁(DeadLock)及其他

9.7 线程同步对象速查表 对象 何时处于未触发状态 何时处于触发状态 成功等待的副作用 进程 进程仍在运行的时候 进程终止的时(ExitProcess.TerminateProcess) 没有 线程 线程仍在运行的时候 线程终止的时候(ExitThread.TermimateThread) 没有 作业 作业尚未超时的时候 作业超时的时候 没有 文件 有待处理的I/O请求的时候 I/O请求完成的时候 没有 控制台输入 没有输入的时候 有输入的时候 没有 文件变更通知 文件没有变更的时候 文件系统

JavaScript进阶 - 第8章 浏览器对象

第8章 浏览器对象 8-1 window对象 window对象是BOM的核心,window对象指当前的浏览器窗口. window对象方法: 注意:在JavaScript基础篇中,已讲解了部分属性,window对象重点讲解计时器. 任务 在右边编辑器script标签内补充代码,弹出对话框"欢迎来到慕课网". 定义一个函数,实现打开一个网页,宽为600,高为400. 当点击"点击我,打开新窗口"按钮时,在打开网页. 如果忘记了,可以查看JavaScript基础篇. 代码

《Linux Device Drivers》第十一章 内核的数据类型——note

简介 由于Linux的多平台特性,任何一个重要的驱动程序都应该是可移植的 与内核代码相关的核心问题是应该能够同时访问已知长度的数据项,并充分利用不同处理器的能力 内核使用的数据类型主要被分成三类 类似int这样的标准C语言类型 类似u32这样的有确定大小的类型 像pid_t这样的用于特定内核对象的类型 本章将讨论在什么情况下使用这三种类型以及如何使用 使用标准C语言类型 当我们需要"两个字节的填充符"或者"用四个字节字符串表示的某个东西"时,我们不能使用标准类型,因

Windows API学习---线程与内核对象的同步

前言 若干种内核对象,包括进程,线程和作业.可以将所有这些内核对象用于同步目的.对于线程同步来说,这些内核对象中的每种对象都可以说是处于已通知或未通知的状态之中.这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的.例如,进程内核对象总是在未通知状态中创建的.当进程终止运行时,操作系统自动使该进程的内核对象处于已通知状态.一旦进程内核对象得到通知,它将永远保持这种状态,它的状态永远不会改为未通知状态. 当进程正在运行的时候,进程内核对象处于未通知状态,当进程终止运行的时候,它就变